Partio is a summarization, chunking, and embeddings generation virtualization platform
4.4K
Partio is a multi-tenant RESTful platform that accepts semantic cells (text, lists, tables, images, code, and more) with a chunking and embedding configuration, and returns chunked text with computed embeddings. Partio also supports optional LLM-powered summarization of cells before chunking and embedding. Partio lets you define endpoints (provider + model + chunking policy) and call them consistently across tenants and applications, so you can focus on building your product instead of managing chunking and embedding infrastructure.
Send a semantic cell with a chunking config:
curl -X POST http://localhost:8400/v1.0/process \
-H "Authorization: Bearer partioadmin" \
-H "Content-Type: application/json" \
-d '{
"Type": "Text",
"Text": "Partio centralizes your chunking and embedding workflow. It accepts semantic cells and returns chunks with embeddings.",
"ChunkingConfiguration": {
"Strategy": "SentenceBased"
},
"EmbeddingConfiguration": {
"EmbeddingEndpointId": "eep_abc123"
}
}'
Get back chunks with computed embeddings:
{
"Text": "Partio centralizes your chunking and embedding workflow. It accepts semantic cells and returns chunks with embeddings.",
"Chunks": [
{
"Text": "Partio centralizes your chunking and embedding workflow.",
"Labels": [],
"Tags": {},
"Embeddings": [0.0123, -0.0456, 0.0789, "... (384 floats for all-minilm)"]
},
{
"Text": "It accepts semantic cells and returns chunks with embeddings.",
"Labels": [],
"Tags": {},
"Embeddings": [0.0321, -0.0654, 0.0987, "... (384 floats for all-minilm)"]
}
]
}
A semantic cell is a typed unit of content from a parsed document. Rather than sending raw text, you send structured content that Partio can chunk intelligently based on its type:
{
"Type": "Text | List | Table | Code | Image | Hyperlink | Meta | Binary",
"Text": "string (for Text, Code, Hyperlink, Meta, Image, Binary)",
"OrderedList": ["item 1", "item 2"],
"UnorderedList": ["item a", "item b"],
"Table": [["id", "name"], ["1", "Alice"], ["2", "Bob"]],
"Labels": ["source:readme", "section:intro"],
"Tags": { "page": "3", "heading": "Introduction" }
}
Each type unlocks different chunking strategies. Text can be split by tokens, sentences, or paragraphs. Lists can be chunked whole or per-entry. Tables can be chunked by row, row groups, key-value pairs, or as a whole. Labels and tags are echoed back on each chunk for downstream traceability.
Partio requires an embedding provider to generate embeddings. Out of the box, Partio is configured to use Ollama with the all-minilm model.
When using Docker Compose (recommended), Ollama is included automatically — just pull a model after starting the services (see below).
When running from source or via Docker (server only), install Ollama separately:
http://localhost:11434)ollama pull all-minilmThe fastest way to run Partio with all components. The Compose file includes Partio server, dashboard, and a local Ollama instance with persistent model storage.
git clone https://github.com/jchristn/partio.git
cd partio/docker
docker compose up -d
Pull the default embedding model:
# Bash / macOS / Linux
curl http://localhost:11434/api/pull -d '{"name": "all-minilm"}'
# Windows Terminal (cmd)
curl http://localhost:11434/api/pull -d "{\"name\": \"all-minilm\"}"
| Component | URL | Docker Image |
|---|---|---|
| Server | http://localhost:8400 | jchristn77/partio-server |
| Dashboard | http://localhost:8401 | jchristn77/partio-dashboard |
| Ollama | (internal via shared network) | ollama/ollama |
The Ollama container shares the server's network namespace, so the default localhost:11434 endpoint works without any configuration changes. Models are persisted in a Docker volume across restarts.
Default admin API key: partioadmin
docker run -d -p 8400:8400 jchristn77/partio-server
Requires the .NET 10 SDK.
git clone https://github.com/jchristn/partio.git
cd partio/src
dotnet build
dotnet run --project Partio.Server
On first startup, Partio creates a partio.json settings file and initializes the database with these defaults:
Caution
**Local development only.** Change all default credentials before any production or shared deployment.
Resource ID Details Tenant defaultDefault Tenant User defaultadmin@partio / password (admin) Credential defaultBearer token defaultAdmin API Key — partioadmin
All endpoints use JSON and require an Authorization: Bearer {token} header unless otherwise noted. See REST_API.md for the full API reference. A Postman collection is also included in the repository.
| Method | Route | Auth | Description |
|---|---|---|---|
HEAD | / | No | Health check |
GET | / | No | Health status |
GET | /v1.0/health | No | Health (JSON) |
GET | /v1.0/whoami | Yes | Caller identity |
| Method | Route | Description |
|---|---|---|
POST | /v1.0/process | Process a single semantic cell |
POST | /v1.0/process/batch | Process multiple semantic cells |
| Method | Route | Auth | Description |
|---|---|---|---|
GET | /v1.0/endpoints/embedding/{id}/health | Yes | Health status for one endpoint |
GET | /v1.0/endpoints/embedding/health | Yes | Health status for all endpoints |
Each admin resource supports PUT (create), GET (read), PUT /{id} (update), DELETE /{id}, HEAD /{id} (exists), and POST /enumerate (list).
| Resource | Route Prefix | ID Prefix |
|---|---|---|
| Tenants | /v1.0/tenants | ten_ |
| Users | /v1.0/users | usr_ |
| Credentials | /v1.0/credentials | cred_ |
| Endpoints | /v1.0/endpoints/embedding | eep_ |
| Completion Endpoints | /v1.0/endpoints/completion | cep_ |
| Request History | /v1.0/requests | req_ |
curl -X POST http://localhost:8400/v1.0/process \
-H "Authorization: Bearer partioadmin" \
-H "Content-Type: application/json" \
-d '{
"Type": "Text",
"Text": "Partio virtualizes your chunking and embedding workflow.",
"ChunkingConfiguration": {
"Strategy": "FixedTokenCount",
"FixedTokenCount": 256
},
"EmbeddingConfiguration": {
"EmbeddingEndpointId": "eep_YOUR_ENDPOINT_ID",
"L2Normalization": false
}
}'
curl -X POST http://localhost:8400/v1.0/process/batch \
-H "Authorization: Bearer partioadmin" \
-H "Content-Type: application/json" \
-d '[
{ "Type": "Text", "Text": "First document to embed." },
{ "Type": "Text", "Text": "Second document to embed." }
]'
| Strategy | Description |
|---|---|
FixedTokenCount | Split content into chunks of a fixed token count (uses cl100k_base encoding). Configurable overlap via OverlapCount or OverlapPercentage. |
SentenceBased | Split at sentence boundaries. |
ParagraphBased | Split at paragraph boundaries. |
WholeList | Treat an entire list as a single chunk. |
ListEntry | Each list entry becomes its own chunk. |
Row | Each table data row as space-separated values (no headers). |
RowWithHeaders | Each table data row as a markdown table with headers prepended. |
RowGroupWithHeaders | Groups of N table rows with headers (configurable via RowGroupSize, default 5). |
KeyValuePairs | Each table row as key-value pairs (e.g. "id: 1, firstname: george, lastname: bush"). |
WholeTable | Entire table as a single markdown table chunk. |
RegexBased | Split at boundaries defined by a user-supplied regular expression (RegexPattern). Works with any content type. |
Supported content types: Text, Code, Hyperlink, Meta, Lists (ordered/unordered), Tables, Binary, and Image.
Not all strategies work with all content types. The generic strategies (FixedTokenCount, SentenceBased, ParagraphBased, RegexBased) work with any type. List strategies (WholeList, ListEntry) only work with List. Table strategies (Row, RowWithHeaders, RowGroupWithHeaders, KeyValuePairs, WholeTable) only work with Table. The API returns 400 Bad Request if an incompatible strategy is used.
| Strategy | Text | Code | Hyperlink | Meta | List | Table | Binary | Image | Unknown |
|---|---|---|---|---|---|---|---|---|---|
| FixedTokenCount | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| SentenceBased | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| ParagraphBased | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| RegexBased | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| WholeList | Y | ||||||||
| ListEntry | Y | ||||||||
| Row | Y | ||||||||
| RowWithHeaders | Y | ||||||||
| RowGroupWithHeaders | Y | ||||||||
| KeyValuePairs | Y | ||||||||
| WholeTable | Y |
Partio is configured via partio.json, created automatically on first run.
{
"Rest": {
"Hostname": "0.0.0.0",
"Port": 8400,
"Ssl": false
},
"Database": {
"Type": "Sqlite",
"Filename": "./partio.db"
},
"Logging": {
"ConsoleLogging": true,
"FileLogging": true,
"LogDirectory": "./logs/",
"LogFilename": "partio.log",
"MinimumSeverity": 0
},
"RequestHistory": {
"Enabled": true,
"Directory": "./request-history/",
"RetentionDays": 7,
"CleanupIntervalMinutes": 60
},
"AdminApiKeys": ["partioadmin"],
"DefaultEmbeddingEndpoints": [
{
"Model": "all-minilm",
"Endpoint": "http://localhost:11434",
"ApiFormat": "Ollama"
}
]
}
| Type | Config Value | Notes |
|---|---|---|
| SQLite | Sqlite | Default. Zero configuration, file-based. |
| PostgreSQL | Postgresql | Set Hostname, Port, DatabaseName, Username, Password. |
| MySQL | Mysql | Set Hostname, Port, DatabaseName, Username, Password. |
| SQL Server | SqlServer | Set Hostname, Port, DatabaseName, Username, Password. |
using Partio.Sdk;
using Partio.Sdk.Models;
using PartioClient client = new PartioClient("http://localhost:8400", "partioadmin");
SemanticCellResponse? response = await client.ProcessAsync(new SemanticCellRequest
{
Type = "Text",
Text = "Hello world",
EmbeddingConfiguration = new EmbeddingConfiguration { EmbeddingEndpointId = "eep_YOUR_ENDPOINT_ID" }
});
from partio_sdk import PartioClient
with PartioClient("http://localhost:8400", "partioadmin") as client:
result = client.process({
"Type": "Text",
"Text": "Hello world",
"ChunkingConfiguration": {"Strategy": "FixedTokenCount", "FixedTokenCount": 256},
"EmbeddingConfiguration": {"EmbeddingEndpointId": "eep_YOUR_ENDPOINT_ID"}
})
import { PartioClient } from './partio-sdk.js';
const client = new PartioClient('http://localhost:8400', 'partioadmin');
const result = await client.process({
Type: 'Text',
Text: 'Hello world',
ChunkingConfiguration: { Strategy: 'FixedTokenCount', FixedTokenCount: 256 },
EmbeddingConfiguration: { EmbeddingEndpointId: 'eep_YOUR_ENDPOINT_ID' }
});
Partio.Core - Models, settings, database, chunking engine, embedding clients
Partio.Server - REST API server, authentication, request history
dashboard/ - React/Vite admin dashboard
sdk/csharp/ - C# SDK and test harness
sdk/python/ - Python SDK and test harness
sdk/js/ - JavaScript SDK and test harness
docker/ - Docker Compose setup and default configuration
| Image | Description | Default Port |
|---|---|---|
jchristn77/partio-server | Partio REST API server | 8400 |
jchristn77/partio-dashboard | React admin dashboard (Nginx) | 8401 |
Both images support linux/amd64 and linux/arm64.
# Server
build-server.bat [tag]
# Dashboard
build-dashboard.bat [tag]
partioadmin) and default user password immediately. Use the admin API to create tenant-scoped credentials with limited access.RetentionDays and CleanupIntervalMinutes in partio.json to control disk usage. Set RequestHistory.Enabled to false to disable entirely.Verify that port 8400 (server) and 8401 (dashboard) are not in use by another process. You can change the port in partio.json under Rest.Port.
Ensure you are passing the Authorization: Bearer {token} header. The default admin API key is partioadmin. If using a credential token, verify the credential, its associated user, and the tenant are all marked as active.
curl http://localhost:11434/api/pull -d '{"name": "all-minilm"}'curl http://localhost:11434/api/pull -d "{\"name\": \"all-minilm\"}"localhost inside the container is not the host machine; use host.docker.internal or the container network address instead.all-minilm for Ollama).ApiFormat is set correctly (Ollama or OpenAI).The dashboard connects to the server URL you enter on the login screen. If both are running in Docker, use http://localhost:8400 from the browser (the dashboard runs client-side). If the server is on a different host, use that host's address.
Verify Hostname, Port, DatabaseName, Username, and Password in partio.json under Database. Ensure the target database server is running and accessible from the Partio server's network.
Adjust FixedTokenCount in your ChunkingConfiguration. The server caps chunk size to the model's context window automatically. Use OverlapCount or OverlapPercentage with OverlapStrategy: "SlidingWindow" for overlapping chunks.
Request history bodies are stored on the filesystem under the configured RequestHistory.Directory. Reduce RetentionDays or CleanupIntervalMinutes in partio.json, or set RequestHistory.Enabled to false to disable logging entirely.
Set the following in partio.json and restart the server:
{
"Logging": { "MinimumSeverity": 0 },
"Debug": {
"Authentication": true,
"Exceptions": true,
"Requests": true,
"DatabaseQueries": true
}
}
Logs are written to ./logs/ by default.
Have a question, found a bug, or want to request a feature?
When filing an issue, please include:
v0.2.0, or the Docker image tag)./logs/Refer to CHANGELOG.md for the full version history.
MIT © 2026 Joel Christner
Content type
Image
Digest
sha256:71414cb26…
Size
132.3 MB
Last updated
about 7 hours ago
docker pull jchristn77/partio-server