2026奇点大会核心突破全披露(AI正则生成技术白皮书首曝)
2026/4/17 16:33:05
在大模型应用中,检索增强生成(RAG,Retrieval-Augmented Generation)是一种强大的技术,它通过将外部知识库与大模型结合,使得模型能够基于真实数据生成更准确的回答。本文将详细讲解如何使用LangChain + LangGraph + DashScope + Milvus的技术栈,从零开始构建一个完整的传统 RAG Agent。
┌─────────────────┐ │ 原始文档 │ │ (company.txt) │ └────────┬────────┘ │ ▼ ┌──────────────────────────┐ │ 文本分割器 │ │ (RecursiveCharacterTS) │ └────────┬─────────────────┘ │ ▼ ┌──────────────────────────┐ │ 向量化 (Embeddings) │ │ (DashScope Embeddings) │ └────────┬─────────────────┘ │ ▼ ┌──────────────────────────┐ │ 向量数据库 (Milvus) │ │ 存储与检索向量索引 │ └────────┬─────────────────┘ │ ▼ ┌──────────────────────────┐ │ RAG Chain │ │ 检索 + 提示词 + LLM │ └────────┬─────────────────┘ │ ▼ ┌──────────────────────────┐ │ LangGraph Agent │ │ (集成多代理系统) │ └──────────────────────────┘importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_community.embeddingsimportDashScopeEmbeddingsfromlangchain_milvusimportMilvusfromlangchain_core.promptsimportPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.documentsimportDocumentfromlangchain_core.messagesimportHumanMessagefromlanggraph.graphimportStateGraph,MessagesState,START,END load_dotenv()key=os.getenv("DASHSCOPE_API_KEY")base_url=os.getenv("DASHSCOPE_API_BASE").env文件安全地存储 API 密钥,避免硬编码敏感信息langchain_text_splitters而非langchain.text_splitter(LangChain 0.2+ 的变化)DashScopeEmbeddings而非 OpenAI Embeddingsgraph_llm=ChatOpenAI(temperature=0,model_name="qwen-plus-2025-12-01",api_key=key,base_url=base_url)llm=ChatOpenAI(temperature=0,model_name="qwen-plus",api_key=key,base_url=base_url)| 参数 | 含义 | 取值 |
|---|---|---|
temperature | 输出随机性 | 0 = 确定性(适合RAG), 1 = 创意性 |
model_name | 模型版本 | qwen-plus(基础)/ qwen-plus-2025-12-01(增强) |
api_key | 身份认证 | 从.env读取(不显示实际密钥) |
base_url | API 端点 | 通义千问 API 基址(从.env读取) |
# Step 1: 加载文档withopen('../doc/company.txt','r',encoding="utf-8")asfile:content=file.read()documents=[Document(page_content=content)]# Step 2: 文本分割chunk_size=250chunk_overlap=30text_splitter=RecursiveCharacterTextSplitter(chunk_size=chunk_size,chunk_overlap=chunk_overlap)splits=text_splitter.split_documents(documents)# Step 3: 初始化 Embeddingsembeddings=DashScopeEmbeddings(model="text-embedding-v4",dashscope_api_key=key# 从环境变量读取)# Step 4: 构建向量索引vectorstore=Milvus.from_documents(documents=splits,collection_name="company_milvus",embedding=embeddings,connection_args={"uri":os.getenv("MILVUS_URI"),# 从环境变量读取"user":os.getenv("MILVUS_USER"),# 从环境变量读取"password":os.getenv("MILVUS_PASSWORD"),# 从环境变量读取})这里向量库可以考虑在线。
这里我们同样使用免费的在线milvus实例,地址如下:https://cloud.zilliz.com/login?redirect=/orgs , 先注册登录
创建索引:
选择免费实例:保存好用户密码:
文本块 ↓ DashScope Embeddings (文本向量化) ↓ 向量 (1024 维) ↓ Milvus (向量存储与索引) ↓ HNSW/IVF 索引结构 ↓ 支持快速相似度检索# Step 5: 创建 RAG Chainprompt=PromptTemplate(template="""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise: Question: {question} Context: {context} Answer: """,input_variables=["question","context"],)rag_chain=prompt|graph_llm|StrOutputParser()用户问题 + 检索上下文 ↓ PromptTemplate (格式化) ↓ ChatOpenAI (推理) ↓ StrOutputParser (解析输出) ↓ 最终回答# Step 6: 测试question="我的知识库中都有哪些公司信息"retriever=vectorstore.as_retriever(search_kwargs={"k":1})docs=retriever.invoke(question)generation=rag_chain.invoke({"context":docs,"question":question})print(f"生成的答案:{generation}")| 步骤 | 操作 | 输出 |
|---|---|---|
| 1 | 问题向量化 | 1024 维向量 |
| 2 | Milvus 相似度搜索 | Top-k 最相关文本块 |
| 3 | 构建提示词 | 格式化后的完整提示 |
| 4 | 调用大模型 | 结构化回答 |
| 5 | 解析输出 | 纯文本答案 |
# Step 7: 定义 AgentStateclassAgentState(MessagesState):next:str# Step 8: 创建 vec_kg Agent 节点defvec_kg(state:AgentState):messages=state["messages"][-1]question=messages.content prompt=PromptTemplate(template="""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise: Question: {question} Context: {context} Answer: """,input_variables=["question","context"],)rag_chain=prompt|graph_llm|StrOutputParser()retriever=vectorstore.as_retriever(search_kwargs={"k":1})docs=retriever.invoke(question)generation=rag_chain.invoke({"context":docs,"question":question})final_response=[HumanMessage(content=generation,name="vec_kg")]return{"messages":final_response}状态输入 (消息列表) ↓ 提取最后一条消息作为问题 ↓ 执行 RAG Chain (检索 + 推理) ↓ 包装为 HumanMessage (带 vec_kg 标识) ↓ 返回更新后的状态next字段控制代理流向# Step 9: 测试 vec_kg 节点if__name__=="__main__":test_state=AgentState(messages=[HumanMessage(content="我的知识库中都有哪些公司信息")])result=vec_kg(test_state)print(f"RAG Agent 响应:{result}")用户问题 → [检索] 相关文档 → [融合] 上下文 → [生成] 准确答案| 方案 | 检索方式 | 优点 | 缺点 |
|---|---|---|---|
| 全文搜索 | 关键词匹配 | 速度快 | 语义理解差 |
| 向量相似度 | 语义匹配 | 准确度高 | 需要计算成本 |
本项目选择向量方案:基于语义理解,适合复杂问题
| 特性 | DashScope | OpenAI |
|---|---|---|
| 成本 | 更便宜 | 较贵 |
| 语言 | 中文优化 | 英文优先 |
| 维度 | 1024 维 | 1536 维 |
| 部署 | 国内快速 | 需科学上网 |
# 结合向量检索 + BM25 关键词检索results=vectorstore.similarity_search_with_score(question,k=5)bm25_results=bm25_retriever.get_relevant_documents(question)combined=merge_and_rerank(results,bm25_results)# 组合图数据库 + 向量数据库 + 传统数据库supervisor_agent.route_to([graph_kg,vec_kg,db_agent])# 使用少样本学习 (Few-shot)template=""" 示例 1:... 示例 2:... 用户问题:{question} """原因:chunk_size 过大或过小
解决:调整分割参数 (推荐 200-500)
原因:检索文档不足或提示词不强制
解决:
# 强制模型只基于上下文回答template+="If the context is not helpful, just say you don't know."原因:Milvus 索引未优化或网络延迟
解决:
# 增加 batch 处理或缓存cache_layer=caching_decorator(rag_chain)本文展示了构建一个完整的传统 RAG Agent 的全过程:
这个系统可以立即用于:
下一步可以考虑引入GraphRAG(图知识库)以处理更复杂的关系推理任务,构建混合知识库系统!
完整代码贴上:
importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_community.embeddingsimportDashScopeEmbeddingsfromlangchain_milvusimportMilvusfromlangchain_core.promptsimportPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.documentsimportDocumentfromlangchain_core.messagesimportHumanMessagefromlanggraph.graphimportStateGraph,MessagesState,START,END# 加载环境变量load_dotenv()key=os.getenv("DASHSCOPE_API_KEY")base_url=os.getenv("DASHSCOPE_API_BASE")# 初始化 LLMgraph_llm=ChatOpenAI(temperature=0,model_name="qwen-plus-2025-12-01",api_key=key,base_url=base_url)llm=ChatOpenAI(temperature=0,model_name="qwen-plus",api_key=key,base_url=base_url)# 3.4 创建传统 RAG Agent# Step 1: 加载文档并分割withopen('../doc/company.txt','r',encoding="utf-8")asfile:content=file.read()documents=[Document(page_content=content)]# Step 2: 文本分割chunk_size=250chunk_overlap=30text_splitter=RecursiveCharacterTextSplitter(chunk_size=chunk_size,chunk_overlap=chunk_overlap)splits=text_splitter.split_documents(documents)# Step 3: 初始化 Embeddingsembeddings=DashScopeEmbeddings(model="text-embedding-v4",dashscope_api_key=key)# Step 4: 构建向量索引并存储到 Milvusvectorstore=Milvus.from_documents(documents=splits,collection_name="company_milvus",embedding=embeddings,connection_args={"uri":"https://xxxxxxxxxxxxxxx.serverless.gcp-us-west1.cloud.zilliz.com","user":"xxxxxxxxx",# 替换为自己的"password":"xxxxxx",})# Step 5: 创建 RAG Chainprompt=PromptTemplate(template="""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise: Question: {question} Context: {context} Answer: """,input_variables=["question","context"],)rag_chain=prompt|graph_llm|StrOutputParser()# Step 6: 测试 RAG Chainquestion="我的知识库中都有哪些公司信息"retriever=vectorstore.as_retriever(search_kwargs={"k":1})docs=retriever.invoke(question)generation=rag_chain.invoke({"context":docs,"question":question})print(f"生成的答案:{generation}")# Step 7: 定义 AgentStateclassAgentState(MessagesState):next:str# Step 8: 创建传统 RAG 的 Agent 节点defvec_kg(state:AgentState):messages=state["messages"][-1]question=messages.content prompt=PromptTemplate(template="""You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise: Question: {question} Context: {context} Answer: """,input_variables=["question","context"],)# 构建传统的RAG Chainrag_chain=prompt|graph_llm|StrOutputParser()# 构建检索器retriever=vectorstore.as_retriever(search_kwargs={"k":1})# 执行检索docs=retriever.invoke(question)generation=rag_chain.invoke({"context":docs,"question":question})final_response=[HumanMessage(content=generation,name="vec_kg")]return{"messages":final_response}# Step 9: 测试 vec_kg 节点if__name__=="__main__":test_state=AgentState(messages=[HumanMessage(content="我的知识库中都有哪些公司信息")])result=vec_kg(test_state)print(f"RAG Agent 响应:{result}")