LangChain+通义千问 RAG知识库问答代码

前置说明:这份代码是LangChain 1.0最新主流写法,实现的是RAG(检索增强生成)核心逻辑,也是LLM落地最实用的入门案例。掌握本案例后可快速搭建属于自己的知识库问答机器人。

✅ 先搞懂【整体功能】

这份代码的核心作用是搭建一个「宠物知识库问答助手」,核心逻辑为「先检索、再回答」,与普通AI问答存在本质区别:

  1. 普通AI问答:大模型凭借自身知识库回答,易出现胡说八道、答非所问的情况;

  2. RAG知识库问答:先从指定资料中筛选与问题相关的内容,再让大模型基于筛选出的资料回答,确保回答绝对精准、有据可依、不编造内容;

  3. 核心效果:例如提问「金鱼适合什么样的人养?」,程序会先从准备好的宠物资料中提取金鱼相关知识点,再让通义千问基于该知识点作答,不会偏离主题或编造饲养规则。

✅ 核心前置认知(3个必懂概念)

① 什么是 RAG ?(检索增强生成)

RAG是「检索+生成」的组合,是解决大模型「胡说八道」的最优解,核心三步为:

用户提问 → 第一步【检索】:从本地知识库查找与问题最相似的资料 → 第二步【生成】:让大模型严格基于找到的资料回答问题

核心价值:让AI的回答有依据、不编造、百分百贴合指定资料,是知识库问答、文档问答的核心技术。

② 向量库 & 嵌入模型 到底是干嘛的?

这是RAG的核心,用大白话解释如下:

  • 嵌入模型(Embeddings):即「文字转数字」的工具。计算机无法直接理解文字,但能识别数字,嵌入模型可将每一句话(如「金鱼是冷水鱼」)转换为一串固定长度的数字(向量),意思越相似的文字,转换后的向量越接近;

  • 向量库(Chroma):即「存向量的数据库」。将知识库文本转成向量后存入向量库,用户提问时,先将问题也转成向量,向量库会快速匹配出与问题向量最相似的文本向量,对应的文本就是最相关的资料。

总结:嵌入模型负责「转码」,向量库负责「检索相似内容」,二者缺一不可。

③ LangChain 1.0 核心:管道符 | 串联一切

LangChain将所有功能(检索器、提示词、模型、解析器)封装成「可运行节点」,通过 | 管道符串联,左边的输出自动作为右边的输入,无需手动传参,代码简洁且逻辑清晰。

核心逻辑:用户问题 → 检索资料 → 填充提示词 → 调用大模型 → 格式化输出

-------------- 1. 基础库导入 --------------


# Python内置的操作系统模块,用于环境变量操作
import os
# 从自定义的config.py文件中导入通义千问的API密钥(你的密钥存在这里)
from config import DASHSCOPE_API_KEY

代码解读(作用+原理)

此部分为基础导入,两行代码的作用明确:

  1. import os:导入Python自带的os模块,此处仅用于将API密钥设置为系统环境变量,方便后续通义千问SDK自动读取密钥完成鉴权;

  2. from config import DASHSCOPE_API_KEY:从自定义的config.py文件中导入密钥,这是规范的密钥管理方式,可避免密钥直接写在主代码中导致泄露。

补充:config.py文件仅需包含一行代码:DASHSCOPE_API_KEY = “你的通义千问密钥”。

-------------- 2. LangChain核心组件导入 --------------


