news 2026/4/23 16:00:55

【langchain框架——检索链】利用检索链创建自己的购物知识库并完成智能体的商品推荐

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【langchain框架——检索链】利用检索链创建自己的购物知识库并完成智能体的商品推荐

检索链的种类

检索链是实现检索增强生成(RAG)的核心组件,其核心逻辑是:先从知识库中检索与用户相关的上下文,再将问题和上下文传入大模型生成答案。其主要分类如下:

链名称核心特点
RetrievalQA基础检索问答链,最通用
RetrievalQAWithSourcesChain专门优化「来源追溯」
ConversationalRetrievalChain融合对话记忆
RetrievalQAWithChainOptions自定义链配置(进阶)

以电商平台商品推荐为例(下面自己手搓的代码,盗用请标注来源)

用到的函数

fromlangchain_community.document_loadersimport(TextLoader,PyPDFLoader,UnstructuredMarkdownLoader,WebBaseLoader)fromlangchain_classic.schemaimportDocumentfromlangchain_community.vectorstoresimportFAISSfromlangchain_classic.chainsimportRetrievalQAfromlangchain_classic.promptsimportPromptTemplatefromlangchain_community.embeddingsimportDashScopeEmbeddings

步骤一:我用到的商品文件

下图是我的商品pdf:

步骤二:pdf转进行分块,我们这里按照自定义字符串进行分割,即#

defprint_document_splits(splits,num_to_display=5):print(f"\n📋 文档分割详情(共{len(splits)}个片段):\n"+"="*60)fori,docinenumerate(splits[:num_to_display]):print(f"\n➡️ 片段{i+1}:")print(f" 来源:{doc.metadata.get('source','未知')}")print(f" 页码:{doc.metadata.get('page','未知')}")print(f" 字符数:{len(doc.page_content)}")content_preview=doc.page_content[:200]+"..."iflen(doc.page_content)>200elsedoc.page_contentprint(f" 内容预览:{content_preview}")iflen(splits)>num_to_display:print(f"\n... 还有{len(splits)-num_to_display}个片段未显示")embeddings=DashScopeEmbeddings(model="text-embedding-v3",dashscope_api_key="sk-8009265c5eddxxxxx9cb9ef3")loader=PyPDFLoader("/wwwxxxx量商品推荐_20251224135554.pdf")documents=loader.load()# 按 # 分割,这里是关键full_text="\n".join([doc.page_contentfordocindocuments])chunks=full_text.split("#")

步骤三:创建向量数据库:

vectorstore=FAISS.from_documents(documents=splits,embedding=embeddings)vectorstore.save_local("./save_knowledgeDB")

结果展示——生成好的知识库:

如果创建成功后,下次就不用再创建向量数据库了,直接导入加载即可,加载代码如下:

