solid-knowledge-ai
Solid Knowledge AI
Un asistente de conocimiento documental de múltiples fuentes impulsado por un agente LangGraph autorreflexivo. Ingiere PDF + Markdown + páginas web en un único almacén vectorial, y luego responde preguntas mediante un agente que evalúa su propia recuperación y verifica su propia respuesta para fundamentarla — reintentando con una consulta reescrita cuando alguna de las comprobaciones falla, y negándose a inventar cuando no puede fundamentar una respuesta. Rastreado con Langfuse, probado en calidad con DeepEval y expuesto a través de MCP.
Construido para mostrar el desarrollo agéntico: LangGraph · LiteLLM · ChromaDB · MCP · Langfuse · DeepEval.
Por qué esto no es "solo RAG"
El agente es un bucle RAG correctivo / autorreflexivo, no una cadena lineal retrieve → generate:
question
│
▼
route ──chitchat/out_of_scope──▶ generate ──▶ END
│ kb
▼
retrieve ──▶ grade_docs ──irrelevant (rewrite query, retry)──▶ retrieve
│ relevant
▼
generate ──▶ self_check ──ungrounded (retry)──▶ retrieve
│ grounded / budget spent
▼
answer + citations (or an honest "I don't know")route — omite la recuperación en preguntas de charla trivial / fuera de alcance.
grade_docs — una puerta de relevancia LLM; en caso de fallo, reescribe la consulta y reintenta.
self_check — verifica que la respuesta redactada está implicada por el contexto recuperado; si no, reintenta o se cubre en lugar de alucinar.
Un presupuesto de reintentos compartido (
max_retries, por defecto 2) limita ambos bucles.Memoria — un checkpointer SQLite mantiene el estado de conversación multi-turno por
thread_id.
Related MCP server: pdf-analyzer
Inicio rápido
# 1. Install (Python 3.11+, uv)
uv sync
# 2. Configure — only ANTHROPIC_API_KEY is required
cp .env.example .env # then edit .env
# 3. Ingest the sample corpus (2 Markdown + 1 PDF + 1 Wikipedia article)
uv run skai ingest # -> builds ./.chroma (local MiniLM embeddings, no API)
# 4. Ask (defaults to Haiku 4.5; switch per-call with --model)
uv run skai ask "What do orcas eat?"
uv run skai ask "How do orcas communicate?" --source md
uv run skai ask "Summarize orca threats" --model sonnet # haiku | sonnet (Opus blocked)
# 5. Multi-turn chat (remembers the conversation)
uv run skai chat
# 6. Web UI (chat + feedback + live data ingestion)
uv run skai ui # http://localhost:7860
# 7. Serve over MCP (stdio) for Claude Desktop / an IDE
uv run skai mcpInterfaz web
skai ui lanza una aplicación Gradio con las características que necesita una demo en vivo:
Chat con memoria por sesión; cada respuesta muestra sus fuentes, ruta y modelo.
Feedback después de cada respuesta — 👍/👎 + un comentario opcional, almacenado en SQLite (
.skai/feedback.sqlite) y enviado como una puntuación de Langfuse en el trace de ese turno cuando el rastreo está activado. Ese es el bucle cerrado: el uso real se convierte en una señal de evaluación.Prompts de ejemplo para guiar la primera interacción.
Amplía la base de conocimiento en vivo — sube un
.md/.txt/.pdfo pega una URL y se ingiere en Chroma al instante, para que la demo no se limite al corpus inicial.Selectores de modelo (haiku/sonnet) y filtro de fuente (all/pdf/md/web).
El feedback se puede exportar a una semilla de evaluación JSONL mediante skai.feedback.export_jsonl.
Comandos
Comando | Qué hace |
| Cargar → fragmentar → incrustar → persistir en Chroma |
| Pregunta de una sola vez con citas |
| Chat interactivo multi-turno con memoria |
| Interfaz web Gradio: chat, feedback, ingesta en vivo |
| Ejecutar el servidor MCP que expone |
| Ejecutar la suite de calidad DeepEval (necesita |
Configuración del cliente MCP
El servidor expone dos herramientas — search_kb(query, source_type?) (recuperación bruta) y ask(question) (agente completo). Apunta un cliente MCP a él:
{
"mcpServers": {
"solid-knowledge-ai": {
"command": "uv",
"args": ["run", "skai", "mcp"],
"cwd": "/absolute/path/to/solid-knowledge-ai"
}
}
}Selección de modelo
El valor por defecto es Haiku 4.5 (rápido, barato — bueno para un bucle de router+calificador+generador de Q&A). Cambia por llamada con --model, o globalmente mediante SKAI_MODEL en .env:
Valor | Resuelve a |
|
|
|
|
cualquier id de LiteLLM | se pasa tal cual (p. ej. |
Opus está bloqueado intencionadamente (resolve_model lanza una excepción), para que el asistente no pueda apuntarse accidentalmente al nivel más caro.
Observabilidad
Configura LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY (y opcionalmente LANGFUSE_HOST) en .env. Cada ejecución del grafo produce entonces un trace con un span por nodo y por llamada LLM. Sin claves, el rastreo es un no-op limpio — nada más cambia.
Evaluación de calidad (DeepEval)
uv sync --group eval
export ANTHROPIC_API_KEY=...
uv run skai ingest
uv run --group eval pytest evals -v # or: skai evalEl juez es Claude vía LiteLLM, por lo que no se necesita clave de OpenAI. Métricas: fidelidad, relevancia de la respuesta, relevancia contextual — además de una compuerta de palabras clave barata.
Pruebas
uv run pytest # 39 tests, fully offline: no network, no API keysEl LLM se inyecta como dependencia, por lo que todo el grafo se ejecuta en pruebas contra un stub determinista, y Chroma utiliza una función de incrustación determinista en proceso.
Cómo está compuesto
src/skai/
config.py settings (.env) agent/llm.py ChatLiteLLM -> Claude
models.py Document/Chunk/AgentState agent/nodes.py route/retrieve/grade/generate/self_check
ingest/loaders.py pdf | md | web -> Document agent/prompts.py node prompts
ingest/chunk.py source-aware splitting agent/graph.py StateGraph + SQLite memory
ingest/store.py Chroma add/query observability.py Langfuse handler (or no-op)
cli.py ingest|ask|chat|mcp|eval mcp_server.py search_kb / ask as MCP tools
evals/ DeepEval suite tests/ offline unit + graph testsDiagramas de grafo del agente y componentes (Mermaid): consulta docs/ARCHITECTURE.md. Racional de diseño y compensaciones técnicas: consulta docs/DECISIONS.md.
Estado
Verificado: uv run skai ingest carga los tres tipos de fuente (2 md + 1 pdf + 1 web → 170 fragmentos) y la recuperación semántica real devuelve pasajes relevantes. 39 pruebas offline pasan. ask/chat/eval requieren una ANTHROPIC_API_KEY.
Available Tools
2 toolsaskB
Ask the self-reflective knowledge agent. Returns a grounded, cited answer.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavior disclosure; it does say outputs are grounded and cited, a meaningful trait. However, it does not mention limitations, confidence, citation format, or whether the agent can refuse/ask follow-ups, leaving the behavioral profile thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, with the core instruction and return behavior front-loaded. No filler or redundant restatement of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with an output schema, the description covers the key behavior and return characteristic. It is mostly complete, though the lack of sibling differentiation and parameter detail keeps it from being fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has a single required `question` string with no field description, and the description does not elaborate on expected question format, length, or scope. The parameter name is self-explanatory, but the description adds no semantic detail to compensate for 0% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action ('Ask') on a distinct resource ('self-reflective knowledge agent') and its output ('grounded, cited answer'). It does not explicitly compare itself to search_kb, but the resource and output type give enough differentiation for a general sense.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to ask versus using search_kb, nor any exclusions or conditions. The name and description imply Q&A usage, but the agent is not told when to choose this tool over the sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_kbC
Semantic search over the ingested documents. Optional source_type: pdf|md|web.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| source_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden of disclosing behavior. It reveals that the tool searches over ingested documents and accepts an optional source_type, but it does not disclose result limits, relevance behavior, authentication needs, or any side effects. For a read/search tool this is a notable but not severe gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence followed by a compact optional-parameter note. It is front-loaded with the core action and resource, and every word adds information. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter search tool, the description covers the essential invocation surface, and an output schema likely documents return values. However, it omits any comparison with 'ask' and does not explain result behavior or limitations, leaving the agent to infer when this tool is appropriate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does add meaning to source_type by enumerating allowed values ('pdf|md|web'), but it leaves the main 'query' parameter semantically undefined beyond the schema's bare type declaration. The compensation is only partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Semantic search') on a clear resource ('ingested documents') and lists the optional source_type filter. It does not explicitly name the sibling tool 'ask' as the alternative, so some differentiation is left to inference, but the operation is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to prefer search_kb over the sibling tool 'ask', nor any exclusions or prerequisites. Usage context is only implied by the phrase 'semantic search', which is not enough to route an agent reliably.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.0- First observed
ask - First observed
search_kb
TDQS
Scored across 2 tools
The two tools are distinct in purpose: search_kb returns semantic search results over sources, while ask provides a grounded, cited answer through an agent. There is some overlap in that both retrieve information from the same knowledge base, but the descriptions clearly differentiate a low-level search from a high-level Q&A interaction, making misselection unlikely.
Both tool names use lowercase snake_case and are verb-based. 'search_kb' follows a verb_noun pattern while 'ask' is a bare verb, creating a minor inconsistency, but the pattern is still simple and predictable given the small set.
With only two tools, the server feels thin but not unreasonable. Search and ask cover the core knowledge-access functions, though additional tools like listing sources or managing documents might be expected in a fuller knowledge-management server.
The tool surface covers the core domain of querying an ingested knowledge base: search_kb for retrieval and ask for synthesized answers. Minor gaps exist, such as no way to enumerate available sources or inspect document metadata, but these are not critical for the stated purpose.
Maintenance
Related MCP Connectors
- LLMtoMDOAuthcom.llmtomd
Convert PDFs, Office docs, websites and audio into AI-ready Markdown, then search and ask your docs.
Ingest, manage, and retrieve documents for RAG-powered AI applications
- docs2mcpOAuthcom.docs2mcp
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Build a RAG pipeline station by station and search your own documents with cited answers.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI-powered querying of PDF documents using hybrid retrieval (BM25 + vector search) and retrieval-augmented generation, returning structured answers with source citations and confidence scores.-
- AlicenseAqualityAmaintenanceEnables AI agents to read and analyze PDF documents for natural language Q\&A. Supports multiple LLM providers including Google Gemini, Anthropic Claude, and OpenAI.1123 npm4Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables querying PDF documents using natural language with grounded answers and source citations via a local RAG pipeline.MIT
- FlicenseNot gradedqualityBmaintenanceEnables traceable, version-aware question answering over product documentation, combining vector and graph retrieval to return cited evidence and support agentic workflows.-