# docloop **Repository Path**: winner_pan/docloop ## Basic Information - **Project Name**: docloop - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: feat/product-profile - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-12 - **Last Updated**: 2026-10-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DocLoop 多租户 SaaS 知识库:客户上传产品资料,AI 基于资料自主检索回答,网站嵌 JS 插件即可对话。 核心机制是 **agent 循环**:模型自主决定查什么、查几轮、何时收束;代码只提供工具和护栏。 高置信问题走快路径(1 次 LLM 调用),复杂问题进循环(典型 2 轮)。 ## 快速开始 ```bash make install # venv + 依赖(含 docling 解析,较重) cp .env.example .env # 改 DL_DB_PASSWORD / YUDI_API_KEY / DL_SECRET_KEY make migrate # 建库建表(需 MySQL 8,ngram 全文索引) python scripts/create_admin.py myco admin@myco.com --generate make run # http://localhost:8300 ``` 登录 → 上传资料(md/txt/pdf/docx…)→ 聊天测试页提问。 ## 架构 ``` FastAPI 单进程 ├── /admin/* 管理端(htmx+Jinja2:文档/目录/chunk编辑/聊天测试/widget/用量) ├── /chat/stream 管理端聊天 SSE ├── /widget/chat 访客对话 SSE(Bearer widget_key + 域名白名单 + IP限流) ├── /mcp MCP server(外部 agent 接入) └── worker×2 入库队列(DB租约:parse→chunk→embed,断点续跑) consult/ 快路径(query_map精确/向量高置信) → agent循环(6工具并行+结果预算) → 回答 MySQL 租户隔离行级强制(DAO 层 tenant_id);FULLTEXT ngram(2) ChromaDB chunks + query_map_vec 两个集合,bge-m3 CPU 单例 LLM anthropic SDK base_url 切换:yudi(litellm qwen3.6-35b) ↔ anthropic(真Claude) ``` ## 6 工具 | 工具 | 作用 | |---|---| | query | LLM 写 SQL(sqlglot 注入租户谓词+强制 LIMIT) | | search_semantic | bge-m3 语义检索 + learn 映射通道 | | list | 目录树浏览 | | read | 读分块全文 | | learn | 记录「说法→目录」映射(精确+语义原子双写) | | refine | 已收集分块内存收敛(零 DB) | ## 评估 ```bash python scripts/eval/run_golden.py --mode retrieval --save-baseline # 首基线 python scripts/eval/run_golden.py --mode retrieval # 回归检查 ``` `evals/golden.jsonl` 每行:`{"id","tenant_id","space_id","question","expected_chunk_ids":[],"gold_answer":""}` ## MCP Server 同一套 6 工具暴露给外部 agent(Claude Code 等),schema 与 agent 循环共用 `consult/tools.py`。 ```bash # stdio(本地 Claude Code 直连,显式租户) python -m docloop.mcp --tenant 1 --space 1 # streamable-http(api_keys 表鉴权:SHA2(key,256) 匹配 key_hash) python -m docloop.mcp --api-key sk-xxx --http --port 8310 ``` Claude Code 配置示例: ```json {"mcpServers": {"docloop": {"command": "python", "args": ["-m", "docloop.mcp", "--tenant", "1", "--space", "1"]}}} ``` ## 部署 - 生产:`uvicorn docloop.app:app --host 0.0.0.0 --port 8300`(单进程假设:Chroma 本地 + 嵌入单例) - 反代:nginx 需 `proxy_buffering off`(SSE) - 切真 Claude:`.env` 设 `LLM_MODE=anthropic` + `ANTHROPIC_API_KEY` - 老数据迁移:`python scripts/migrate_from_enterprise_kb.py --old-db enterprise_kb --tenant-slug legacy` - 访客插件:客户网站嵌 `` ## 开发 ``` docloop/ ├── config.py env 驱动,LLM_MODE 切换 ├── llm.py Anthropic 协议客户端(熔断/抖动重试/错误分类/缓存标记) ├── db.py DBUtils 连接池 ├── dal/ DAO(全部强制 tenant_id) ├── vector/ 嵌入单例 + 可插拔 reranker ├── core/ 解析分块(Docling/StructureAwareChunker/OCR标点修复) ├── consult/ 检索心脏:prompts/tools/fast_path/loop/orchestrator ├── ingest/ 租约队列 + 分阶段管线 ├── auth/ 管理端 cookie 会话 / widget key+origin+限流 ├── api/ 路由 ├── web/ Jinja2+htmx 管理界面 ├── widget/ widget.js(访客插件,零依赖单文件) └── mcp/ MCP server ``` 设计原则:极简规则+模型自治;目录优先结构检索;判定模型驱动;learn 是唯一学习环;评估驱动一切旋钮。