vectorstore=FAISS.load_local(folder_path="./save_knowledgeDB",# 你的保存路径embeddings=embeddings,# 需要用相同的embedding模型allow_dangerous_deserialization=True)

步骤四:创造检索器

由于工作内容检索复杂,我打算采用混合检索器的方式,那么混合检索器主要分为2种,分别为:简单检索器和加权融和检索器。混合检索器混合的两种方法通常是向量检索和BM25混合,下面我将主要介绍这两种方法:

方法一:简单融合检索器实现

defSimple_hunhe_search(query,k):print("🟢 简单混合检索——执行向量检索...")vector_document=vector_retriever.invoke(query)print("🟢 简单混合检索——执行BM25检索...")bm25_document=BM25_retriever.invoke(query)all_docs,seen__content=[],set()for_invector_document:content=_.page_content[:100]# 取文档前100字符作为唯一标识,防止相同文档重复统计ifcontentnotinseen__content:all_docs.append((_,0.6))seen__content.add(content)for_inbm25_document:content=_.page_content[:100]ifcontentnotinseen__content:seen__content.add(content)all_docs.append((_,0.4))all_docs.sort(key=lambdax:x[1],reverse=True)result=[cforc,_inall_docs[:k]]print("🟢 简单混合检索完成!...")returnresult

方法一:加权融合检索器实现

defWeight_hunhe_search(query,vector_weight=0.7,bm25_weight=0.3,k=5):print(f"⚖️ 加权融合检索 (向量:{vector_weight}/BM25:{bm25_weight})")vector_document=vector_retriever.invoke(query)bm25_document=BM25_retriever.invoke(query)score_docs={}fori,_inenumerate(vector_document):score=(1-i/len(vector_document))*vector_weightifvector_documentelse0content=_.page_content[:150]ifcontentnotinscore_docs:score_docs[content]={"doc":_,"score":score}else:score_docs[content]["score"]+=scorefori,_inenumerate(bm25_document):score=(1-i/len(bm25_document))*bm25_weightifbm25_documentelse0content=_.page_content[:150]ifcontentnotinscore_docs:score_docs[content]={"doc":_,"score":score}else:score_docs[content]["score"]+=score result=sorted(score_docs.values(),key=lambdax:x['score'],reverse=True)result=[items['doc']foritemsinresult[:k]]returnresult

步骤五:写好提示词,连接chain,搭建工作流。

我们的目的是:先提取用户想买的商品,该商品放入检索器检索并输出可能的商品,再让一个基础LLMChain完成商品推荐逻辑

## 先提取用户的商品名称:fromlangchain_classic.chainsimportLLMChain extract_product_name=LLMChain(llm=llm,prompt=PromptTemplate.from_template("你是一个专业提取用户需求的助手,能够提取用户{input}里面想要的商品名称。例如:我想买花露水 -> 花露水,直接输出最终商品名称即可,严禁多于废话"),output_key="product_name",verbose=False)introduct_products=LLMChain(llm=llm,prompt=PromptTemplate.from_template("请结合用户需求,和在知识库中检索出来的商品列表,挑选最符合的商品推荐给用户,输出格式为:"\"为您推荐xx个商品,第一款为xxx,第二款为xxx。现在用户需求为{input},商品列表为{product_list}"),output_key="answer",verbose=False)user_issues=["我想买大米","给我推荐食用油","有没有口罩"]fori,issueinenumerate(user_issues,1):print(f"\n{'='*60}")print(f"{'-'*60}")result=extract_product_name.invoke({"input":f"{issue}"})print("result:",result['product_name'])products_list=Weight_hunhe_search(result['product_name'],vector_weight=0.7,bm25_weight=0.3,k=10)res=introduct_products.invoke({"input":f"{issue}","product_list":f'{products_list}'})print("推荐话术:",res['answer'])print(f"{'='*60}")print("\n✅ 所有需求处理完成!")

效果展示

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 13:43:43

基于springboot反诈APP系统(源码+lw+部署文档+讲解等)

课题介绍本课题聚焦当前电信网络诈骗高发、反诈宣传覆盖不足、群众预警响应滞后等痛点,设计并实现基于Spring Boot框架的反诈APP系统。系统以Spring Boot为后端核心开发框架,整合MyBatis-Plus实现反诈数据高效持久化,搭配MySQL构建安全可靠的…

作者头像 李华
网站建设 2026/4/23 11:04:09

一文讲清楚DOM动态观察器MutationObserver的原理和使用场景

一文讲清楚DOM动态观察器MutationObserver的原理和使用场景 1. 引出 前端的童鞋都应该了然一件事,不管是借助框架像vue/react/angular,还是原生开发,就是我们开发来开发去,操作来操作去,其实本质都是在对页面上的HTML内容进行CURD 那既然我们是在对HTML进行CURD,那我们是…

作者头像 李华
网站建设 2026/4/23 12:15:24

云原生密钥管理:Sealed Secrets与Vault

在云原生环境中,密钥管理是保障系统安全的关键环节。密钥就像是一把打开系统资源的“钥匙”,如果管理不当,就会面临密钥泄露、管理失败等严重问题,从而威胁整个云原生系统的安全。而 Sealed Secrets 和 Vault 就是解决这些问题的有…

作者头像 李华
网站建设 2026/4/23 13:59:15

基于深度学习的电动车头盔佩戴检测系统

博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实…

作者头像 李华
网站建设 2026/4/23 13:30:22

AI应用架构师如何优化增量学习应用实践

AI应用架构师如何优化增量学习应用实践 一、引入与连接:当AI模型遇上“实时数据洪流” 凌晨3点,某电商AI应用架构师李明盯着监控大屏上的“推荐准确率”曲线——这条原本平稳的曲线,正随着凌晨促销活动的开启快速下滑。原因很简单&#xff1a…

作者头像 李华
网站建设 2026/4/23 12:59:10

Java毕设选题推荐:基于springboot+vue的校园学习互助系统基于springboot的课程互助学习系统【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华