# 1. 向量数据库:Chroma是轻量级本地向量库,无需部署,适合测试
from langchain_community.vectorstores import Chroma
# 2. 嵌入模型:DashScopeEmbeddings是通义千问的文本转向量工具
#    作用:把文字(如"猫咪性格高冷")转换成计算机能理解的向量数字
from langchain_community.embeddings import DashScopeEmbeddings
# 3. 大模型调用工具:ChatTongyi是通义千问的LLM调用入口
#    作用:连接通义千问大模型,发送指令并获取回答
from langchain_community.chat_models import ChatTongyi
# 4. 提示词模板:ChatPromptTemplate用于定义固定的提问格式
#    作用:约束AI的回答规则,比如"只能用参考资料回答,禁止编造"
from langchain_core.prompts import ChatPromptTemplate
# 5. 数据透传工具:RunnablePassthrough用于传递用户原始问题
#    作用:不用手动写函数,直接把用户问题传给提示词模板
from langchain_core.runnables import RunnablePassthrough
# 6. 输出格式化工具:StrOutputParser用于格式化AI的输出
#    作用:把模型返回的复杂对象转换成纯字符串,方便打印查看
from langchain_core.output_parsers import StrOutputParser
# 7. 文档标准类:Document是LangChain的统一文档格式
#    作用:包装文本内容和元数据(如来源),让向量库能识别
from langchain_core.documents import Document

代码解读(逐组件解析)

此部分导入了实现RAG的所有核心组件,共7个,按功能分类解读如下,便于理解和记忆:

  1. 向量库相关:Chroma,轻量级本地向量库,无需安装部署,直接可用,是新手学习测试的首选;

  2. 嵌入模型相关:DashScopeEmbeddings,阿里云官方的嵌入模型,专门适配通义千问,负责将知识库文字转换为向量;

  3. 大模型相关:ChatTongyi,LangChain封装的通义千问聊天模型调用入口,无需编写原生调用代码,更贴合LangChain的链式写法,使用便捷;

  4. 提示词相关:ChatPromptTemplate,用于定义AI的回答规则,例如约束AI必须基于参考资料回答,是保证回答精准的核心组件;

  5. 数据传递相关:RunnablePassthrough,即数据透传器,可将用户原始问题原封不动地传递到提示词模板的指定位置,无需手动编写传递函数,简化代码;

  6. 输出处理相关:StrOutputParser,用于将大模型返回的复杂嵌套对象转换为纯字符串,便于直接打印查看;

  7. 文档格式相关:Document,LangChain的统一文档标准类,向量库Chroma仅识别该格式数据,需用其包装知识库内容和附加信息,确保向量库能正确存入和检索。

-------------- 3. 配置API密钥 --------------


# 将API密钥设置为环境变量,确保通义千问的SDK能读取到
os.environ["DASHSCOPE_API_KEY"] = DASHSCOPE_API_KEY

代码解读(作用+必要性)

此行代码的核心作用是将通义千问密钥设置为系统环境变量,其必要性在于:后续使用的DashScopeEmbeddings(嵌入模型)和ChatTongyi(大模型),底层会自动读取该环境变量中的密钥完成身份验证,证明用户有权调用阿里云的模型。

补充:除了设置环境变量,后续初始化模型时也可显式传入密钥,采用双重保险的方式,可避免密钥读取失败。此代码为鉴权前置步骤,必须编写,否则后续所有模型调用都会报「Invalid api key」错误。

-------------- 4. 准备示例文档 --------------


# 用Document类包装我们的宠物资料,每个Document对应一条知识
# page_content:核心文本内容;metadata:附加信息(如来源、分类)
sample_docs = [
    Document(
        page_content="狗狗是群居动物,性格活泼,需要每天遛弯,忠诚度高,适合作为陪伴宠物。",
        metadata={"source": "宠物手册-犬类"}
    ),
    Document(
        page_content="猫咪是独居动物,性格高冷,爱干净,不需要频繁遛弯,适合喜欢安静的饲养者。",
        metadata={"source": "宠物手册-猫类"}
    ),
    Document(
        page_content="金鱼是冷水鱼,饲养时需要注意鱼缸水质清洁,喂食不宜过多,寿命一般3-5年。",
        metadata={"source": "宠物手册-鱼类"}
    ),
    Document(
        page_content="仓鼠是啮齿类动物,夜间活动,主食为谷物和坚果,饲养空间需要通风干燥。",
        metadata={"source": "宠物手册-啮齿类"}
    )
]

