ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

阿里云部署qwen 、embedding、增加RAG增强知识检索,第6步:运行demo.py

阿里云部署qwen 、embedding、增加RAG增强知识检索,第6步:运行demo.py 任务 4 智能体开发RAG 信贷知识库问答完整拆解你的模型 对话大模型Qwen3_5‑0_8B生成回答 向量嵌入模型Qwen3‑Embedding‑0_6B文档向量化、检索 环境rag_env虚拟环境库已经装好 核心任务RAG 检索增强生成智能体逻辑先检索知识库→相似度判断→再给大模型回答知识库没有就禁止编造✅ 整体流程给学生理解读取txt知识库 → 文本分块 → 用Embedding模型把每一块转向量 → 构建向量索引 用户提问 → 提问转为向量 → 在索引里面检索最相似的TopK知识库片段 【智能体判断逻辑】如果最高相似度阈值 → 直接输出无相关信息不送入大模型 如果相似度达标 → 把【检索到的知识库片段 用户问题】放进你设计的提示词模板约束大模型只能用检索到的内容回答 送入Qwen3.5大模型输出回答重点大模型不能靠自己记忆回答只能使用检索出来的文档内容找不到就不能编造信贷规则完整分步操作服务器 rag_env 环境前置准备把credit_product.txt放到路径./2_data/finance_task/# 先创建文件夹 mkdir -p 2_data/finance_task # 把txt文件上传到此目录两个模型已经解压完成./Qwen3_5‑0_8B生成大模型./Qwen3‑Embedding‑0_6B向量嵌入模型步骤 1激活虚拟环境进入工作目录cd ~/workspace source rag_env/bin/activate步骤 2确认依赖除了之前的库RAG 需要向量库faiss如果没装执行pip install faiss-cpu步骤 3新建 RAG 智能体代码文件nano rag_agent.py粘贴下面带大量注释的完整代码# 导入工具包 # 大模型、分词器 from transformers import AutoTokenizer, AutoModelForCausalLM # Embedding向量模型 from transformers import AutoModel, AutoTokenizer as EmbeddingTokenizer import torch # faiss向量库用来做相似度检索 import faiss # 文件读取 import os # 【配置区学生只需要修改模型路径】 # 回答用的对话大模型 LLM_MODEL_PATH ./Qwen3_5‑0_8B # 向量嵌入模型用来把文字转向量 EMBED_MODEL_PATH ./Qwen3‑Embedding‑0_6B # 知识库文件路径 KNOWLEDGE_FILE ./2_data/finance_task/credit_product.txt # RAG超参数可以自行调整 CHUNK_SIZE 200 # 文档分块大小每块200字符 TOP_K 3 # 检索返回最相似的3条知识片段 SIM_THRESHOLD 0.75 # 相似度阈值低于这个值判定知识库无相关内容 # 加载Embedding向量模型 # 向量模型把文本转为向量用于相似度匹配 embedding_tokenizer EmbeddingTokenizer.from_pretrained(EMBED_MODEL_PATH, trust_remote_codeTrue) embedding_model AutoModel.from_pretrained(EMBED_MODEL_PATH, trust_remote_codeTrue).to(cuda) # 函数输入一段文本输出向量 def get_text_embedding(text): inputs embedding_tokenizer(text, return_tensorspt, truncationTrue, max_length512).to(cuda) with torch.no_grad(): model_output embedding_model(**inputs) # 取句向量Qwen embedding标准处理 vec model_output.last_hidden_state.mean(dim1) return vec[0].cpu().numpy() # 1.读取知识库 文本分块 def load_and_split_knowledge(file_path): # 读取txt全部内容 with open(file_path, r, encodingutf-8) as f: full_text f.read() # 简单分块按固定字符切割 chunks [] for i in range(0, len(full_text), CHUNK_SIZE): chunk full_text[i:iCHUNK_SIZE] chunks.append(chunk) return chunks # 2.构建向量索引 def build_vector_index(chunk_list): # 初始化faiss索引 sample_vec get_text_embedding(test) dim sample_vec.shape[0] index faiss.IndexFlatL2(dim) vec_list [] for chunk in chunk_list: vec get_text_embedding(chunk) vec_list.append(vec) vec_np np.array(vec_list).astype(float32) index.add(vec_np) return index, chunk_list # 3.检索函数输入问题返回topk片段相似度 def search_knowledge(query, index, chunk_list): query_vec get_text_embedding(query) query_vec np.array([query_vec]).astype(float32) # 检索返回距离和序号 distance_array, idx_array index.search(query_vec, TOP_K) results [] for dis, idx in zip(distance_array[0], idx_array[0]): # L2距离转相似度距离越小相似度越高 sim 1.0 / (1.0 dis) results.append( {chunk:chunk_list[idx], similarity:sim} ) return results # 4.加载大语言模型Qwen3.5和任务2、3加载代码完全一致 llm_tokenizer AutoTokenizer.from_pretrained(LLM_MODEL_PATH, trust_remote_codeTrue) llm_model AutoModelForCausalLM.from_pretrained( LLM_MODEL_PATH, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ) # 5.【提示词模板本任务核心设计】 def build_rag_prompt(question, context_text): prompt f 你是银行信贷咨询客服只能依据下面【参考知识库内容】回答用户问题。 严格约束 1. 只能使用【参考知识库】里提供的信息回答绝对不能使用模型自带知识严禁编造信贷政策、利率、申请条件。 2. 如果参考资料不足以回答问题直接回复依据本行普惠信贷业务资料暂未查询到该问题相关信息无法解答。 【参考知识库内容】 {context_text} 用户问题{question} 回答 return prompt # 主程序入口 if __name__ __main__: import numpy as np print(正在加载知识库构建向量索引) # 读取分块 knowledge_chunks load_and_split_knowledge(KNOWLEDGE_FILE) # 构建向量库 faiss_index, chunk_data build_vector_index(knowledge_chunks) print(知识库加载完成) # input接收客户咨询问题题目指定问题 user_question input(请输入客户信贷咨询问题) # 检索知识库 search_result search_knowledge(user_question, faiss_index, chunk_data) print(\n检索到Top-K知识片段) for item in search_result: print(f相似度{item[similarity]:.3f}) print(f片段内容{item[chunk]}\n) # 智能体判断逻辑【本题重点】相似度过滤 max_sim search_result[0][similarity] if max_sim SIM_THRESHOLD: final_answer 依据本行普惠信贷业务资料暂未查询到该问题相关信息无法解答 else: # 把topk片段拼接成上下文 context_str \n.join([item[chunk] for item in search_result]) # 拼接rag提示词 full_prompt build_rag_prompt(user_question, context_str) #送入大模型推理 inputs llm_tokenizer(full_prompt, return_tensorspt).to(cuda) with torch.no_grad(): output_tokens llm_model.generate( **inputs, max_new_tokens512, temperature0.1 ) final_answer llm_tokenizer.decode(output_tokens[0], skip_special_tokensTrue) print(\n模型最终回答) print(final_answer)保存CtrlO回车 →CtrlX退出 nano步骤 4运行代码python3 rag_agent.py程序先读取 txt 文档分块、生成向量构建向量索引第一次运行会慢一点提示输入问题输入题目指定问句小微企业申请普惠信用贷需要准备哪些申请材料哪些情形企业会禁止准入终端会打印检索出来的 Top-K 知识库片段、相似度、最后模型生成回答保存完整控制台截图作为提交成果考点拆解给学生写报告文档分块长文档不能一次性丢给向量模型切成小段提升检索精度Embedding 向量模型Qwen3-Embedding-0.6B专门把文本转为向量用来做相似度检索不生成文字向量库 FAISS快速查找和用户提问最相似的知识库片段智能体判断逻辑本题智能体核心检索后拿到最高相似度和阈值对比。相似度太低直接输出无法解答不再送入大模型防止幻觉编造RAG 提示词模板强制约束模型只允许使用检索到的片段回答禁止编造业务规则大模型加载代码和任务 2、任务 3骨架完全一致仅修改模型路径学生复用之前的代码重要竞赛踩坑提醒❗Embedding 模型 和 LLM 对话模型是两个独立模型不要搞混Qwen3-Embedding只做检索不回答问题Qwen3.5-0.8B拿到检索片段之后生成回答必须保留相似度判断分支这是智能体的核心逻辑不能省略。低于阈值直接输出无法解答不调用大模型。提示词约束一定要写死严禁模型编造金融规则。运行输出必须打印检索片段 相似度题目要求控制台打印 Top-K 片段。运行输出样例结构正在加载知识库构建向量索引 知识库加载完成 请输入客户信贷咨询问题小微企业申请普惠信用贷需要准备哪些申请材料哪些情形企业会禁止准入 检索到Top-K知识片段 相似度0.872 片段内容xxxx 相似度0.811 片段内容xxxx 相似度0.780 片段内容xxxx 模型最终回答 基于检索片段生成的信贷回答三个任务代码统一逻辑总结方便学生记忆任务 2基础模型对话加载 Qwen LLM官方 chat 模板任务 3提示词设计加载 Qwen LLM手写任务提示词模板input 输入单次推理任务 4RAG 智能体双模型Embedding 向量模型 LLM 大模型增加文档读取、分块、向量检索、相似度判断智能体逻辑手写 RAG 约束提示词模板模型加载代码全部复用只改路径。新增的是文档处理、向量检索、相似度判断这一整套 RAG 逻辑。credit_product.txt 作为输入范例普惠小微企业信用贷款业务说明 1、申请所需材料 ①营业执照原件扫描件 ②法人身份证正反面扫描件 ③近6个月企业对公银行流水 ④企业征信报告 ⑤经营场地租赁合同。 2、禁止准入情形 ①企业当前存在未结案的被执行案件 ②企业或法人征信存在当前逾期 ③企业属于高污染淘汰类行业 ④成立时间不足12个月的小微企业 ⑤企业有欠税记录未结清。 3、利率区间 普惠小微企业信用贷年化利率区间3.45% ~ 4.8%。 4、还款方式 按月付息到期一次性归还本金也可选择等额本息按月还款。 5、审批流程 1.线上提交材料 2.系统初筛 3.人工复核 4.授信审批 5.放款。补充代码逻辑先看题目原文智能体开发包含工具函数封装、长期 / 短期记忆管理、多轮任务调度你现在这份样例任务信贷咨询 RAG需要实现【多轮对话记忆】也就是记住客户上一轮问过的内容不是每次提问完全独立。 我们现在原来的代码每一次提问都是独立的没有记忆这就是缺失的部分。✅ 什么是短期记忆本题需要的记忆逻辑通俗讲 保存历史对话用户之前的问题 模型上一轮的回答新提问的时候把历史对话一起放进 prompt让大模型记得前面聊了什么。短期记忆存在程序内存里程序关闭就消失竞赛题目要的就是这个 长期记忆存入向量库本次考题不需要不用做避免学生做复杂了。举例子 用户第一轮小微企业申请普惠信用贷需要准备哪些申请材料 模型回答列出营业执照、法人身份证等材料。用户第二轮追问那里面哪一条材料是法人相关的 有记忆模型记得上一轮对话直接回答法人身份证扫描件 无记忆旧代码单独拿这句话检索知识库容易理解断裂不知道 “里面” 指代什么。重点改动新增全局列表chat_history用来存放对话历史短期记忆修改build_rag_prompt把历史对话拼进提示词改成循环while True支持多轮提问每一轮问答都存入记忆列表原有知识库检索、相似度判断逻辑全部保留不动一、讲清楚窗口大小、读取全部还是部分历史给学生理解1、当前代码逻辑现在代码每次会把【全部历史对话】一股脑拼进提示词# 代码里的拼接逻辑 history_str for user_msg, bot_msg in history: history_str f客户{user_msg}\n客服{bot_msg}\n✅ 优点最简单学生好理解写报告方便 ❌ 缺点对话轮次越来越多 → prompt 文本越来越长会占用显存严重时超过模型最大输入长度直接报错。2、两个概念短期记忆窗口大小就是最多保留多少轮对话。方案 A当前代码窗口 无限大保留全部历史直到爆长度。适合竞赛简单演示轮次少的时候没问题。方案 B推荐优化加分固定窗口只保留最近 N 轮丢弃最早的对话。比如窗口大小 2只保存最近 2 轮问答旧对话删掉防止 prompt 过长。考题只要求实现记忆模块基础版本 “保存全部对话” 已经满足得分要求如果想完善加上窗口截断更好。3、通俗一句话基础版每一次新提问把从头到尾所有历史对话全部塞给大模型。 加窗口限制版只拿最近 N 轮更早对话直接丢掉避免文本太长。二、两套代码版本版本 1原版保留全部历史无窗口截断最简单优先给学生适合调试代码改动最小好理解轮次少不会出错 重点确认代码无语法错误所有逻辑不变仅增加记忆、while 循环# 导入工具包 # 大模型、分词器 from transformers import AutoTokenizer, AutoModelForCausalLM # Embedding向量模型 from transformers import AutoModel, AutoTokenizer as EmbeddingTokenizer import torch # faiss向量库用来做相似度检索 import faiss # 文件读取 import os import numpy as np # 【配置区学生只需要修改模型路径】 # 回答用的对话大模型 LLM_MODEL_PATH ./Qwen3_5‑0_8B # 向量嵌入模型用来把文字转向量 EMBED_MODEL_PATH ./Qwen3‑Embedding‑0_6B # 知识库文件路径 KNOWLEDGE_FILE ./2_data/finance_task/credit_product.txt # RAG超参数可以自行调整 CHUNK_SIZE 200 # 文档分块大小每块200字符 TOP_K 3 # 检索返回最相似的3条知识片段 SIM_THRESHOLD 0.75 # 相似度阈值低于这个值判定知识库无相关内容 # 【新增短期记忆保存多轮对话历史】 chat_history [] # 记忆容器存放每一轮 (用户问题模型回答) # 加载Embedding向量模型 # 向量模型把文本转为向量用于相似度匹配 embedding_tokenizer EmbeddingTokenizer.from_pretrained(EMBED_MODEL_PATH, trust_remote_codeTrue) embedding_model AutoModel.from_pretrained(EMBED_MODEL_PATH, trust_remote_codeTrue).to(cuda) # 函数输入一段文本输出向量 def get_text_embedding(text): inputs embedding_tokenizer(text, return_tensorspt, truncationTrue, max_length512).to(cuda) with torch.no_grad(): model_output embedding_model(**inputs) # 取句向量Qwen embedding标准处理 vec model_output.last_hidden_state.mean(dim1) return vec[0].cpu().numpy() # 1.读取知识库 文本分块 def load_and_split_knowledge(file_path): # 读取txt全部内容 with open(file_path, r, encodingutf-8) as f: full_text f.read() # 简单分块按固定字符切割 chunks [] for i in range(0, len(full_text), CHUNK_SIZE): chunk full_text[i:iCHUNK_SIZE] chunks.append(chunk) return chunks # 2.构建向量索引 def build_vector_index(chunk_list): # 初始化faiss索引 sample_vec get_text_embedding(test) dim sample_vec.shape[0] index faiss.IndexFlatL2(dim) vec_list [] for chunk in chunk_list: vec get_text_embedding(chunk) vec_list.append(vec) vec_np np.array(vec_list).astype(float32) index.add(vec_np) return index, chunk_list # 3.检索函数输入问题返回topk片段相似度 def search_knowledge(query, index, chunk_list): query_vec get_text_embedding(query) query_vec np.array([query_vec]).astype(float32) # 检索返回距离和序号 distance_array, idx_array index.search(query_vec, TOP_K) results [] for dis, idx in zip(distance_array[0], idx_array[0]): # L2距离转相似度距离越小相似度越高 sim 1.0 / (1.0 dis) results.append( {chunk:chunk_list[idx], similarity:sim} ) return results # 4.加载大语言模型Qwen3.5和任务2、3加载代码完全一致 llm_tokenizer AutoTokenizer.from_pretrained(LLM_MODEL_PATH, trust_remote_codeTrue) llm_model AutoModelForCausalLM.from_pretrained( LLM_MODEL_PATH, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ) # 5.【提示词模板增加对话记忆】 def build_rag_prompt(question, context_text, history): # 拼接全部历史对话 history_str for user_msg, bot_msg in history: history_str f客户{user_msg}\n客服{bot_msg}\n prompt f 你是银行信贷咨询客服只能依据下面【参考知识库内容】回答用户问题。 严格约束 1. 只能使用【参考知识库】里提供的信息回答绝对不能使用模型自带知识严禁编造信贷政策、利率、申请条件。 2. 如果参考资料不足以回答问题直接回复依据本行普惠信贷业务资料暂未查询到该问题相关信息无法解答。 【参考知识库内容】 {context_text} 【历史对话记录】 {history_str} 客户当前新问题{question} 客服回答 return prompt # 主程序入口 if __name__ __main__: print(正在加载知识库构建向量索引) # 读取分块 knowledge_chunks load_and_split_knowledge(KNOWLEDGE_FILE) # 构建向量库 faiss_index, chunk_data build_vector_index(knowledge_chunks) print(知识库加载完成支持多轮对话输入exit退出) # 多轮循环实现记忆一轮一轮对话 while True: user_question input(\n请输入客户信贷咨询问题) if user_question.strip() exit: print(对话结束) break # 检索知识库 search_result search_knowledge(user_question, faiss_index, chunk_data) print(\n检索到Top-K知识片段) for item in search_result: print(f相似度{item[similarity]:.3f}) print(f片段内容{item[chunk]}\n) # 智能体判断逻辑【本题重点】相似度过滤 max_sim search_result[0][similarity] if max_sim SIM_THRESHOLD: final_answer 依据本行普惠信贷业务资料暂未查询到该问题相关信息无法解答 else: # 把topk片段拼接成上下文 context_str \n.join([item[chunk] for item in search_result]) # 拼接rag提示词带上对话记忆history full_prompt build_rag_prompt(user_question, context_str, chat_history) #送入大模型推理 inputs llm_tokenizer(full_prompt, return_tensorspt).to(cuda) with torch.no_grad(): output_tokens llm_model.generate( **inputs, max_new_tokens512, temperature0.1 ) final_answer llm_tokenizer.decode(output_tokens[0], skip_special_tokensTrue) print(\n模型最终回答) print(final_answer) # 【记忆写入本轮问答存入记忆列表下一轮对话可以读取】 chat_history.append( (user_question, final_answer) )版本 2增加窗口截断只保留最近 N 轮推荐加分版防止超长增加参数MAX_HISTORY_ROUND 2窗口大小 2只保留最近 2 轮问答更早对话丢弃只增加少量代码其余完全不变# 在配置区增加一行 MAX_HISTORY_ROUND 2 # 记忆窗口大小最多保留最近2轮对话 # 【存入记忆的时候截断旧对话】 chat_history.append( (user_question, final_answer) ) # 截断只保留末尾MAX_HISTORY_ROUND条 if len(chat_history) MAX_HISTORY_ROUND: chat_history chat_history[-MAX_HISTORY_ROUND:]解释chat_history[-MAX_HISTORY_ROUND:]取列表最后 N 个前面旧对话直接删掉。 学生可以修改 MAX_HISTORY_ROUND 数值比如改成 3保留最近 3 轮。完整带窗口截断的 build_rag_prompt 主循环片段替换上面对应部分即可# 【配置区新增记忆窗口大小】 MAX_HISTORY_ROUND 2 # 短期记忆窗口只保留最近2轮问答 # 5.【提示词模板】 def build_rag_prompt(question, context_text, history): # 拼接历史对话此时history已经被截断只有最近N轮 history_str for user_msg, bot_msg in history: history_str f客户{user_msg}\n客服{bot_msg}\n prompt f 你是银行信贷咨询客服只能依据下面【参考知识库内容】回答用户问题。 严格约束 1. 只能使用【参考知识库】里提供的信息回答绝对不能使用模型自带知识严禁编造信贷政策、利率、申请条件。 2. 如果参考资料不足以回答问题直接回复依据本行普惠信贷业务资料暂未查询到该问题相关信息无法解答。 【参考知识库内容】 {context_text} 【最近对话记录】 {history_str} 客户当前新问题{question} 客服回答 return prompt # 主循环末尾 记忆存储截断 print(\n模型最终回答) print(final_answer) # 存入本轮问答 chat_history.append( (user_question, final_answer) ) # 窗口截断超过最大轮数删掉最早对话 if len(chat_history) MAX_HISTORY_ROUND: chat_history chat_history[-MAX_HISTORY_ROUND:]三、学生调试注意事项重点先使用版本 1调试简单逻辑直观满足基础得分。测试记忆功能操作步骤第一轮小微企业申请普惠信用贷需要准备哪些申请材料哪些情形企业会禁止准入第二轮追问刚才提到的禁止准入情形里面包含欠税的情况吗如果模型能关联上一轮内容说明记忆生效。当对话很多轮后版本 1 会越来越慢、甚至报错。这时切换版本 2设置窗口大小。记忆是内存短期记忆程序一旦exit退出chat_history 列表清空记忆全部消失符合考题短期记忆定义。四、报告描述文字直接复制短期记忆模块采用列表存储对话历史基础版本每次推理时将全部历史对话拼接进提示词优化版本设置记忆窗口大小仅保留最近 N 轮对话丢弃早期对话控制提示词总长度防止超出模型上下文上限。每次问答结束将本轮用户提问与模型回答存入记忆列表新提问时检索知识库片段 历史对话共同送入提示词实现多轮对话理解。
返回列表