Arquitectura

Las notas entran por un observador y una cola de tareas; las preguntas vuelven como citas con rangos de líneas. Cada recuadro nombra el archivo que lo implementa.

real: siempre forma parte del sistema opcional: necesita un modelo de lenguaje flecha discontinua: lee o escribe la base de datos

En una pantalla estrecha, lee la tabla de cada parte en lugar de los dibujos.

Los dos flujos

arquitectura de knowman, los flujos de ingesta y consulta INGESTACONSULTAENTRADAS Postgres + pgvectorstore.py es el único módulo que habla SQL: fragmentos (columna embedding, índice HNSW), tareas, corridas de eval, trazas tareaslee tareasfragmentos + vectores k más cercanos nada dentro de la distancia pregunta Notas (.md)carpeta CORPUS_PATHREAL Observadorwatcher.pyeventos de watchfilesREAL Cola de tareasstore.pyingest / deleteREAL Procesadorworker.pytoma tareasREAL Fragmentadorchunking.pyingest.pyREAL Embeddingsembeddings/ollama.pyOllamaREAL Embed consultaretrieval.pyembeddings/ollama.pyREAL Fragmentos cercanosstore.pyHNSW, cosineREAL Filtro de distanciaretrieval.pymáx. por defecto 0.5REAL Citasretrieval.pypath:Lstart-LendREAL Respuesta del LLMask.pyllm/*.pyOPCIONAL Evaluacióneval.pydataset.jsonREAL Sin evidencia"No evidence foundfor that query."REAL Agenteagent.pyknowman writeOPCIONAL CLIcli.pyknowman ...REAL API HTTPapi.py/search, /ask, /evalREAL Servidor MCPmcp_server.pysearch, ask (stdio)REAL Paneldashboard.pyGET /dashboardREAL

Recuperación, citas y evaluación solo necesitan Postgres y Ollama para los embeddings. Un modelo de lenguaje añade la respuesta escrita en ask. Corre con Docker Compose o de forma nativa con unidades systemd; la GPU se usa por Vulkan cuando existe /dev/dri y nunca es obligatoria. Los mensajes del programa, como No evidence found for that query., se quedan en inglés porque son la salida literal. Fuente: core/README.md, core/docs/running.md.

Los componentes que hay detrás

El mismo sistema, agrupado por capa. Se lee de arriba abajo: cada capa llama a la de abajo, y la fila del final la usan todas. Cada recuadro es un archivo o un paquete dentro de core/src/knowman/.

componentes de knowman por capaPuntos de entrada: CLI, API HTTP, servidor MCP, panel. Servicios: observador, procesador, agente opcional. Casos de uso: ingesta, respuesta, evaluación. Núcleo: fragmentación, recuperación, formato. Adaptadores: embeddings, proveedores de modelos de lenguaje, prompts. Almacenamiento: módulo store sobre Postgres con pgvector. Común: configuración, control de acceso, registro. Las flechas van de una capa a la capa de la que depende. ENTRADA SERVICIOS CASOS DE USO NÚCLEO ADAPTADORES ALMACÉN COMÚN CLIcli.pyknowman search, ask, ingestREAL API HTTPapi.py/search, /ask, /eval, /indexREAL Servidor MCPmcp_server.pysearch y ask por stdioREAL Paneldashboard.pyGET /dashboardREAL Observadorwatcher.pylos eventos de watchfiles son tareasREAL Procesadorworker.pytoma una tarea a la vezREAL Agenteagent.py, LangGraphknowman write: busca y luego escribeOPCIONAL Ingestaingest.pyarchivo a fragmentos, vectores y filasREAL Respuestaask.pytexto redactado a partir de las citasOPCIONAL Evaluacióneval.pydataset puntuado contra la recuperaciónREAL Fragmentaciónchunking.pycorta en líneas vacías, guarda el rangoREAL Recuperaciónretrieval.pyembed, k más cercanos, filtro, citaREAL Formatoformatting.pypath:L5-L6, o el negativo explícitoREAL Embeddingsembeddings/base.py, ollama.pyun vector por fragmento, el mismo modeloREAL Modelos de lenguajellm/base.py + ollama, claude,openai, grokOPCIONAL Promptsprompts/ask_v1.txtPROMPT_VERSION elige el archivoOPCIONAL Almacénstore.py: el único módulo que habla SQLPostgres + pgvector: fragmentos (columna embedding, índice HNSW cosine), tareas, corridas de eval, trazasREAL Configuraciónconfig.pyun único Settings desde env y .envREAL Control de accesoaccess.pytoken y límite de tasa, apagadosREAL Registrologging_setup.pyun registro JSON por líneaREAL

La flecha de la izquierda va de la capa que llama a la capa de la que depende. Configuración, control de acceso y registro van al final porque todas las capas de arriba los leen. Fuente: core/src/knowman/, core/README.md, core/docs/running.md.

Cada parte

Los nombres de la columna Parte están traducidos. Los nombres de la columna Código son los archivos y ajustes reales.

ParteCódigoEstadoQué hace
Notas (.md)carpeta CORPUS_PATHrealTu carpeta Markdown. La indexación nunca la modifica; solo el agente escribe en ella.
Observadorwatcher.pyrealConvierte cada archivo .md añadido, editado o borrado en una tarea.
Cola de tareasstore.pyrealLas tareas son filas en Postgres: ingest_path y delete_path, con estado pending, processing, done o failed.
Procesadorworker.pyrealToma una tarea a la vez y la ejecuta; una tarea fallida queda registrada, no se reintenta en silencio.
Fragmentadorchunking.py, ingest.pyrealCorta en líneas vacías conservando el rango de líneas de cada fragmento; ingest.py calcula los embeddings y guarda los fragmentos.
Embeddingsembeddings/base.py, embeddings/ollama.pyrealOllama convierte cada fragmento en un vector (modelo en EMBEDDINGS_MODEL). Una interfaz, una implementación.
Postgres + pgvectorstore.pyrealGuarda fragmentos, tareas, corridas de eval y trazas. Índice HNSW cosine sobre la columna embedding.
Embed consultaretrieval.pyrealConvierte la pregunta en un vector con el mismo modelo.
Fragmentos cercanosstore.pyrealDevuelve los k fragmentos más cercanos (k por defecto viene de RETRIEVAL_DEFAULT_K).
Filtro de distanciaretrieval.pyrealDescarta los fragmentos que están más lejos que RETRIEVAL_MAX_DISTANCE. Un resultado vacío es el negativo explícito.
Citasretrieval.pyrealCada cita lleva ruta, línea inicial, línea final, texto y distancia.
Formatoformatting.pyrealEscribe una cita como path:Lstart-Lend más su pasaje, y un resultado vacío como "No evidence found for that query."
Respuesta del LLMask.py, llm/*.pyopcionalSolo cuando LLM_PROVIDER está definido (Ollama, Claude, OpenAI o Grok) y hay evidencia. search y eval nunca lo necesitan.
Promptsprompts/ask_v1.txtopcionalLa plantilla con la que se redacta la respuesta; PROMPT_VERSION elige el archivo, así que un texto nuevo es un archivo nuevo, no un cambio de código.
Evaluacióneval.py, evaldata/dataset.jsonrealPuntúa un dataset etiquetado contra la recuperación; ningún modelo juzga a otro modelo.
Agenteagent.pyopcionalknowman write: un agente LangGraph sobre Ollama que puede buscar en las notas y escribir una nueva.
CLIcli.pyrealdb-init, ingest, search, ask, eval, worker, watch, mcp, write.
API HTTPapi.pyrealSearch, ask, eval, tareas de indexación, estado; API_TOKEN y límite de tasa opcionales.
Control de accesoaccess.pyrealLa comprobación del token y el contador de peticiones por minuto detrás de esas dos opciones. Ambas están apagadas si no se definen, y ninguna sabe qué hacen search o ask.
Servidor MCPmcp_server.pyrealDos herramientas de solo lectura por stdio: search y ask.
Paneldashboard.pyrealUna página en /dashboard: índice contra disco, cola de tareas, última evaluación, actividad reciente.
Configuraciónconfig.pyrealUn único objeto Settings leído del entorno y de .env; cada módulo se lo pide en vez de parsear variables.
Registrologging_setup.pyrealLogs JSON en stdout, un registro por línea, para que los contenedores y las unidades systemd registren la misma forma.