代码解读(结构+作用)

此部分用于准备知识库内容,是程序的数据源,AI的所有回答均来源于此,核心细节如下:

  1. Document类的固定格式:每个Document对象包含两个必填参数,page_content为核心文本内容,即知识库知识点,是AI回答的依据;metadata为元数据(字典格式),用于存储文本的附加信息(如来源、分类),不影响回答内容,但可帮助追溯回答的资料来源;

  2. 数据组织方式:将所有Document对象放入列表sample_docs中,向量库可直接批量读取该列表,便于批量存入数据;

  3. 灵活性:修改知识库时,仅需调整sample_docs列表中的Document对象即可,例如添加新的宠物知识点或删除原有内容,无需修改其他代码。

-------------- 5. 初始化通义千问嵌入模型 --------------


# model:指定嵌入模型版本,text-embedding-v1是通义的轻量版,免费可用
# dashscope_api_key:显式传入密钥,确保权限生效
embeddings = DashScopeEmbeddings(
    model="text-embedding-v1",
    dashscope_api_key=DASHSCOPE_API_KEY
)

代码解读(作用+参数说明)

此行代码用于初始化「文字转向量」工具,实例化后的embeddings对象将负责所有文本的向量转换操作,参数说明如下:

  1. model=“text-embedding-v1”:指定使用阿里云的轻量级嵌入模型,该模型免费、速度快且精度满足学习测试需求,是新手的最优选择;

  2. dashscope_api_key=DASHSCOPE_API_KEY:显式传入密钥,与前文设置环境变量形成双重保险,确保即使环境变量配置失败,模型仍能正常调用。

-------------- 6. 初始化Chroma向量库并存入文档 --------------


# from_documents:把Document列表存入向量库
# embedding:指定用什么嵌入模型转向量(这里用通义的)
# persist_directory:None=内存模式(重启数据消失);指定路径=持久化到本地
vector_db = Chroma.from_documents(
    documents=sample_docs,
    embedding=embeddings,
    persist_directory=None
)

代码解读(核心步骤+参数说明)

此步骤为RAG的核心环节之一,负责将知识库文档存入Chroma向量库,一行代码完成3件关键事情,参数解读如下:

  1. Chroma.from_documents():Chroma向量库的批量存入方法,专门用于将Document列表存入向量库,是最常用的存入方式;

  2. documents=sample_docs:指定待存入的数据源,即前文准备的宠物知识库列表;

  3. embedding=embeddings:指定用于文本转向量的嵌入模型,向量库会自动调用该模型将所有文档转换为向量后存入,无需手动编写转码代码;

  4. persist_directory=None:控制向量库的数据存储模式,设为None时为内存模式,数据仅存在内存中,程序重启后丢失,适合学习测试;设为具体路径(如"./chroma_db")时为持久化模式,数据会存入本地文件夹,程序重启后仍保留,适合正式使用。

-------------- 7. 创建检索器(核心:从向量库找相似资料) --------------


# as_retriever:把向量库转换成LangChain的检索器(可接入工作链)
# search_type="similarity":按相似度检索
# search_kwargs={"k": 2}:返回最相似的2条文档
retriever = vector_db.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 2}
)

代码解读(核心作用+参数说明)

此部分是RAG的核心环节,负责创建检索器,从向量库中匹配与用户问题最相关的资料,参数和作用解读如下:

  1. 核心方法:vector_db.as_retriever(),向量库本身无法直接接入LangChain工作链,通过该方法可将向量库转换为LangChain标准的检索器,转换后的retriever对象可通过管道符串联到工作链中,为固定写法;

  2. search_type=“similarity”:指定检索方式为相似度匹配,用户提问后,检索器会将问题转换为向量,在向量库中匹配出最相似的文本向量,对应最相关的资料,此为最常用的检索方式,新手无需更换;

  3. search_kwargs={“k”: 2}:控制检索结果数量,k=2表示每次检索返回最相似的2条文档。k值设置需合理,过大易导致回答冗余,过小可能遗漏关键信息,2-3为学习测试的最佳值,可根据需求灵活调整。

