Skip to main content
Glama
hailampy123

solid-knowledge-ai

by hailampy123

Solid Knowledge AI

一个由自反思 LangGraph 智能体驱动的多源文档知识助手。它将 PDF + Markdown + 网页 摄取到同一个向量库中,然后通过一个对自身检索进行评分并验证自身答案是否有据可依的智能体来回答问题——当任一检查失败时,使用重写的查询重试;当无法为答案提供依据时,拒绝编造。使用 Langfuse 进行追踪,使用 DeepEval 进行质量测试,并通过 MCP 暴露。

旨在展示智能体开发:LangGraph · LiteLLM · ChromaDB · MCP · Langfuse · DeepEval。

为什么这不是"单纯的 RAG"

该智能体是一个纠正性 / 自反思 RAG 循环,而不是线性的 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 — 对闲聊 / 超出范围的问题跳过检索。

  • grade_docs — 一个 LLM 相关性门控;失败时重写查询并重试。

  • self_check — 验证草拟的答案是否由检索到的上下文所蕴含;如果不是,则重试或给出保守回答,而不是产生幻觉。

  • 共享的重试预算(max_retries,默认 2)约束两个循环。

  • Memory — 一个 SQLite 检查点器按 thread_id 维护多轮对话状态。

Related MCP server: pdf-analyzer

快速开始

# 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 mcp

Web UI

skai ui 启动一个 Gradio 应用,具备实时演示所需的功能:

  • 聊天,带每会话记忆;每个答案都显示其来源、路由和模型。

  • 每次响应后的反馈 — 👍/👎 + 可选评论,存储到 SQLite(.skai/feedback.sqlite)并且在开启追踪时作为该轮对话 trace 上的 Langfuse 评分推送。这就是闭环:真实使用成为评估信号。

  • 示例提示,引导首次交互。

  • 实时扩展知识库 — 上传 .md/.txt/.pdf 或粘贴 URL,即刻被摄取到 Chroma 中,因此演示不限于种子语料。

  • 模型(haiku/sonnet)和来源过滤器(all/pdf/md/web)选择器。

反馈可通过 skai.feedback.export_jsonl 导出为 JSONL 评估种子。

命令

命令

作用

skai ingest [--path data/docs --urls data/urls.txt --reset]

加载 → 分块 → 嵌入 → 持久化到 Chroma

skai ask "..." [--source pdf|md|web] [--thread-id X]

带引用的单次提问

skai chat

带记忆的交互式多轮聊天

skai ui [--port 7860 --share]

Gradio Web UI:聊天、反馈、实时摄取

skai mcp

运行暴露 search_kb 和 ask 的 MCP 服务器

skai eval

运行 DeepEval 质量套件(需要 --group eval + 密钥)

MCP 客户端配置

服务器暴露两个工具 — search_kb(query, source_type?)(原始检索)和 ask(question)(完整智能体)。将 MCP 客户端指向它:

{
  "mcpServers": {
    "solid-knowledge-ai": {
      "command": "uv",
      "args": ["run", "skai", "mcp"],
      "cwd": "/absolute/path/to/solid-knowledge-ai"
    }
  }
}

模型选择

默认是 Haiku 4.5(快速、便宜 — 适合 Q&A 路由+评分+生成循环)。通过 --model 按调用切换,或通过 .env 中的 SKAI_MODEL 全局切换:

值

解析为

haiku(默认)

anthropic/claude-haiku-4-5

sonnet

anthropic/claude-sonnet-4-5

任意 LiteLLM id

透传(例如 openai/gpt-4o-mini)

Opus 被有意阻止(resolve_model 会抛出异常),因此助手不会意外指向最昂贵的层级。

可观测性

在 .env 中设置 LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY(以及可选的 LANGFUSE_HOST)。每次图运行随后产生一个 trace,每个节点和每次 LLM 调用各有一个 span。没有密钥时,追踪是一个干净的空操作 — 其他一切不变。

质量评估(DeepEval)

uv sync --group eval
export ANTHROPIC_API_KEY=...
uv run skai ingest
uv run --group eval pytest evals -v      # or: skai eval

评判者是 通过 LiteLLM 的 Claude,因此不需要 OpenAI 密钥。指标:faithfulness、answer relevancy、contextual relevancy — 外加一个廉价的关键词门控。

测试

uv run pytest        # 39 tests, fully offline: no network, no API keys

LLM 是依赖注入的,因此整个图在测试中针对一个确定性的桩运行,Chroma 使用确定性的进程内嵌入函数。

结构组成

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 tests

智能体图与组件图(Mermaid): 参见 docs/ARCHITECTURE.md。 设计理由与技术权衡: 参见 docs/DECISIONS.md。

状态

已验证:uv run skai ingest 加载所有三种来源类型(2 个 md + 1 个 pdf + 1 个 web → 170 个块),真实的语义检索返回相关段落。39 个离线测试通过。ask/chat/eval 需要 ANTHROPIC_API_KEY。

Available Tools

2 tools
askB

Ask the self-reflective knowledge agent. Returns a grounded, cited answer.

NameRequiredDescriptionDefault
questionYes

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault
queryYes
source_typeNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters2/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

  1. 2 tool updatesv0.1.0
    • First observedask
    • First observedsearch_kb

TDQS

B3.2/5.0

Scored across 2 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count3/5

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.

Completeness4/5

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

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers