使用说明
论文摘要任务的多代理系统(多代理+矢量存储+OCR+MCP)
该存储库实现了构建多代理系统的技术挑战,该系统:
- 接收论文(本地PDF、URL或文本)。
- 将论文分为三个科学领域之一。
- 提取包含字段的JSON 确切地 匹配提示(包括 错字 在
artcle). - 用葡萄牙语撰写批判性评论,强调优势、局限性和对有效性的威胁。
该系统由以下部分组成:
- A. 向量存储 ChromaDB中有9篇论文(3个区域×每个区域3个PDF)。
- 一 MCP服务器 暴露对该矢量存储的访问(
search_articles,get_article_content). - A. 多代理管道 在LangGraph(分类器→ 提取器→ 审稿人)。
- 可选的 OCR支持 当PDF没有嵌入文本时,通过文档。
- 自动化测试 用于矢量存储和集成管道。
- Makefile, Dockerfile,以及 docker编写 以简化设置和执行。
1.高层架构
汇总流程:
-
矢量数据库摄取
- 按以下方式组织的PDF
pdf_database/<area>/(例如。,economy,med,tech). - 每个PDF都被拆分为 块 (
chunk_size=1000,overlap=200). - 使用生成的嵌入
sentence-transformers/all-MiniLM-L6-v2. - 所有内容都被编入Chroma系列,名为
articles在...之下chroma_db/.
- 按以下方式组织的PDF
-
MCP服务器(
src/mcp_server/server.py)- 从读取配置
configuration/base.yaml. - 打开现有的色度索引。
- 通过MCP显示两个工具:
search_articles(query: str, top_k: int)→ 列表{id, title, area, score}.get_article_content(article_id: str)→{id, title, area, content}.
- 从读取配置
-
多代理系统(
src/multi_agent_system)-
已实施 LangGraph.
-
主要节点:
-
分类器_节点
将纸张分类到一个区域。
使用:- 纸质文本(截断为4000个字符)。
- 通过MCP检索上下文(
search_articles带有初始片段)。
-
提取器节点
读取论文(带有安全截断),并用模式填充JSON:{ "what problem does the artcle propose to solve?": "", "step by step on how to solve it": ["", "", ""], "conclusion": "" }钥匙在 相同的 提示,包括
artcle. -
审阅者_节点
使用论文文本中提取的JSON+部分生成葡萄牙语评论(Markdown)。
-
-
该图为:
start → classifier → extractor → reviewer → END.
-
-
用户输入(
scripts/run_agents.py+src/pipeline/pipeline_runner.py)- 接受:
- 本地路径
.pdf,.txt,或.md. - 指向PDF的URL。
- 本地路径
- 将输入标准化并保存到
samples/input_article_N.ext. - 运行多代理管道(
run_pipeline). - 生成:
samples/review_N.md随着审查。samples/output_N.json和{area, extraction, review_markdown}.
- 接受:
2.目录结构
概述:
.
├── chroma_db/ # Where the persistent ChromaDB vector index is stored
├── configuration/
│ └── base.yaml # Central configuration file (paths, vector DB, MCP, LLM, etc.)
├── pdf_database/ # Local PDF base used as reference for the vector store
│ ├── economy/ # 3 economy papers
│ ├── med/ # 3 medical papers
│ └── tech/ # 3 technology papers
├── samples/ # Outputs generated when running the pipeline
│ ├── input_article_N.pdf # Normalized inputs (PDF/URL/MD/TXT)
│ ├── output_N.json # Structured output (area + extracted JSON + review)
│ └── review_N.md # Critical review written by the agent
├── src/
│ ├── mcp_server/
│ │ └── server.py # MCP server exposing tools backed by the vector store
│ ├── multi_agent_system/
│ │ ├── classifier_agent.py # Agent that classifies the paper's area
│ │ ├── extractor_agent.py # Agent that generates the JSON required by the challenge
│ │ ├── reviewer_agent.py # Agent that writes the critical review
│ │ ├── graph.py # LangGraph graph connecting the three agents
│ │ └── mcp_vector_client.py # HTTP client that talks to the MCP server
│ ├── pdf_parser/
│ │ └── pdf_parser.py # PDF reader (PyPDF + Docling OCR fallback when needed)
│ ├── pipeline/
│ │ └── pipeline_runner.py # Orchestrates the full execution flow
│ └── vector_database/
│ ├── vector_database.py # Vector store implementation (Chroma + embeddings)
│ └── ingestion_runner.py # Handles ingestion of the 9 PDFs and index creation
├── scripts/
│ ├── database_ingestion.py # Script to rebuild the vector database
│ └── run_agents.py # CLI script to run the pipeline on a paper
├── tests/ # Automated test suite
│ ├── test_vector_database.py
│ └── test_graph_pipeline.py
├── mcp.json # MCP manifest (for external MCP clients)
├── Makefile # Main commands (setup, index, tests, agents, mcp)
├── Dockerfile # Project Docker image
├── docker-compose.yml # Docker Compose orchestration
├── requirements.txt # Python dependencies
└── pytest.ini # Pytest configuration
3.要求
3.1.主要依赖关系
执行旨在运行 Docker容器内部。在主机上,您只需要:
-
码头工人
-
Docker Compose
-
环境变量或
.env文件包含:GROQ_API_KEY=<your_groq_key>
(可选)如果您在配置了GPU和CUDA的计算机上运行,PyTorch和 sentence-transformers 将在容器内自动使用它。
3.2.环境变量
在项目根目录下,创建一个 .env 与:
echo "GROQ_API_KEY=YOUR_TOKEN_HERE" > .env
docker-compose.yml 已配置为加载此 .env 放入容器中。
4.使用Docker和Docker编写运行
所有依赖项安装、向量索引创建和管道执行都会发生 在…内 集装箱。
4.1.塑造形象
在项目根节点:
docker compose build
4.2.输入容器
要打开容器内的外壳,请执行以下操作:
docker compose run --rm summary-app bash
你会在 /app 在容器内,代码通过卷安装。
5.建立病媒库(吸收9篇论文)
仍然 集装箱内,运行:
make index
这 index 目标:
- 清洁
chroma_db/文件夹(如果存在)。 - 通过调用来重建完整的向量索引
scripts.database_ingestion.
内部:
- 阅读
configuration/base.yaml. - 解决
pdf_database/和chroma_db/. - 创建一个
VectorDatabase实例包含:embedding_model="sentence-transformers/all-MiniLM-L6-v2"chunk_size=1000chunk_overlap=200
- 迭代下的每个子文件夹
pdf_database/:- 每个PDF都会被读取、文本提取、分块和索引。
- 将嵌入和元数据持久化到Chroma中(存储在
/app/chroma_db,其被安装到主机)。
6.OCR和PDF文本提取
这 PdfTextExtractor 班级(src/pdf_parser/pdf_parser.py)实施:
-
使用PyPDF进行提取
- 用途
pypdf.PdfReader和page.extract_text()逐页。 - 如果它可以提取文本,则返回该内容。
- 用途
-
通过Docling进行OCR回退(可选)
- 如果 无文本 与PyPDF一起找到
enable_ocr=True,它尝试OCR。 - 用途
docling.document_converter.DocumentConverter().convert(...). - 呼叫
export_to_text(). - 如果仍然没有文本,它会提高
ValueError.
- 如果 无文本 与PyPDF一起找到
在管道中,默认情况下启用OCR .pdf 文件夹。
7.多代理管道(LangGraph)
图表存在于 src/multi_agent_system/graph.py.组件:
-
分类器代理(
classifier_agent.py)- 通过列出下的子文件夹来发现区域
pdf_database/(例如。,economy,med,tech). - 将纸张文本截断为
max_article_chars(4000个字符)。 - 使用MCP客户端(
MCPVectorStoreClient)拨打电话search_articles带有初始片段(mcp_query_chars,800个字符)。 - 从向量存储点击中构建文本上下文。
- 致电Groq LLM:
- 在中配置的系统提示
MultiAgentConfig. - 包含截断的纸张文本+类似纸张列表的人工消息。
- 在中配置的系统提示
- 将输出规范化为已知区域(精确匹配、子字符串、同义词如“econ”)。
- 通过列出下的子文件夹来发现区域
-
提取剂(
extractor_agent.py)-
接收
article_text(以及可选area). -
将文本截断为
max_article_chars(6000). -
指示LLM返回 仅 JSON。
-
用途
_extract_json_from_response支持:- 原始JSON。
json ...用栅栏围起来的街区。
-
用途
_normalize_extraction以确保:{ "what problem does the artcle propose to solve?": "string", "step by step on how to solve it": ["string", "..."], "conclusion": "string" }
-
-
审核代理(
reviewer_agent.py)- 接收
area,extraction,以及article_text. - 连载
extraction转换为JSON字符串。 - 将纸张截断为~4000个字符,以提供可选上下文。
- 生成葡萄牙语评论,重点关注:
- 新颖性/贡献。
- 方法/实验设计。
- 结果的有效性。
- 对有效性和可重复性的威胁。
- 接收
-
图表(
graph.py)- 国家:
{"article_text", "area", "extraction", "review"}. - 订单:
start → classifier → extractor → reviewer → END.
- 公共职能:
run_pipeline(article_text: str) -> Dict[str, Any].
- 国家:
8.MCP服务器
在 src/mcp_server/server.py:
- 阅读
configuration/base.yaml:- 配置
pdf_root,chroma_path. - 配置
embedding_model,collection_name,chunk_size,chunk_overlap. - 配置
mcp.name,mcp.transport.
- 配置
- 实例化
VectorDatabase使用这些设置。 - 创建一个
FastMCP服务器与json_response=True. - 外露工具:
@mcp.tool()
def search_articles(query: str, top_k: int = 5) -> List[Dict[str, Any]]:
...
@mcp.tool()
def get_article_content(article_id: str) -> Dict[str, Any]:
...
8.1.MCP清单(mcp.json)
mcp.json 定义:
- 服务器名称、标签、版本和描述。
- 如何通过STDIO启动它:
{
"servers": [
{
"name": "stdio",
"transport": "stdio",
"command": "python",
"args": ["-m", "src.mcp_server.server"],
"env": {
"PYTHONPATH": "."
}
}
],
"tools": [
{ "name": "search_articles", ... },
{ "name": "get_article_content", ... }
]
}
外部MCP客户端(如ChatGPT或IDE)使用它来发现如何与容器内的服务器通信。
8.2.内部MCP客户端(MCPVectorStoreClient)
src/multi_agent_system/mcp_vector_client.py:
- 用途
mcp.ClientSession+stdio_client将MCP服务器作为子进程启动:- 默认命令:
python -m src.mcp_server.server 2>/dev/null.
- 默认命令:
- 公共方法:
search_articles(query: str, top_k: int).get_article_content(article_id: str).
换句话说,内部代理无法访问 VectorDatabase 直接;一切都通过MCP工具。
9.管道执行CLI(使用下面解释的Makefile)
src/pipeline/pipeline_runner.py:
-
ArticleSampleManager:- 阅读
samples/output_N.json以发现下一个索引。 - 将本地文件或下载URL复制到
samples/input_article_N.ext. - 计算路径
review_N.md和output_N.json.
- 阅读
-
ArticlePipelineRunner:- 解析来源→ 规范输入→ 阅读文本。
- 呼叫
run_pipeline(article_text). - 保存
review_N.md和output_N.json. - 返回执行元数据。
10.自动化测试
10.1.运行测试(容器内)
随着 GROQ_API_KEY 在环境中可用(通过 .env):
make test
这 test 目标:
- 重建矢量数据库(
scripts.database_ingestion). - 跑
pytest.
10.2.测试
tests/test_vector_database.py:- 测试组块,
search_articles,以及get_article_content.
- 测试组块,
tests/test_graph_pipeline.py:- 图的端到端集成(
run_pipeline)在PDF上。 - 跳过如果
GROQ_API_KEY未设置。
- 图的端到端集成(
11.生成文件
可用的主要目标 集装箱内:
make help
-
make index
清洁chroma_db/文件夹并从中重建完整的矢量索引pdf_database/. -
make test
重建索引并运行pytest. -
make agent SOURCE=...
在纸张(本地文件或URL)上运行多代理管道。
示例:make agent SOURCE="samples/input_article_1.pdf" make agent SOURCE="https://example.com/paper.pdf" -
make mcp
在容器内的后台启动MCP服务器,将PID写入.mcp_server.pid。这仅在您想将外部MCP客户端(如ChatGPT)连接到容器内运行的服务器时有用。 -
make stop-mcp
停止通过启动的MCP服务器make mcp.
12.Docker和Docker组合
Docker流程概述:
-
塑造形象 (在主机上):
docker compose build -
输入容器 (在主机上):
docker compose run --rm summary-app bash -
集装箱内部 (in
/app):# 1) Build the vector index in chroma_db/ make index # 2) Run the pipeline on an example paper make agent SOURCE="samples/input_article_1.pdf" # 3) Run tests make test # 4) Start MCP server in the background for external clients make mcp # ... use it from an external MCP client ... make stop-mcp
这 /app/chroma_db, /app/samples,以及 /app/pdf_database 文件夹作为主机卷装载,因此容器内生成的工件显示在本地项目树中。
13.快速总结
-
创建
.env使用密钥(在主机上):echo "GROQ_API_KEY=YOUR_TOKEN_HERE" > .env -
构建Docker镜像(在主机上):
docker compose build -
输入容器:
docker compose run --rm summary-app bash -
在容器内部,构建索引:
make index -
在示例上运行服务器和管道:
make mcp make agent SOURCE="samples/input_article_1.pdf" -
检查输出(来自主机或容器):
samples/output_N.jsonsamples/review_N.md
14.详细配置(base.yaml)--参数说明
以下是对 每个配置字段的作用 和 为什么选择它 在这个系统内。
mcp block:MCP服务器参数
mcp:
name: "ArticleVectorStore"
transport: "http"
host: "0.0.0.0"
port: 8000
base_url: "http://127.0.0.1:8000"
✦ name: "ArticleVectorStore"
MCP服务器的逻辑名称。
仅用于外部MCP客户端的识别。
我们选择这个名字是因为服务器只公开一个矢量存储的论文。
✦ transport: "http"
定义MCP作为 HTTP服务器,不是STDIO。
这允许多代理系统使用正常的HTTP请求与MCP通信——更简单、更可预测、更容易调试。
✦ host: "0.0.0.0"
使服务器监听容器内的所有网络接口。
这是必需的,这样即使在单独的进程中运行,多代理系统也可以到达MCP。
✦ port: 8000
项目FastAPI/uvicorn服务器的默认端口。
✦ base_url: "http://127.0.0.1:8000"
MCP客户端使用的URL(MCPVectorStoreClient)发送请求。
即使服务器绑定到 0.0.0.0,客户端连接到 127.0.0.1 从容器内。
paths 块:主要路径
paths:
pdf_root: pdf_database
chroma_path: chroma_db
✦ pdf_root
包含用于构建矢量存储的9个PDF的目录。
我们选择了 <area>/<pdf> 结构,因为分类器通过列出子文件夹自动发现区域。
✦ chroma_path
ChromaDB保存其持久矢量数据库的目录。
保持简单,从项目根开始,通过以下方式简化版本控制和清理 make index.
vector_db 块:向量存储参数
vector_db:
embedding_model: sentence-transformers/all-MiniLM-L6-v2
collection_name: articles
chunk_size: 1000
chunk_overlap: 200
✦ embedding_model: all-MiniLM-L6-v2
一种快速、轻便的模型,被广泛推荐用于 语义相似度.
动机:
- 比大型型号轻得多
- 强大的嵌入功能,可缩短技术文本
- 低延迟,是多代理管道的理想选择
✦ collection_name: articles
ChromaDB集合名称。
我们保持 articles 因为存储的内容完全是科学论文。
✦ chunk_size: 1000
每个PDF被分割成最多1000个字符的块。
此尺寸平衡:
- 每个块有足够的上下文
- 矢量搜索的良好粒度
- 更快的嵌入生成
✦ chunk_overlap: 200
块之间有20%的重叠。
选择它是为了防止跨块边界的上下文丢失,这对较长的PDF尤为重要。
multi_agent block:LLM代理配置
multi_agent:
llm:
provider: groq
model: openai/gpt-oss-120b
temperature: 0.0
✦ provider: groq
我们使用 格罗克 以实现极低的延迟,减少整体管道响应时间。
✦ model: openai/gpt-oss-120b
Groq加速的OSS模型,具有以下强大的平衡:
- 成本
- 速度
- 推理能力
根据经验,它为分类器、提取器和审阅者产生了最一致的结果。
✦ temperature: 0.0
完全确定的行为。
关键在于:
- 自动化测试稳定
- 无结构变化的JSON提取
- 分类不会在运行中波动
代理提示
分类器提示
专注于选择 正好一个 这三个领域。
它可以访问以下输出 search_articles(),鼓励使用真实的矢量存储上下文。
提取器提示
强制LLM返回 仅 JSON包含:
- 与提示相同的按键
- 严格格式
- 自信的循序渐进的解决方案
这 artcle 拼写错误被保留以遵循官方提示。
审阅者提示
在中生成完整的批判性评论 巴西葡萄牙语,有八个强制性部分。
它还引导模型识别纸张何时“超出区域”,与分类器行为相匹配。
主要依赖关系和基本原理
groq
低延迟LLM提供程序→ 减少了管道响应时间。
chromadb
简单高效的矢量存储,直接使用Python API。
句子变换器
语义搜索的高质量嵌入。
pypdf
第一阶段文本提取——快速且无本地依赖。
文档
现代OCR被用作没有嵌入文本的PDF的后备方案。
easyocr
Docling在某些场景中内部使用的互补依赖关系。
兰格拉夫
构建一个确定性和可重复的代理管道。
朗肯码头
Groq司机简化LLM呼叫。
fastapi+uvicorn
MCP服务器通过HTTP的轻量级基础设施。
皮丹提克
对所有MCP请求/响应进行严格验证。
测试
矢量存储和多代理管道的自动化测试。