总结:retriever检索器是连接向量库与工作链的关键,负责从知识库中筛选相关资料,直接决定AI回答的精准度。

-------------- 8. 定义提示词模板 --------------


# from_template:用模板字符串创建提示词
# {context}:检索到的参考资料(会自动填充)
# {question}:用户的问题(会自动填充)
# 模板作用:告诉AI必须基于参考资料回答,禁止胡说八道
prompt = ChatPromptTemplate.from_template("""
请严格根据提供的参考资料回答问题,不要编造任何不在资料里的内容。
参考资料:
{context}

用户问题:
{question}
""")

代码解读(作用+结构说明)

此部分用于定义提示词模板,约束AI的回答规则,是保证AI不编造内容的关键,核心细节如下:

  1. 创建方式:ChatPromptTemplate.from_template(),通过字符串模板创建提示词,简洁高效,模板中的占位符会自动填充内容;

  2. 核心占位符:模板中的{context}和{question}为动态占位符,工作链运行时会自动填充,{context}填充检索器找到的相似文档内容,{question}填充用户的原始问题;

  3. 核心作用:模板中的指令「请严格根据提供的参考资料回答问题,不要编造任何不在资料里的内容」直接决定AI的回答逻辑,约束AI仅基于检索到的资料作答,避免使用自身知识库编造内容,即使资料中无相关答案,AI也会提示无相关信息,不会瞎编,这是RAG的核心价值所在。

补充:提示词模板可根据需求灵活修改,例如添加「回答简洁,不超过50字」「分点回答」等指令,AI会严格遵守。

-------------- 9. 初始化通义千问大模型 --------------


# model:指定大模型版本,qwen-turbo=基础版(免费额度充足);qwen-plus=进阶版
# temperature:温度系数(0-1),越小回答越严谨,越大越有创造性
# dashscope_api_key:传入密钥
llm = ChatTongyi(
    model="qwen-turbo",
    temperature=0.1,
    dashscope_api_key=DASHSCOPE_API_KEY
)

代码解读(参数说明+作用)

此部分用于初始化通义千问大模型,为回答生成环节提供核心支撑,参数解读如下:

  1. model=“qwen-turbo”:指定使用通义千问基础版模型,该模型免费额度充足、速度快、精度满足学习测试需求,新手无需更换为qwen-plus(进阶版)或qwen-max(旗舰版);

  2. temperature=0.1:温度系数,取值范围0-1,值越小回答越严谨、精准、保守,适合问答、翻译等需准确的场景;值越大回答越随机、有创意,适合创作场景。RAG问答场景建议设置为0.1-0.3;

  3. dashscope_api_key=DASHSCOPE_API_KEY:显式传入密钥,确保模型调用的权限,与前文的环境变量设置形成双重保险。

-------------- 10. 构建RAG工作链(核心:检索→回答) --------------


# 链式调用逻辑:
# 1. {"context": retriever, "question": RunnablePassthrough()}
#    - retriever:自动检索相似文档,填充到context
#    - RunnablePassthrough():把用户问题直接传给question
# 2. | prompt:把context和question代入提示词模板,生成完整指令
# 3. | llm:把完整指令传给通义千问大模型
# 4. | StrOutputParser():把模型输出转换成纯字符串
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

代码解读(核心逻辑+逐环节拆解)

此部分为整篇代码的精华与灵魂,通过管道符串联所有组件,形成全自动的问答流水线,无需手动传参、编写循环或处理函数,LangChain已封装所有逻辑。从左到右拆解为4个环节,清晰呈现每一步的输入与输出:

