基于Python的高性能多智能体协同RAG(检索增强生成)系统架构与生产级实现指南
1. 引言:大模型时代的检索增强生成(RAG)与多智能体(Multi-Agent)演进
在大语言模型(LLM)技术席卷全球的背景下,企业级AI应用的落地面临着三大核心痛点:知识幻觉(Hallucination) 、时效性滞后(Knowledge Cutoff)以及私有领域数据孤岛(Data Silos)。传统的全量微调(Full Fine-Tuning)与参数高效微调(PEFT,如LoRA/QLoRA)虽然能在一定程度上调整模型的语气和垂直领域认知,但其动辄数十万甚至上百万的算力成本,以及无法实时更新动态数据的本质缺陷,使得其在快速变化的企业业务场景中捉襟见肘。
为了解决这些问题,**检索增强生成(Retrieval-Augmented Generation, RAG)**应运而生。经典的单体RAG系统(Naïve RAG)通过"切片-向量化-检索-拼接"的管道(Pipeline)模式,成功为大模型装上了"外挂知识库"。然而,随着应用场景向复杂决策、长文本分析以及跨多数据源协同等深水区迈进,传统RAG的局限性迅速暴露:
- 语义断层:简单的Top-K向量检索无法理解复杂的组合查询意图。
- 上下文爆炸与噪声干扰:检索到的大量无关片段不仅消耗Token,更会导致模型"迷失在中间(Lost in the Middle)"。
- 缺乏反思能力:一旦检索到错误或不相关的信息,系统缺乏自我修正和重新检索的闭环机制。
为了突破单体RAG的性能瓶颈,**多智能体系统(Multi-Agent Systems)**与先进RAG技术的融合成为当前AI工程化领域的绝对前沿。多智能体协同RAG通过将复杂的"检索-生成"过程解耦为多个具备单一职责的自治代理(如查询路由Agent、文档检索Agent、事实核验Agent、总结生成Agent),利用图结构(Graph)编排任务流,引入动态反思(Self-Reflection)与纠错机制,从而实现了具备高鲁棒性、高准确率的企业级级AI系统。
本文 opinionated 地基于 Python 语言堆栈,深入剖析如何从零构建一套具备生产力的高性能多智能体协同 RAG 系统。我们将从底层的实体关系建模、核心组件的原子化开发,一直演进到多智能体拓扑网络的编排与生产级性能优化,并提供完整的、可直接运行的代码解析。
2. 核心架构设计:从单体RAG到多智能体协同网络
2.1 单体RAG的阿喀琉斯之踵
传统的流水线RAG是一个线性的串行系统。用户提出查询,系统将其转化为向量,在向量数据库中匹配出相似度最高的若干文档片段,直接喂给LLM生成回答。在这个过程中,任何一个环节的失效都会导致全局性灾难:
- 意图模糊:用户输入"对比去年和今年的财务报表",单体系统通常会直接检索同时包含"去年"和"今年"的片段,而无法将其拆解为两个独立的检索子任务。
- 检索噪音:PDF中的页眉、页脚、表格错位等噪声会被无差别向量化,导致检索噪音。
- 无法自我迭代:LLM发现检索到的文档无法回答用户问题时,只能生硬地回答"抱歉,知识库中没有相关内容"。
2.2 多智能体网络(Multi-Agent Topology)的崛起
多智能体协同架构引入了分布式治理的思想。每个Agent都是一个独立的决策单元,拥有自己的System Prompt、特有的工具集(Tools)以及独立的记忆(Memory)空间。在多智能体RAG网络中,核心拓扑结构通常由以下几类智能体构成:
- 路由智能体(Router Agent):负责理解用户的高级意图,判断是否需要调用知识库,或者将任务分发给哪个特定的知识库分片。
- 检索与分析智能体(Retrieval & Analysis Agent):专门负责多源数据的检索,不仅包括向量数据库,还涵盖图数据库、关系型数据库(通过Text-to-SQL)以及Web搜索工具。
- 核验与反思智能体(Critic / Reflection Agent):这是质量把关者。它会评估检索到的文档与查询的相关性(Graundedness),以及生成的回答是否忠实于原文(Faithfulness),若不达标则触发重试流程。
- 编排智能体(Orchestrator / Supervisor Agent):负责整个图网络的状管理,控制Agent之间的流转跳转与Token熔断。
下面我们通过一张完整的系统拓扑与数据流图,展示整个系统是如何通过有向无环图(DAG)或有环状态图进行协同的:
[User Query] ──> (Router Agent)
│
├───> [Intent: Simple] ──> (Vector Search Agent) ──> (Critic Agent) ──> [Success] ──> [Output]
│ │
│ [Fail]
│ │
│ v
│ (Query Rewriter Agent)
│ │
└───> [Intent: Complex] ──> (Supervisor Agent) │
│ │
┌────────────────┴────────────────┐ │
v v v
(Financial Data Agent) (Market Research Agent)
│ │
└────────────────┬────────────────┘
v
(Synthesis Agent) ──> [Output]
3. 数据库与知识表示:企业级知识库的向量化与关系建模
在一个生产级的 RAG 系统中,单一的向量数据往往无法承载实体之间的复杂关系。例如,在分析"公司的某项核心技术由哪个研发团队负责,该团队的预算审批人是谁"这类多跳(Multi-Hop)问题时,关系型数据或图数据比纯向量更具表现力。因此,混合存储架构(Hybrid Storage Architecture)成为行业标准。
为了清晰表达系统的后端数据存储结构,我们需要对其进行实体关系(ER)建模。系统需要同时管理用户对话状态、知识库文档元数据、文档切片(Chunks)及其对应的向量索引关系。
3.1 实体关系图(ER Diagram)
以下是系统底层数据模型的 Mermaid ER 图表示。它涵盖了知识库、文档、分片、向量关联以及Agent执行审计日志的核心拓扑:
#mermaid-svg-w2uKpX950t5fAyVD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-w2uKpX950t5fAyVD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-w2uKpX950t5fAyVD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-w2uKpX950t5fAyVD .error-icon{fill:#552222;}#mermaid-svg-w2uKpX950t5fAyVD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-w2uKpX950t5fAyVD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-w2uKpX950t5fAyVD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-w2uKpX950t5fAyVD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-w2uKpX950t5fAyVD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-w2uKpX950t5fAyVD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-w2uKpX950t5fAyVD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-w2uKpX950t5fAyVD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-w2uKpX950t5fAyVD .marker.cross{stroke:#333333;}#mermaid-svg-w2uKpX950t5fAyVD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-w2uKpX950t5fAyVD p{margin:0;}#mermaid-svg-w2uKpX950t5fAyVD .entityBox{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-w2uKpX950t5fAyVD .relationshipLabelBox{fill:hsl(80, 100%, 96.2745098039%);opacity:0.7;background-color:hsl(80, 100%, 96.2745098039%);}#mermaid-svg-w2uKpX950t5fAyVD .relationshipLabelBox rect{opacity:0.5;}#mermaid-svg-w2uKpX950t5fAyVD .labelBkg{background-color:rgba(248.6666666666, 255, 235.9999999999, 0.5);}#mermaid-svg-w2uKpX950t5fAyVD .edgeLabel .label{fill:#9370DB;font-size:14px;}#mermaid-svg-w2uKpX950t5fAyVD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-w2uKpX950t5fAyVD .edge-pattern-dashed{stroke-dasharray:8,8;}#mermaid-svg-w2uKpX950t5fAyVD .node rect,#mermaid-svg-w2uKpX950t5fAyVD .node circle,#mermaid-svg-w2uKpX950t5fAyVD .node ellipse,#mermaid-svg-w2uKpX950t5fAyVD .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-w2uKpX950t5fAyVD .relationshipLine{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-w2uKpX950t5fAyVD .marker{fill:none!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-w2uKpX950t5fAyVD .edgeLabel{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-w2uKpX950t5fAyVD .edgeLabel .label rect{fill:rgba(232,232,232, 0.8);}#mermaid-svg-w2uKpX950t5fAyVD .edgeLabel .label text{fill:#333;}#mermaid-svg-w2uKpX950t5fAyVD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} contains
splits_into
indexes
records
triggers
KNOWLEDGE_BASE
string
id
PK
string
name
string
description
timestamp
created_at
DOCUMENT
string
id
PK
string
kb_id
FK
string
title
string
file_path
string
file_type
string
hash_code
DOCUMENT_CHUNK
string
id
PK
string
doc_id
FK
text
content
int
chunk_index
int
token_count
json
metadata
VECTOR_INDEX
string
chunk_id
PK,FK
string
vector_provider
string
model_name
binary
embedding_vector
USER_SESSION
string
session_id
PK
string
user_id
timestamp
started_at
string
status
AGENT_LOG
string
log_id
PK
string
session_id
FK
string
agent_name
string
input_payload
string
output_payload
int
execution_time_ms
timestamp
executed_at
RETRIEVAL_AUDIT
string
audit_id
PK
string
log_id
FK
string
chunk_id
FK
float
similarity_score
int
rerank_rank
3.2 数据结构设计原则与字段解析
- DOCUMENT_CHUNK 中的
hash_code与metadata:生产环境中的文档是动态更新的。通过对 file 内容计算 MD5 或 SHA-256 哈希值,可以有效避免重复切片与重复向量化,大幅节省 Embedding 算力。metadata字段则使用 JSON 格式存储,用于存放诸如创建时间、作者、权限控制等级(ACL)等非结构化元数据,以便在检索阶段进行确定性的精确布尔过滤(Hard Filtering)。 - VECTOR_INDEX 的解耦 :将向量数据与文本分片独立开来,允许系统在不改变文本存储的前提下,无缝升级 Embedding 模型(例如从
text-embedding-3-small升级到本地部署的bge-large-zh-v1.5)。 - AGENT_LOG 与 RETRIEVAL_AUDIT 的审计审计线索:由于多智能体系统具有明显的随机性(Stochastic Nature),对每一个智能体节点的输入、输出、耗时,以及检索时的原始相似度得分(Similarity Score)与重排得分(Rerank Score)进行落库持久化,是后期进行 Ragas 自动化评估以及系统调优(Prompt Engineering / Fine-Tuning)的唯一数据来源。
4. 核心组件开发:基于Python与LangChain/LangGraph的原子化实现
在明确了架构与数据模型后,我们进入代码编写阶段。本节将采用 Python 现代异步编程生态(asyncio),结合 LangChain 与 LangGraph,实现系统的底层原子组件。
4.1 混合文档解析与高阶动态切片器(Advanced Text Splitter)
传统的固定窗口切片(Fixed-Size Chunking)极易切断上下文。我们将编写一个基于语义关联度的动态切片组件,支持 Markdown 标题感知与递归字符分块。
python
import re
import uuid
import hashlib
from typing import List, Dict, Any
import asyncio
class SmartDocumentProcessor:
def __init__(self, chunk_size: int = 800, chunk_overlap: int = 150):
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
def calculate_md5(self, text: str) -> str:
return hashlib.md5(text.encode('utf-8')).hexdigest()
def clean_text(self, text: str) -> str:
text = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', text)
text = re.sub(r' +', ' ', text)
return text.strip()
def split_by_markdown_headings(self, text: str) -> List[Dict[str, Any]]:
cleaned_text = self.clean_text(text)
lines = cleaned_text.split("\n")
chunks = []
current_headers = {"h1": "", "h2": "", "h3": ""}
buffer = []
current_tokens = 0
for line in lines:
h1_match = re.match(r'^#\s+(.*)', line)
h2_match = re.match(r'^##\s+(.*)', line)
h3_match = re.match(r'^###\s+(.*)', line)
if h1_match:
current_headers["h1"] = h1_match.group(1)
current_headers["h2"] = ""
current_headers["h3"] = ""
elif h2_match:
current_headers["h2"] = h2_match.group(1)
current_headers["h3"] = ""
elif h3_match:
current_headers["h3"] = h3_match.group(1)
line_tokens = len(line)
if current_tokens + line_tokens > self.chunk_size and buffer:
chunk_content = "\n".join(buffer)
chunks.append({
"id": str(uuid.uuid4()),
"content": chunk_content,
"metadata": current_headers.copy(),
"token_count": current_tokens
})
overlap_lines = buffer[-2:] if len(buffer) > 2 else buffer
buffer = list(overlap_lines)
current_tokens = sum(len(l) for l in buffer)
buffer.append(line)
current_tokens += line_tokens
if buffer:
chunks.append({
"id": str(uuid.uuid4()),
"content": "\n".join(buffer),
"metadata": current_headers.copy(),
"token_count": current_tokens
})
return chunks
4.2 高级异步向量搜索引擎(Milvus / Qdrant 封装)
在生产环境中,同步阻塞地向向量数据库查询数据会导致严重的I/O等待。以下代码展示了如何基于 Python 异步上下文管理器,构建一个支持双路混合检索与硬过滤的高性能向量检索客户端。
python
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
import numpy as np
class AsyncVectorStoreClient:
def __init__(self, host: str = "localhost", port: int = 6333):
self.client = QdrantClient(host=host, port=port, timeout=10.0)
self.collection_name = "enterprise_knowledge_net"
async def init_collection(self, vector_dim: int = 1536):
loop = asyncio.get_running_loop()
def _init():
if not self.client.collection_exists(collection_name=self.collection_name):
self.client.create_collection(
collection_name=self.collection_name,
vectors_config=VectorParams(size=vector_dim, distance=Distance.COSINE),
)
await loop.run_in_executor(None, _init)
async def upsert_chunks(self, chunks: List[Dict[str, Any]], embeddings: List[List[float]]):
loop = asyncio.get_running_loop()
def _upsert():
points = []
for idx, chunk in enumerate(chunks):
points.append(PointStruct(
id=chunk["id"],
vector=embeddings[idx],
payload={
"content": chunk["content"],
"token_count": chunk["token_count"],
**chunk["metadata"]
}
))
self.client.upsert(collection_name=self.collection_name, points=points)
await loop.run_in_executor(None, _upsert)
async def hybrid_search(self, query_vector: List[float], filter_dict: Dict[str, Any] = None, top_k: int = 5) -> List[Dict[str, Any]]:
loop = asyncio.get_running_loop()
must_conditions = []
if filter_dict:
for key, val in filter_dict.items():
if val:
must_conditions.append(FieldCondition(key=key, match=MatchValue(value=val)))
query_filter = Filter(must=must_conditions) if must_conditions else None
def _search():
search_result = self.client.search(
collection_name=self.collection_name,
query_vector=query_vector,
query_filter=query_filter,
limit=top_k,
with_payload=True
)
return [{
"id": hit.id,
"score": hit.score,
"content": hit.payload["content"],
"metadata": {k: v for k, v in hit.payload.items() if k != "content"}
} for hit in search_result]
return await loop.run_in_executor(None, _search)
5. 多智能体协同机制:任务编排、状态管理与反思路由
5.1 全局状态定义与代理实体声明
python
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage
class AgentGraphState(TypedDict):
original_query: str
revised_query: str
retrieved_documents: Annotated[List[Dict[str, Any]], operator.add]
evaluation_score: float
reflection_feedback: str
generation_output: str
loop_count: int
messages: Annotated[Sequence[BaseMessage], operator.add]
5.2 核心节点逻辑原子化实现
python
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
class GradeQuestionRelevance(BaseModel):
binary_score: str = Field(description="文档与问题是否相关? 可选值为 'yes' 或 'no'")
explanation: str = Field(description="给出打分的详细依据与原因")
class AsyncMultiAgentSystem:
def __init__(self, vector_client: AsyncVectorStoreClient):
self.vector_client = vector_client
self.llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
async def node_rewrite_query(self, state: AgentGraphState) -> Dict[str, Any]:
query = state["original_query"]
loop_cnt = state.get("loop_count", 0)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个资深的搜索引擎优化专家。请分析用户的原始输入,消除歧义,并补充潜在的行业专业近义词。请直接返回优化后的单行查询文本,不需要任何解释。"),
("human", f"当前循环次数: {loop_cnt}。请重写此查询: {query}")
])
chain = prompt | self.llm
response = await chain.ainvoke({})
return {
"revised_query": response.content.strip(),
"loop_count": loop_cnt + 1
}
async def node_retrieve(self, state: AgentGraphState) -> Dict[str, Any]:
query_to_search = state["revised_query"]
mock_vector = list(np.random.rand(1536).astype(float))
docs = await self.vector_client.hybrid_search(query_vector=mock_vector, top_k=4)
return {"retrieved_documents": docs}
async def node_criticize(self, state: AgentGraphState) -> Dict[str, Any]:
query = state["original_query"]
docs = state["retrieved_documents"]
if not docs:
return {"evaluation_score": 0.0, "reflection_feedback": "未检索到任何有效文档,必须重试。"}
doc_context = "\n\n".join([f"文档片段:
{d['content']}" for d in docs])
structured_llm = self.llm.with_structured_output(GradeQuestionRelevance)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个极度严苛的审计官。你需要评估给定的文档上下文是否足以回答用户的原始问题。"),
("human", f"原始问题: {query}
检索到的文档上下文:
{doc_context}")
])
try:
result = await structured_llm.ainvoke(prompt.format_messages())
score = 1.0 if result.binary_score.lower() == "yes" else 0.0
return {
"evaluation_score": score,
"reflection_feedback": result.explanation
}
except Exception as e:
return {
"evaluation_score": 0.0,
"reflection_feedback": f"结构化审计出错: {str(e)}"
}
async def node_generate_answer(self, state: AgentGraphState) -> Dict[str, Any]:
query = state["original_query"]
docs = state["retrieved_documents"]
doc_context = "\n\n".join([d['content'] for d in docs])
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业、严谨的企业AI助手。请基于提供的参考文档回答用户的问题。如果文档中没有相关信息,请直接说明,绝不胡编乱造。"),
("human", f"问题: {query}
权威参考凭据:
{doc_context}")
])
chain = prompt | self.llm
response = await chain.ainvoke({})
return {"generation_output": response.content}
5.3 编排逻辑与有向条件图构建
python
from langgraph.graph import StateGraph, END
def router_decision_edge(state: AgentGraphState):
score = state["evaluation_score"]
loop_cnt = state.get("loop_count", 0)
if loop_cnt >= 3:
return "goto_generate"
if score >= 0.8:
return "goto_generate"
else:
return "goto_rewrite"
def build_workflow(system_manager: AsyncMultiAgentSystem) -> StateGraph:
workflow = StateGraph(AgentGraphState)
workflow.add_node("rewrite_query", system_manager.node_rewrite_query)
workflow.add_node("retrieve_docs", system_manager.node_retrieve)
workflow.add_node("criticize_docs", system_manager.node_criticize)
workflow.add_node("generate_answer", system_manager.node_generate_answer)
workflow.set_entry_point("rewrite_query")
workflow.add_edge("rewrite_query", "retrieve_docs")
workflow.add_edge("retrieve_docs", "criticize_docs")
workflow.add_conditional_edges(
"criticize_docs",
router_decision_edge,
{
"goto_rewrite": "rewrite_query",
"goto_generate": "generate_answer"
}
)
workflow.add_edge("generate_answer", END)
return workflow.compile()
6. 生产级优化:查询重写、混合检索与重排序(Reranking)
6.1 工业级重排序开发
python
import httpx
from typing import Optional
class ProductionReranker:
def __init__(self, api_url: str = "http://localhost:8000/v1/rerank", api_key: Optional[str] = None):
self.api_url = api_url
self.api_key = api_key
self.http_client = httpx.AsyncClient(timeout=5.0, limits=httpx.Limits(max_connections=50))
async def rerank_documents(self, query: str, documents: List[Dict[str, Any]], top_n: int = 3) -> List[Dict[str, Any]]:
if not documents:
return []
payload = {
"query": query,
"texts": [doc["content"] for doc in documents],
"truncate": True
}
headers = {"Content-Type": "application/json"}
if self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"
try:
response = await self.http_client.post(self.api_url, json=payload, headers=headers)
if response.status_code != 200:
return documents[:top_n]
rerank_results = response.json()
reranked_docs = []
for item in rerank_results[:top_n]:
original_idx = item["index"]
target_doc = documents[original_idx].copy()
target_doc["rerank_score"] = item["score"]
reranked_docs.append(target_doc)
return reranked_docs
except Exception as e:
print(f"[警告] Reranker服务通信异常: {str(e)}。执行原生降级机制。")
return documents[:top_n]
async def close(self):
await self.http_client.aclose()
7. 完整项目实战与工作流驱动
python
import asyncio
import numpy as np
async def main():
print("====== 1. 初始化底座高性能向量数据库 ======")
vector_store = AsyncVectorStoreClient()
await vector_store.init_collection(vector_dim=1536)
print("\n====== 2. 模拟真实环境下的企业级文档摄入流程 ======")
raw_document = """
# 狂风科技集团企业核心网络安全合规白皮书
## 1. 认证与鉴权规范
所有企业级核心微服务系统在处理外部请求时,必须实施强有力的统一身份认证。
当前系统强制要求采用 OAuth2.0 框架下的 JWT (JSON Web Token) 机制。
所有的访问令牌(Access Token)的生存周期(TTL)必须严格限制为 1800秒(即30分钟)。
一旦令牌过期,客户端必须使用安全的刷新令牌(Refresh Token)重新获取,刷新令牌的最长有效期为7天。
"""
processor = SmartDocumentProcessor(chunk_size=300, chunk_overlap=50)
processed_chunks = processor.split_by_markdown_headings(raw_document)
mock_embeddings = [list(np.random.rand(1536).astype(float)) for _ in processed_chunks]
await vector_store.upsert_chunks(processed_chunks, mock_embeddings)
print("\n====== 3. 组装多智能体系统并进行图编译 ======")
agent_system = AsyncMultiAgentSystem(vector_client=vector_store)
compiled_graph = build_workflow(agent_system)
print("\n====== 4. 模拟复杂长尾线上查询,触发Agent网络流转 ======")
user_query = "集团合规白皮书中对JWT访问令牌的有效时间是怎么规定的?如果过期了怎么办?"
initial_state: AgentGraphState = {
"original_query": user_query,
"revised_query": "",
"retrieved_documents": [],
"evaluation_score": 0.0,
"reflection_feedback": "",
"generation_output": "",
"loop_count": 0,
"messages": []
}
final_output_state = await compiled_graph.ainvoke(initial_state)
print(f"最终判定得分 (Evaluation Score): {final_output_state['evaluation_score']}")
print(f"总计迭代反思循环次数 (Loop Count): {final_output_state['loop_count']}")
print(f"智能体网络最终输出 (Generation Output):\n{final_output_state['generation_output']}")
if __name__ == "__main__":
asyncio.run(main())
8. 性能评估与监控:Ragas度量与LangSmith追踪
单纯靠人工主观"盲测"是无法保障系统健壮性的。行业标准的自动化评估框架(如 Ragas)提出了四个最为核心的黄金度量指标:
- 忠实度 (Faithfulness):评估生成的回答是否全部基于检索到的文档上下文。
- 回答相关性 (Answer Relevance):评估最终生成的文本是否真正切中用户提问的要害。
- 上下文召回率 (Context Recall):评估为了完美回答这个问题,所需要的全部核心事实是否有被检索智能体成功拉取。
- 上下文精准度 (Context Precision):评估检索到的无关噪声片段的占比。
9. 总结与未来演进
多智能体架构的本质是通过解耦和引入显式状态机,对抗大语言模型本身的随机性和不稳定性。通过实现"重写-检索-反思-生成"的完整闭环图拓扑,系统具备了极高的线上鲁棒性,是当今企业私有知识库升级的不二之选。