[对比学习LangChain和MAF-11]RAG的实现

📅 2026/6/16 10:05:18
[对比学习LangChain和MAF-11]RAG的实现
在大语言模型LLM的实际应用中单靠模型自身的能力会遇到严重的瓶颈。RAG检索增强生成技术的出现正是为了解决原生LLM在商业和技术落地上的五大硬伤根治LLM的幻觉硬伤大语言模型本质上是基于概率的下一个词预测生成器:没有RAG当模型遇到不掌握的知识时它不会说我不知道而是会一本正经地胡编乱造产生严重的幻觉Hallucination引入RAG它强迫LLM进行开卷考试。模型必须基于检索到的确定性参考资料来组织语言从根本上压制了胡思乱想确保回答的严谨性跨越知识时效性的时间墙所有LLM在训练完成的那一刻其内部知识就已经冻结了:没有RAG模型无法得知今天早上刚发生的新闻也无法得知你刚刚更新的产品规格。如果想要让它知道必须重新花费数周时间、数百万资金去**微调Fine-tuning**或重新训练模型引入RAG无需触动模型本身。只需要把最新的新闻、实时的股市数据、或今天的会议记录放入外部知识库LLM通过即时检索就能立刻掌握最新动态解锁企业私有海量数据LLM是在公开的互联网数据上训练出来的对企业内部的机密知识一无所知没有RAG企业如果直接把自己的财务报表、员工手册、客户服务记录喂给公共LLM去训练会导致严重的商业机密泄露风险引入RAG企业的数据可以安全地保存在本地或私有云的向量数据库中。只有在用户提问时系统才会安全地检索相关片段提供给AI临时阅读完美保护了数据隐私实现答案的可追溯性与透明度原生LLM的输出是一个黑盒你很难知道它的某句话是从哪里学来的没有RAGAI 给出医疗建议或法律条款时用户无法判断其真伪不敢盲目采信引入RAG由于LLM是根据检索到的具体文本片段进行回答的系统可以轻松地在回答末尾附带来源引用例如“参考自《2026年Q1财务报告》第14页”从而建立了极高的信任度极低的管理与算力成本这是RAG能够在企业级应用中迅速普及的商业决定性原因对比模型微调SFT微调需要昂贵的GPU算力、专业的 AI 科学家、以及繁琐的数据标注且每次更新数据都要重新来过RAG的优势只需像管理网盘一样往数据库里增删改文档增量更新成本几乎为零。普通开发人员只需几行代码即可搭建完成以下面这个程序为例。我们通过LangGraph SDK来调用之前构建的Agent服务器并请求它回答**2026年斯诺克世界赛冠军是谁**这个问题。由于这个问题涉及到2026年的最新信息原生的LLM是无法回答的会产生幻觉但是由于我们在Agent服务器端引入了RAG技术Agent可以通过检索最新的知识库来给出正确的答案。usingAzure.AI.Projects;usingdotenv.net;usingMicrosoft.Extensions.AI;usingOpenAI;usingOpenAI.Responses;usingSystem.ClientModel;DotEnv.Load();varmodelEnvironment.GetEnvironmentVariable(MODEL)!;varapiKeyEnvironment.GetEnvironmentVariable(API_KEY)!;varendpointEnvironment.GetEnvironmentVariable(OPENAI_URL)!;varagentnewOpenAIClient(credential:newApiKeyCredential(key:apiKey),options:newOpenAIClientOptions{EndpointnewUri(endpoint)}).GetResponsesClient().AsAIAgent(model:model);varresponseawaitagent.RunAsync(message:2026年斯诺克世界赛冠军是谁);Console.WriteLine(response.Text);输出我目前**无法确定**2026年斯诺克世界锦标赛的冠军是谁。 原因是 - 虽然按赛程来看2026年世锦赛通常在**4月下旬至5月初**结束但 - 我无法获取**实时或最新比赛结果**而且不应在没有可靠数据的情况下猜测冠军。 你可以选择下面两种方式之一 1. **如果你想要的是已产生的正式结果**我可以告诉你去哪里快速核实如世界斯诺克官网、BBC Sport、世界斯诺克巡回赛官方微博等。 2. **如果你想要的是赛前或赛中的预测/分析**我可以根据当时的世界排名、签表、球员状态给你一个专业预测。 你是想问**“已经夺冠的是谁”**还是**“你预测谁会夺冠”**由于模型训练的时间早于2026年所以它无法知道2026年斯诺克世界锦标赛的冠军是谁。既然模型不均有相关的知识我们就根据用户的查询将相关的信息检索出来作为上下文提供给LLM来生成回答。接下来我们通过简单例子看看在LangChain和MAF中如何利用RAG来解决这个问题。1. LangChain传统的RAG基本建立在向量数据库基于自然语言的检索上。简单起见下面的程序程序将检索逻辑硬编码在工具函数search_context中。在这个模拟基于用户查询检索的工具函数中如果用户的查询中同时包含2026、斯诺克和世锦赛这几个关键词我们就返回一段相关的新闻稿。除了提供文本内容之外我们还附带了一个SourceLink和SourceName来说明这个信息的来源。fromlangchain.agentsimportcreate_agentfromlangchain.toolsimporttoolfromdotenvimportload_dotenv load_dotenv()tooldefsearch_context(query:str)-str:根据用户的查询检索相关的上下文信息if2026inqueryand斯诺克inqueryand世锦赛inquery:news\ 北京时间2026年5月5日英国谢菲尔德克鲁斯堡剧院决胜局最后一颗黑球落袋后00后中国球员吴宜泽挥拳庆祝。18:17吴宜泽击败肖恩·墨菲拿下2026年斯诺克世锦赛冠军。 社交平台上“吴宜泽夺冠”迅速登上热搜不少球迷将这场胜利形容为“中国斯诺克新的接力时刻”。这是继2025年赵心童夺冠之后中国选手再次问鼎这项赛事最高荣誉。这也是在经历2023年前后相关禁赛与争议事件后中国球员重新回到世界顶级竞争序列的重要节点。 相比十多年前丁俊晖在斯诺克领域的单点突破中国近几年开始稳定涌现世界级斯诺克选手。从个体突破到群体崛起这项运动在中国已经进入新的发展阶段。 ;returnf\ SourceLink: https://baijiahao.baidu.com/s?id1864605028122769594 SourceName: 每日经济新闻, Text:{news}returnNo relevant context found.agentcreate_agent(modelgpt-5.2-chat,tools[search_context],system_prompt你拥有一个根据用户查询检索相关上下文信息的工具search_context。请根据用户的查询调用工具获取相关的上下文信息并结合这些信息给出最终的回答。)resultagent.invoke(input{messages:[{role:user,content:2026年斯诺克世锦赛的冠军是谁}]})formessageinresult[messages]:message.pretty_print()我们在系统提示词中明确告诉模型它拥有一个名为search_context的工具这个工具可以根据用户的查询来检索相关的上下文信息。模型需要先调用这个工具来获取相关的信息然后才能结合这些信息来生成最终的回答。程序输出结果如下 Human Message 2026年斯诺克世锦赛的冠军是谁 Ai Message Tool Calls: search_context (call_fEqvdSEywsm9aCrJAeJJdQaO) Call ID: call_fEqvdSEywsm9aCrJAeJJdQaO Args: query: 2026年 斯诺克 世锦赛 冠军 Tool Message Name: search_context SourceLink: https://baijiahao.baidu.com/s?id1864605028122769594 SourceName: 每日经济新闻, Text: 北京时间2026年5月5日英国谢菲尔德克鲁斯堡剧院决胜局最后一颗黑球落袋后00后中国球员吴宜泽挥拳庆祝。18:17吴宜泽击败肖恩·墨菲拿下2026年斯诺克世锦赛冠军。 社交平台上“吴宜泽夺冠”迅速登上热搜不少球迷将这场胜利形容为“中国斯诺克新的接力时刻”。这是继2025年赵心童夺冠之后中国选手再次问鼎这项赛事最高荣誉。这也是在经历2023年前后相关禁赛与争议事件后中国球员重新回到世界顶级竞争序列的重要节点。 相比十多年前丁俊晖在斯诺克领域的单点突破中国近几年开始稳定涌现世界级斯诺克选手。从个体突破到群体崛起这项运动在中国已经进入新的发展阶段。 Ai Message 2026年斯诺克世锦赛的冠军是**吴宜泽**。 他在北京时间 **2026年5月5日** 于英国谢菲尔德克鲁斯堡剧院举行的决赛中击败了**肖恩·墨菲**成功夺冠。这也是继2025年赵心童夺冠之后中国选手连续第二年获得斯诺克世锦赛冠军。上面这段输出体现包含整个推理流程产生的四个消息Human Message用户的输入消息即“2026年斯诺克世锦赛的冠军是谁”Ai Message模型生成的消息其中包含了模型调用工具的相关信息工具名称、调用ID、调用参数等。Tool Message工具函数search_context的输出结果其中包含了检索到的相关上下文信息新闻内容、来源链接和来源名称。Ai Message模型根据工具函数的输出生成的最终回答即“2026年斯诺克世锦赛的冠军是吴宜泽”。关于RAG涉及的内容还有很多比如各种文档的加载、文本的分割、向量数据库、重排序甚至图数据库实现GraphRAG。如果希望了解关于RAG的更多内容可以参考我们之前的博客文章系列RAG在LangChain中的实现(共8篇)。2. MAF顾名思义RAG的本质上属于AIAgent输入增强的范畴。在ChatClientAgent的管道中具有专门用于输入和响应增强的组件那就是AIContextProvider。MAF的常规额RAG结解决方案由TextSearchProvider实现它就派生于AIContextProvider。这是上面演示实例针对MAF的实现版本。我们首先创建了一个TextSearchProvider调用其构造函数提供的第一个参数是一个指向SearchAsync函数的委托TextSearchProvider正是使用它来完成上下文的检索。接下来我们创建了一个针对OpenAIClient的ChatClientAgent在调用AsAIAgent扩展方法时我们提供了一个ChatClientAgentOptions对象并将之前创建的TextSearchProvider添加到AIContextProviders属性中。usingAzure.AI.Projects;usingdotenv.net;usingMicrosoft.Agents.AI;usingMicrosoft.Extensions.AI;usingOpenAI;usingOpenAI.Responses;usingSystem.ClientModel;usingstaticMicrosoft.Agents.AI.TextSearchProvider;DotEnv.Load();varmodelEnvironment.GetEnvironmentVariable(MODEL)!;varapiKeyEnvironment.GetEnvironmentVariable(API_KEY)!;varendpointEnvironment.GetEnvironmentVariable(OPENAI_URL)!;vartextSearchProvidernewTextSearchProvider(searchAsync:SearchAsync);varagentnewOpenAIClient(credential:newApiKeyCredential(key:apiKey),options:newOpenAIClientOptions{EndpointnewUri(endpoint)}).GetChatClient(model:model).AsIChatClient().AsAIAgent(options:newChatClientAgentOptions{AIContextProviders[textSearchProvider]});varresponseawaitagent.RunAsync(message:2026年斯诺克世界赛冠军是谁);Console.WriteLine(response.Text);staticTaskIEnumerableTextSearchResultSearchAsync(stringquery,CancellationTokencancellationToken){if(query.Contains(2026)query.Contains(斯诺克)query.Contains(世界赛)){varnews 北京时间2026年5月5日英国谢菲尔德克鲁斯堡剧院决胜局最后一颗黑球落袋后00后中国球员吴宜泽挥拳庆祝。18:17吴宜泽击败肖恩·墨菲拿下2026年斯诺克世锦赛冠军。 社交平台上“吴宜泽夺冠”迅速登上热搜不少球迷将这场胜利形容为“中国斯诺克新的接力时刻”。这是继2025年赵心童夺冠之后中国选手再次问鼎这项赛事最高荣誉。这也是在经历2023年前后相关禁赛与争议事件后中国球员重新回到世界顶级竞争序列的重要节点。 相比十多年前丁俊晖在斯诺克领域的单点突破中国近几年开始稳定涌现世界级斯诺克选手。从个体突破到群体崛起这项运动在中国已经进入新的发展阶段。;varresultnewTextSearchResult{RawRepresentationnews,SourceLinkhttps://baijiahao.baidu.com/s?id1864605028122769594,SourceName每日经济新闻,Textnews};returnTask.FromResultIEnumerableTextSearchResult([result]);}else{returnTask.FromResultIEnumerableTextSearchResult([]);}}我们最终调用RunAsync方法来请求Agent回答**2026年斯诺克世界赛冠军是谁**这个问题。程序输出结果如下2026年斯诺克世界锦标赛冠军是**吴宜泽**。 据《每日经济新闻》报道北京时间2026年5月5日在英国谢菲尔德克鲁斯堡剧院举行的决赛中吴宜泽在决胜局击败肖恩·墨菲成功夺得2026年斯诺克世锦赛冠军。这也是继2025年赵心童夺冠之后中国选手再次问鼎这项斯诺克最高荣誉赛事。 来源每日经济新闻 链接https://baijiahao.baidu.com/s?id1864605028122769594关于TextSearchProvider的设计和实现原理可以参考我们之前的博客文章TextSearchProvider在MAF中实现RAG。