环节1:数据准备层 → {“context”: retriever, “question”: RunnablePassthrough()}

此为字典格式的数据映射器,是工作链的入口,负责完成两项核心工作:

  • context: retriever:将检索器赋值给context键,用户提问时,检索器自动运行,将找到的相似文档内容填充到该位置;

  • question: RunnablePassthrough():将数据透传器赋值给question键,负责将用户原始问题原封不动地传递到该位置,无需额外处理函数。

结果:生成字典{“context”: “检索到的宠物资料”, “question”: “用户的问题”}。

环节2:提示词填充层 → | prompt

管道符将环节1的字典结果自动传给提示词模板prompt,模板将字典中的context和question自动填充到对应占位符,生成完整的指令文本,包含回答规则、参考资料和用户问题。

示例:生成指令「请严格根据提供的参考资料回答问题,不要编造任何不在资料里的内容。参考资料:金鱼是冷水鱼,饲养时需要注意鱼缸水质清洁,喂食不宜过多,寿命一般3-5年。 用户问题:金鱼适合什么样的人养?」。

环节3:大模型调用层 → | llm

管道符将填充完整的指令自动传给通义千问大模型llm,模型严格遵守指令,基于参考资料生成回答,不编造内容。

结果:模型返回包含嵌套属性的复杂回答对象,非纯字符串。

环节4:输出格式化层 → | StrOutputParser()

管道符将模型返回的复杂对象自动传给字符串解析器,解析器将其转换为干净的纯字符串,即最终的回答内容。

结果:得到纯文本回答,如「金鱼是冷水鱼,饲养时需注意鱼缸水质清洁、喂食不宜过多,适合喜欢安静、不需要频繁打理宠物的人饲养。」。

总结:rag_chain工作链整合了检索、填充、调用、格式化的全流程,仅需调用一个方法即可触发整个流水线,体现了LangChain简洁高效的核心优势。

-------------- 11. 测试运行 --------------


# 主函数入口:防止被其他文件导入时自动运行
if __name__ == "__main__":
    # 定义用户问题
    user_question = "金鱼适合什么样的人养?"
    # invoke:执行RAG链,获取回答
    answer = rag_chain.invoke(user_question)
    
    # 打印结果
    print("=" * 20)
    print(f"问题:{user_question}")
    print("-" * 20)
    print(f"回答:{answer}")
    print("=" * 20)

代码解读(作用+核心方法)

此部分为程序的运行入口,也是调用RAG链的标准方式,核心知识点如下:

  1. if name == “main”::Python固定写法,确保仅当直接运行该文件时,内部代码才执行;若文件被其他文件导入,内部代码不自动运行,避免干扰其他程序,为规范写法;

  2. user_question = “金鱼适合什么样的人养?”:定义用户问题,可根据需求灵活修改,如改为「猫咪适合什么样的人养?」「仓鼠的饲养要求是什么?」等;

  3. answer = rag_chain.invoke(user_question):核心调用方法,invoke()为LangChain同步调用的标准方法,传入用户问题后触发整个RAG工作链,最终将完整回答结果赋值给answer变量;

  4. 打印结果:通过格式化打印清晰展示问题和回答,便于查看运行效果。

运行结果演示


====================
问题:金鱼适合什么样的人养?
--------------------
回答:金鱼是冷水鱼,饲养时需要注意鱼缸水质清洁,喂食不宜过多,它适合喜欢安静、不需要频繁打理宠物的人饲养。
====================

该回答完全来源于指定知识库,无任何编造内容,精准度符合预期,体现了RAG的核心价值。

✅ 核心知识点总结(必背清单)

本代码包含LangChain 1.0开发RAG的所有核心知识点,掌握后可举一反三开发各类知识库问答应用,核心总结如下:

一、RAG核心流程(灵魂)

