随着业务的不断扩展,我们的后台系统菜单项必定也会随着不断增加,这可能会给用户在寻找特定功能菜单时带来困扰。
进一步复杂化的是,不同子模块或者不同业务项目的菜单名存在命名模糊或相近的现象。
考虑到当前OpenAI的流行趋势,可以考虑利用 Text-Embedding 文本嵌入的方式来实现智能检索,以进一步提升用户体验和便利性。
1、利用LangChain,通过代码编排链路的方式来实现RAG检索
2、利用DIFY工作流,通过可视化配置工作流的方式来实现RAG检索
我们知道智能检索(Retrieval)的效果主要取决于使用的嵌入模型的质量以及知识库的内容。
这里我们先假设用户的输入均符合常理,非胡乱输入(在检索中会做过滤)。
1、嵌入模型(Embedding):指知识库文档嵌入处理的大模型,检索和导入知识库时均会使用该Embedding模型进行向量化处理。
这里我们使用OpenAI的嵌入大模型:text-embedding-3-large
附上一篇官方介绍的嵌入模型对比介绍文档:ada v2 VS text-embedding-3
(https://openai.com/index/new-embedding-models-and-api-updates/)
2、知识库(Knowledge base):指一系列紧密关联且始终保持更新的知识集合,它构成了 RAG 的核心基础。
在本次的实践中,该知识库即为我们在后台所导出的前端菜单路由数据。
而通常在使用搜索功能时,用户会输入的主要有以下几种情况:关键词检索、拼音检索、语义相似词检索、口语表达检索等
1、菜单名称、父级目录、菜单路径我们可以通过爬取接口的方式导出有效数据
2、拼音全拼、拼音首拼可以借助第三方拼音库批量生成
3、菜单描述,由于在前期的后台开发中,并没有维护菜单描述这个内容,那么是时候借助AI的能力啦
利用 LangChain + GPT3.5 遍历菜单批量生成菜单描述:
constprompt=PromptTemplate.fromTemplate(`#角色你是一位后台管理菜单的详细描述专家。你的主要职责是根据给定的父级目录名称以及菜单名称,生成简洁且准确的后台菜单描述。##技能###技能1:生成后台菜单的描述信息-根据提供的父级目录:<{parent_menu}>和菜单名称:<{menu}>,为该后台菜单构建一段不超过40个字的描述信息。-在描述信息中,应包括该菜单所能执行的主要操作。##限制-你返回的信息不能包含任何换行或者换行符。-父级目录和菜单名称在<>中。-描述信息必须用中文回答并且不超过40个字。-只处理与后台菜单描述信息相关的问题。如果用户询问了其他问题,不要回答。-对于未指定的信息,根据菜单名称推测其功能。{format_instructions}`);在LangChain的一通操作后,生成的内容某种程度上还是符合预期的。
后续则可以直接在已生成内容的基础上再进行调整,也更加方便。
在完成知识库的整理及嵌入模型的选型之后,我们再来看看如何实现内容的检索。
LangChain:LangChain 是一个开源编排框架,用于使用大型语言模型(LLM) 开发应用程序。
1、构建提示工程:定义提示词Prompt跟解析器Parser
(1)扩展搜索词组:解析用户的输入,拆解分词、扩展额外的搜索可能
(2)解析器:定义返回值的规范格式,这里利用官方提供的zodSchema例子
//2.1提示词consttask=`{format_instructions}Givenaquery,Expandtheprocessedwordsbytransformingsynonymsortranslatingtograsptheuser'sintentmoreprecisely.AnswerinChinese.ReturntheArray,thelengthofthearrayshouldbelessthan2.Thisisthequery:{query}Answer:`;//2.2解析器constparser=StructuredOutputParser.fromZodSchema(z.object({menuArray:z.array(z.string()).describe(''),}),);
2、构建查询链:利用LangChain提供的RunnableSequence顺序链连接:提示模板、LLM大模型、解析器
constchain=RunnableSequence.from([newPromptTemplate({template:task,inputVariables:['query'],partialVariables:{format_instructions:parser.getFormatInstructions()},}),newOpenAI({azureOpenAIApiKey:AZURE_API_KEY,azureOpenAIApiInstanceName:AZURE_INSTANCE_NAME,azureOpenAIApiDeploymentName:AZURE_DEPLOYMENT_16K_NAME,azureOpenAIApiVersion:AZURE_VERSION,temperature:0,modelName:'gpt-4',maxTokens:4096,}),parser,]);
3、知识库的嵌入存储:比如 Pinecone,云原生的向量数据库,利用langchain的pinecone第三方库,可将目录数据以Document的格式进行嵌入存储,不同的第三方库对接方式不同。
4、RAG检索:根据扩展的搜索词组,进行Retriever检索(余弦相似度的结果),并根据相似度分数过滤搜索结果,
最终根据分数进行排序返回 TOPK 结果,这里K取值3
在使用LangChain的过程中,整个环节从依赖引入、知识库构建、提示模板、解析器、RAG链的编写或多或少涉及到API的选择及代码的编写。
以及在调试的过程中相对不是那么直观,需要进行断点或日志定位问题。
在这个AI场景中,DIFY 能更加直接的配置及维护一整套流程。
1、知识库的构建:依旧选择以 EXCEL 文档作为数据源,便于整理与向量检索返回
(2)设置文本分段与清洗,可以在嵌入前计算预估消耗的token数与费用
(相比较LangChain,则免去了对接第三方向量存储库,翻阅对应API库的繁琐过程)
(3)支持直接对知识库进行增删查改,便于后续调整。
2、配置工作流:通过可视化的操作更直观的配置检索的链路
(1)可视化提示模板、条件分支、LLM、RAG链的流程
3、调试与日志:可预览整体流程执行情况及单功能调试,无需再打断点
LangChain可以自由选择需要的功能模块,优势在于灵活多变,即使不完全使用LangChain框架,也可以实现其部分功能。
Dify使用UI和平台集成的方式进行功能管理,提供一站式的解决方案,并能够方便地在开发环节中进行准确诊断和问题解决。
LangChain 这类的开发库(Library)像是有着锤子、钉子的工具箱。与之相比,Dify、Coze这类提供了更接近生产需要的完整方案。
所以在这种非深度开发、无需高度定制功能的场景下,或许用 DIFY 实现确实更简单便利。