准备知识库 → 文本转向量 → 存入向量库 → 创建检索器 → 定义提示词模板 → 初始化大模型 → 构建工作链 → 调用问答

二、LangChain核心组件(工具)

  1. Document:封装知识库文本和元数据,向量库的标准格式;

  2. DashScopeEmbeddings:通义千问的文本转向量工具;

  3. Chroma:轻量级本地向量库,新手首选;

  4. as_retriever():向量库转检索器的固定方法;

  5. ChatPromptTemplate:定义AI回答规则的提示词模板;

  6. ChatTongyi:通义千问大模型的调用入口;

  7. RunnablePassthrough:数据透传器,传递用户原始问题;

  8. StrOutputParser:格式化输出,转换为纯字符串;

  9. 管道符 |:串联所有节点,实现自动传参。

三、核心调用方法(使用)

同步调用RAG链:rag_chain.invoke(用户问题),固定写法,一次性返回完整回答。

四、灵活修改技巧(举一反三)

  1. 修改知识库:仅需调整sample_docs列表中的Document对象;

  2. 修改回答规则:修改prompt提示词模板中的指令;

  3. 修改检索数量:调整search_kwargs={“k”: 2}中的k值。

✅ 新手避坑指南(运行报错解决方案)

运行代码时若出现错误,99%为以下4种原因,按顺序排查即可解决:

  1. 鉴权失败:Invalid api key → 检查config.py文件中的密钥是否正确,变量名是否为DASHSCOPE_API_KEY;

  2. 依赖缺失:ModuleNotFoundError → 运行命令pip install langchain-core langchain-community chromadb dashscope python-dotenv安装所有依赖;

  3. 检索不到内容:回答「无相关资料」 → 检查知识库是否包含与问题相关的内容,或适当调大k值;

  4. AI回答编造内容 → 检查提示词模板是否包含「严格根据参考资料回答,不要编造」的指令,该指令为必加项。

完整代码

# -------------- 1. 基础库导入 --------------
# Python内置的操作系统模块,用于环境变量操作
import os
# 从自定义的config.py文件中导入通义千言的API密钥(你的密钥存在这里)
from config import DASHSCOPE_API_KEY

# -------------- 2. LangChain核心组件导入 --------------
# 1. 向量数据库:Chroma是轻量级本地向量库,无需部署,适合测试
from langchain_community.vectorstores import Chroma
# 2. 嵌入模型:DashScopeEmbeddings是通义千言的文本转向量工具
#    作用:把文字(如"猫咪性格高冷")转换成计算机能理解的向量数字
from langchain_community.embeddings import DashScopeEmbeddings
# 3. 大模型调用工具:DashScope是通义千言的LLM调用入口
#    作用:连接通义千言大模型,发送指令并获取回答
from langchain_community.chat_models import ChatTongyi
# 4. 提示词模板:ChatPromptTemplate用于定义固定的提问格式
#    作用:约束AI的回答规则,比如"只能用参考资料回答,禁止编造"
from langchain_core.prompts import ChatPromptTemplate
# 5. 数据透传工具:RunnablePassthrough用于传递用户原始问题
#    作用:不用手动写函数,直接把用户问题传给提示词模板
from langchain_core.runnables import RunnablePassthrough
# 6. 输出格式化工具:StrOutputParser用于格式化AI的输出
#    作用:把模型返回的复杂对象转换成纯字符串,方便打印查看
from langchain_core.output_parsers import StrOutputParser
# 7. 文档标准类:Document是LangChain的统一文档格式
#    作用:包装文本内容和元数据(如来源),让向量库能识别
from langchain_core.documents import Document

# -------------- 3. 配置API密钥 --------------
# 将API密钥设置为环境变量,确保通义千言的SDK能读取到
os.environ["DASHSCOPE_API_KEY"] = DASHSCOPE_API_KEY

# -------------- 4. 准备示例文档 --------------
# 用Document类包装我们的宠物资料,每个Document对应一条知识
# page_content:核心文本内容;metadata:附加信息(如来源、分类)
sample_docs = [
    Document(
        page_content="狗狗是群居动物,性格活泼,需要每天遛弯,忠诚度高,适合作为陪伴宠物。",
        metadata={"source": "宠物手册-犬类"}
    ),
    Document(
        page_content="猫咪是独居动物,性格高冷,爱干净,不需要频繁遛弯,适合喜欢安静的饲养者。",
        metadata={"source": "宠物手册-猫类"}
    ),
    Document(
        page_content="金鱼是冷水鱼,饲养时需要注意鱼缸水质清洁,喂食不宜过多,寿命一般3-5年。",
        metadata={"source": "宠物手册-鱼类"}
    ),
    Document(
        page_content="仓鼠是啮齿类动物,夜间活动,主食为谷物和坚果,饲养空间需要通风干燥。",
        metadata={"source": "宠物手册-啮齿类"}
    )
]

# -------------- 5. 初始化通义千言嵌入模型 --------------
# model:指定嵌入模型版本,text-embedding-v1是通义的轻量版,免费可用
# dashscope_api_key:显式传入密钥,确保权限生效
embeddings = DashScopeEmbeddings(
    model="text-embedding-v1",
    dashscope_api_key=DASHSCOPE_API_KEY
)

# -------------- 6. 初始化Chroma向量库并存入文档 --------------
# from_documents:把Document列表存入向量库
# embedding:指定用什么嵌入模型转向量(这里用通义的)
# persist_directory:None=内存模式(重启数据消失);指定路径=持久化到本地
vector_db = Chroma.from_documents(
    documents=sample_docs,
    embedding=embeddings,
    persist_directory=None
)

# -------------- 7. 创建检索器(核心:从向量库找相似资料) --------------
# as_retriever:把向量库转换成LangChain的检索器(可接入工作链)
# search_type="similarity":按相似度检索
# search_kwargs={"k": 2}:返回最相似的2条文档
retriever = vector_db.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 2}
)

# -------------- 8. 定义提示词模板 --------------
# from_template:用模板字符串创建提示词
# {context}:检索到的参考资料(会自动填充)
# {question}:用户的问题(会自动填充)
# 模板作用:告诉AI必须基于参考资料回答,禁止胡说八道
prompt = ChatPromptTemplate.from_template("""
请严格根据提供的参考资料回答问题,不要编造任何不在资料里的内容。
参考资料:
{context}

用户问题:
{question}
""")

# -------------- 9. 初始化通义千言大模型 --------------
# model:指定大模型版本,qwen-turbo=基础版(免费额度充足);qwen-plus=进阶版
# temperature:温度系数(0-1),越小回答越严谨,越大越有创造性
# dashscope_api_key:传入密钥
llm = ChatTongyi(
    model="qwen-turbo",
    temperature=0.1,
    dashscope_api_key=DASHSCOPE_API_KEY
)

# -------------- 10. 构建RAG工作链(核心:检索→回答) --------------
# 链式调用逻辑:
# 1. {"context": retriever, "question": RunnablePassthrough()}
#    - retriever:自动检索相似文档,填充到context
#    - RunnablePassthrough():把用户问题直接传给question
# 2. | prompt:把context和question代入提示词模板,生成完整指令
# 3. | llm:把完整指令传给通义千言大模型
# 4. | StrOutputParser():把模型输出转换成纯字符串
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# -------------- 11. 测试运行 --------------
# 主函数入口:防止被其他文件导入时自动运行
if __name__ == "__main__":
    # 定义用户问题
    user_question = "金鱼适合什么样的人养?"
    # invoke:执行RAG链,获取回答
    answer = rag_chain.invoke(user_question)
    
    # 打印结果
    print("=" * 20)
    print(f"问题:{user_question}")
    print("-" * 20)
    print(f"回答:{answer}")
    print("=" * 20)
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