RAG应用构建及优化

前言


在人工智能快速发展的今天,传统的生成模型在处理复杂查询和提供准确信息方面仍面临诸多挑战,如知识更新滞后和上下文理解不足。为了解决这些问题,检索增强生成(RAG)技术应运而生。本课程介绍了RAG的基本概念及其工作原理,包括RAG配合大模型在提升内容生成准确性和相关性方面的独特优势,并展望其未来的发展趋势。本课程为你提供深入的理论知识和实用的应用指导,帮助你在RAG技术的学习和实践中迈出坚实的一步。

[羽毛笔]本节目标 


学完本节课程后,你将能够:

→  了解什么是检索增强生成(RAG)

→  了解检索增强生成(RAG)的实现原理。

→  了解检索增强生成(RAG)的优势。

 

 

1、什么是检索增强生成(RAG)

1.1  检索增强生成的概念

检索增强生成(Retrieval-Augmented Generation, RAG)是一种结合了信息检索和文本生成技术的新型自然语言处理方法。这种方法增强了模型的理解和生成能力。

相比于传统的生成模型,检索增强生成可以通过添加来自其他数据源的上下文并通过培训补充大模型的原始知识库来提高搜索体验的相关性。 这增强了大型语言模型的输出,而无需重新训练模型。 其他信息来源的范围包括 LLM 未受过培训的互联网上的新信息、专有业务背景或属于企业的机密内部文件。

 

 

接下来我们用一个简单易懂的例子来解释下检索增强生成。你是一个导游,在你的工作中遇到了问题。你把当导游时无法给游客提供专业、全面信息的困惑告诉了你的主管,于是主管给了你一本志愿者手册。游客询问最近的全聚德烤鸭店在哪里,你拿出了志愿者手册,翻到了全聚德烤鸭店的位置,然后告诉了游客具体的走法。

              用系统资料导游

你又遇到了一个游客,游客眼睛不太好,他想知道如何前往银锭桥,此时你也犯难了,志愿者手册并没有该细节内容,但是此时游客手里有一张导览图,你接过地图,经过简单的分析,按照地图指出应该如何前往银锭桥。

用系统资料和用户资料结合来导游

假设我们是开发大模型导游助理的技术团队,我们把导游助理比作志愿者。

在第一种情况下,“志愿者手册”就是我们在开发系统的时候就配置好的知识库,因此导游助理可以从系统默认的知识库中获取烤鸭店的地址,然后生成导航路径给游客。

在第二种情况中,假设我们的系统支持用户上传个性化资料,来更好地满足个性化业务需要。换句话说,系统支持用户添加垂直领域知识,构建私域知识库。那么,当游客向志愿者提供一份个性化导航资料时,系统可以结合游客的垂直领域知识与系统预置的知识共同为游客提供服务。

第一种方案的知识库,可以理解是公司统一配置的知识库;第二种方案中,每个团队或者用户还可以根据自己的需要来增加私域定制化知识库。显然,第二种系统更灵活,不需要复杂的操作就能补充了业务知识。但总体来看,这两个系统都是通过知识库来增强导游助理的能力,减少“幻觉”回答的情况(即导游助理不是编造一个像模像样的地址,而是按照已有知识来回答)。

在这个案例中,我们明白了检索增强生成包括三个步骤,建立索引、检索、生成。如果说大模型导游助理是一位志愿者,那么我们给志愿者们准备“志愿者手册”的过程就是建立知识库索引,志愿者查看资料就是系统在检索知识库,志愿者基于检索到的资料充分思考并回答用户的问题就是生成答案。

1.2 RAG的实现原理

那么RAG是怎样将信息检索与文本生成结合起来的呢?请看大模型RAG基本流程图:

    大模型RAG基本工作流

如图所示,RAG主要由两个部分构成:

建立索引:首先要清洗和提取原始数据,将 PDF、Docx等不同格式的文件解析为纯文本数据;然后将文本数据分割成更小的片段(chunk);最后将这些片段经过嵌入模型转换成向量数据(此过程叫做embedding),并将原始语料块和嵌入向量以键值对形式存储到向量数据库中,以便进行后续快速且频繁的搜索。这就是建立索引的过程。

检索生成:系统会获取到用户输入,随后计算出用户的问题与向量数据库中的文档块之间的相似度,选择相似度最高的K个文档块(K值可以自己设置)作为回答当前问题的知识。知识与问题会合并到提示词模板中提交给大模型,大模型给出回复。这就是检索生成的过程。

了解了RAG的原理后,我们发现现阶段,RAG有诸多的优势,使用大模型配合RAG比传统的生成模型可以显著提高生成内容的准确性和相关性。 同时还可以应用在各种专业的垂直领域,带来更高的生产效率。接下来我们来了解一下这些优势。

 

2、大模型配合RAG的优势

2.1 提升信息的准确性和相关性

2.1.1 实时知识更新的优势

通过结合外部知识库,RAG技术能够显著提高生成内容的准确性和相关性。传统的生成模型主要依赖于预训练时所积累的知识库,这些知识库虽然庞大,但其信息往往在模型训练完成后就固定下来,无法与时俱进。随着时间的推移,新的事件、科技进步和领域知识不断涌现,传统模型难以及时更新这些信息,导致生成的内容可能变得过时或不全面。RAG通过实时检索外部知识库,如互联网资源、最新的学术论文或企业内部数据库,动态获取最新的相关文档,能够有效弥补预训练模型知识更新滞后的不足,使得生成内容保持最新和准确。

2.1.2 提供准确及时的答案

例如,当用户询问关于最新科技产品的问题时,传统生成模型可能只能基于其预训练时所学的信息进行回答,这些信息可能已经过时或缺乏细节。而RAG技术可以实时从互联网或其他实时更新的数据源中检索到最新的产品发布信息、用户评价和专业评测,从而生成更加准确和相关性更高的答案。这不仅提升了回答的可靠性,还增强了用户的满意度和信任感。此外,RAG还能够根据具体的查询需求,筛选出最相关的文档内容,确保生成的回答与用户问题高度契合,提供更具针对性和实用性的解决方案。

2.2 增强上下文理解能力

2.2.1 深度理解用户需求

在处理复杂的查询时,上下文的理解至关重要。RAG不仅能够利用自身的语言理解能力,还可以通过检索相关的上下文信息来更好地理解用户的需求。这意味着系统不仅依赖于预训练模型的知识,还能动态获取与当前对话相关的外部文档和数据,增强对用户意图的把握。例如,当用户提出一个涉及多个专业领域的问题时,RAG可以通过检索相关文献和资料,全面分析用户的需求,从而生成更加准确和详尽的回答。这种深度理解能力使得RAG在面对复杂和多层次的问题时,能够提供更具针对性和实用性的解决方案。

2.2.2 连贯一致的多轮对话

RAG技术在多轮对话中表现出色,能够通过结合之前的对话记录和检索到的相关文档,保持对话的一致性和连贯性。这种能力在技术支持、客户服务和教育辅导等场景中尤为重要。例如,在一个涉及多个步骤的技术支持对话中,用户可能会逐步描述问题的不同方面。RAG能够回顾之前的对话内容,检索相关的技术文档,确保每一次响应都与前文保持一致,并且基于最新的信息提供详细的解决方案。这不仅提升了用户体验,还增强了系统对复杂任务的处理能力,使得整个对话过程 更加顺畅和高效。

2.3 减少“幻觉”现象

2.3.1 幻觉现象及其影响

“幻觉”是指生成模型在缺乏足够信息的情况下编造答案的现象。这种现象可能导致生成的内容与实际情况不符,甚至完全错误。幻觉不仅削弱了用户对生成内容的信任,还可能在关键应用场景中引发严重后果,如医疗诊断、法律咨询等领域,因错误信息导致误导性决策或行动。

2.3.2 RAG技术减少幻觉的机制

RAG通过引入外部知识库,减少了模型在生成过程中凭空编造信息的可能性。当模型无法从其内部知识库中找到合适的答案时,它可以依靠检索到的外部文档来生成更加可靠和真实的信息。这种结合确保了生成内容基于实际存在的资料和数据,从而提高了回答的准确性和可信度,显著降低了幻觉现象的发生,增强了系统的整体可靠性和用户满意度。

2.4 支持个性化和垂直领域应用

2.4.1 整合私域知识库支持高度个性化应用

RAG不仅可以利用公共知识库,还可以整合私域知识库,从而支持高度个性化的应用场景。例如,在企业环境中,RAG可以接入企业的内部文档和专有数据,为企业员工提供定制化的信息和服务。这种整合使得员工能够快速获取与其工作相关的具体信息,显著提高工作效率。通过访问企业内部的知识库,RAG能够提供精准的指导、流程说明和问题解决方案,帮助员工更好地完成任务。此外,整合私域知识库还确保了敏感信息的安全性,企业可以通过严格的权限管理和数据保护措施,防止未经授权的访问,保障内部数据的机密性和完整性。

2.4.2 垂直专业领域的精准问答系统

RAG技术的灵活性使其在特定领域的专业问答系统中同样表现出色。例如,在医疗、法律和金融等行业,RAG可以整合大量的专业文献和行业数据,提供更加精准和专业的服务。在医疗领域,RAG能够访问最新的医学研究成果和临床指南,辅助医生做出更为准确的诊断和治疗决策;在法律领域,RAG可以检索相关的法律条文和案例,帮助律师迅速找到支持其论点的法律依据;在金融领域,RAG能够分析市场数据和财经报告,为投资者提供有价值的分析和建议。这些应用不仅提升了专业服务的质量和效率,还为用户提供了高度定制化的解决方案,满足了不同行业和用户的特定需求。

 

通过以上分析可以看出,检索增强生成(RAG)不仅解决了传统生成模型的一些固有问题,还在多个方面带来了显著的优势。在未来,随着技术的不断发展和完善,RAG有望在更多领域发挥重要作用,推动自然语言处理技术迈向新的高度。接下来我们来了解下RAG的未来趋势。

 

 

3、RAG的未来趋势

检索增强生成技术正处于快速发展阶段,其未来趋势涵盖了从安全性再到个性化服务等多个方面。随着技术的进步,我们可以期待RAG将在更多领域展现其潜力,为用户带来更加智能、高效和个性化的体验。 接下来我们来了解一下这些趋势:

3.1 对话式AI的改进

RAG技术对于构建更加自然流畅的对话式AI至关重要。未来的发展方向可能包括改进长程记忆管理,使得系统能够在长时间对话中保持上下文连贯性;以及开发更智能的情感识别与响应机制,使机器能够更好地理解人类的情绪,并做出相应的反应。

3.1.1 改进长程记忆管理

维持上下文连贯性是构建高质量对话系统的核心挑战之一。当前的大多数对话系统在处理短期对话时表现良好,但在长时间的互动中,往往难以保持上下文的一致性和连贯性。这不仅影响用户体验,还可能导致误解和不相关的回应。

RAG技术在长程记忆管理中的作用:

  • 动态上下文检索:通过RAG,系统可以实时从庞大的知识库中检索与当前对话相关的历史记录和背景信息,确保每次响应都能参考之前的对话内容。这种动态检索能力有助于系统在长时间对话中保持上下文的连贯性。
  • 知识更新与扩展:RAG允许对话系统持续更新其知识库,确保系统能够处理最新的信息和用户需求。这样,系统不仅能记住之前的对话内容,还能随时获取新的知识,增强其应对复杂对话的能力。
  • 分层记忆结构:未来的RAG系统可能会采用分层记忆结构,将对话历史按照不同的主题和时间段进行分类和存储。这种结构化的记忆管理方式能够更高效地检索相关信息,提升对话的连贯性和准确性。

实际应用案例:例如,在一个医疗咨询对话系统中,患者可能会多次咨询不同的症状和治疗方案。通过RAG技术,系统不仅能记住患者的历史咨询内容,还能实时检索相关医学文献和最新研究成果,提供更加精准和个性化的建议。

3.1.2 开发更智能的情感识别与响应机制

理解并响应用户情感是提升对话式AI自然性的关键一步。人类在交流中不仅传递信息,还表达情感和态度。一个能够识别和回应用户情感的AI系统,能够显著增强用户的互动体验。

RAG技术在情感识别与响应中的应用:

  • 情感数据检索:RAG系统可以从情感分析数据库中检索与当前用户情感相关的内容,帮助生成更具同理心的回应。例如,当用户表达出沮丧或困惑时,系统可以检索到安慰性的话语或解决方案,给予适当的支持。
  • 多模态情感理解:结合文本、语音和面部表情等多种数据源,RAG技术能够更全面地理解用户的情感状态。通过多模态的数据检索与融合,系统可以生成更加精准和自然的情感响应。
  • 个性化情感适应:RAG系统可以根据用户的情感历史和偏好,调整响应的语气和内容。例如,对于经常表达焦虑的用户,系统可以采用更加温和和鼓励的语言,提升用户的满意度和信任感。

实际应用案例:在心理咨询对话系统中,用户可能会表达各种复杂的情感和情绪需求。通过RAG技术,系统能够实时检索到相关的心理支持内容和应对策略,并结合用户的情感状态,生成具有同理心和支持性的回应,帮助用户缓解情绪压力。

3.2 隐私保护与安全

随着RAG技术被广泛应用于企业级和个人级服务,如何确保用户数据的安全与隐私成为了一个关键问题。未来的RAG框架可能会集成更多的隐私保护措施,比如差分隐私、同态加密等技术,以确保敏感信息不被泄露。以下展开两点介绍注重隐私保护与安全的趋势:

3.2.1 差分隐私(Differential Privacy)

1. 在RAG中的应用

差分隐私是一种数学框架,通过在数据查询结果或统计分析中添加随机噪声,以保护个人数据的隐私,使得即使在分析结果中,单个数据条目的信息也难以被推断出来。这种机制在RAG(Retrieval-Augmented Generation)中的应用体现在两个方面:首先,在训练阶段,通过在梯度更新过程中引入噪声,可以有效保护训练数据集的隐私性,使得即便在模型训练过程中也不泄露个体数据;其次,在生成内容的阶段,差分隐私技术通过在生成的输出中添加噪声,降低了生成内容暴露用户敏感信息的风险,从而确保用户交互的隐私安全。

2. 实际案例

一些企业和研究机构已经在其机器学习平台中实现差分隐私。例如,谷歌在TensorFlow中引入了差分隐私库(TF Privacy),帮助开发者在ML模型训练过程中保护数据隐私。类似地,未来的RAG系统也可以集成差分隐私技术,以确保用户数据在各个处理阶段的安全性。

3.2.2 同态加密(Homomorphic Encryption)

1. 在RAG中的应用

同态加密是一种高级加密技术,允许在数据保持加密状态下执行特定计算操作,计算后的结果仍然是加密的,只有在解密后才能得到正确的结果,这使得在数据处理过程中无需暴露敏感信息,从而极大地提高了数据安全性。在RAG(Retrieval-Augmented Generation)系统中,同态加密的应用体现在两个方面:首先,在数据存储与传输过程中,用户数据使用同态加密技术进行加密,确保即使攻击者获得了存储或传输的数据,也无法解密或利用这些数据;其次,在数据处理和生成响应时,数据始终保持加密状态,例如在检索和生成内容的中间步骤中应用同态加密,避免暴露任何敏感信息,从而进一步保障数据的隐私和安全。

2. 实际应用与前景

同态加密已经在一些敏感数据处理领域得到应用,如金融和医疗。未来,随着计算性能的提升和算法优化的进步,RAG系统中的同态加密也将变得更加可行。例如,IBM和微软等公司正在开发和推广同态加密技术,试图降低其计算成本并推广其应用范围。

3.3 个性化与定制化

随着用户需求日益多样化,未来的RAG解决方案将更加注重个性化体验。这意味着系统不仅要能够接入私域知识库,还要能够根据用户的偏好、历史行为和特定需求进行个性化推荐和服务。定制化的RAG平台将允许企业和个人根据自己的具体要求配置和调整系统,从而实现最佳的服务效果。

3.3.1 个性化体验

1. 使用私域知识库

未来的RAG系统将需要集成用户特定的私域知识库,包含个性化的数据和信息。这种整合不仅能够增强模型对个人上下文的理解,还能确保信息检索和内容生成更贴合用户需求。同时,私域知识库必须具备动态更新的能力,以及时反映用户的最新需求和环境变化。这种动态更新机制能够保持生成内容的准确性和相关性,使RAG系统始终能够提供最新、最符合用户期望的信息和服务。通过集成私域知识与动态知识更新,未来的RAG系统将实现更加智能化和个性化的应用,显著提升用户体验和系统的整体效能。

2. 利用用户偏好和历史行为

通过分析用户的偏好历史、行为模式和互动记录,系统能够准确了解每位用户的特定兴趣和需求。这一过程涉及大量的数据收集和分析,为后续的行为预测和内容推荐奠定基础。利用先进的机器学习模型,RAG系统能够预测用户的未来行为和需求,从而为用户推荐个性化的内容和选项。例如,在电子商务平台上,RAG系统可以根据用户的历史购买记录和浏览行为,生成精准的商品推荐,提升用户的购物体验和满意度。通过用户画像构建与行为预测的有机结合,未来的RAG系统将实现更加智能和贴合用户需求的个性化服务,显著增强用户的互动体验和系统的整体效能。

3.3.2 定制化服务

1. 配置灵活的RAG平台

首先,企业可以根据自身的行业需求和业务流程,定制化RAG系统的功能模块,调整检索机制和生成模型,以满足特定的服务需求。这种企业级定制不仅能够提升系统的适应性和效率,还能帮助企业在竞争中获得独特的优势,实现精准的业务支持与优化。同时,个人用户也能够通过交互设置实现个性化设置,类似于使用个性化智能助理。用户可以根据自身偏好调整系统的响应风格、信息推送频率和内容格式等,从而获得更加贴合个人需求的服务体验。这种个性化设置不仅提升了用户的互动体验和满意度,也使得RAG系统能够更好地满足不同用户群体的多样化需求。通过企业级定制与个性化设置的有机结合,未来的RAG系统将变得更加灵活和强大,广泛应用于各类复杂的业务场景和个人化服务中,显著提升整体效能和用户满意度。

2. 可扩展的系统架构

RAG采用模块化设计易于扩展和修改。用户或企业可以根据不同的应用场景,灵活地添加或移除功能模块,从而实现定制化的解决方案。此外,未来的RAG平台将提供丰富的API和插件接口,允许第三方开发者扩展平台功能,满足多样化的需求。这不仅促进了一个活跃的第三方开发者生态系统的形成,也增强了RAG平台的灵活性和适应性。通过模块化设计与开放的API生态,RAG系统能够迅速响应市场变化和用户需求,推动创新发展,并在各类复杂应用场景中发挥更大的作用,显著提升整体效能和用户体验。

随着技术的发展,大模型和RAG会运用得越来越广泛,覆盖多个行业和领域,为各类用户提供更加智能化和高效的解决方案。

[进度: 已完成]本节小结


在本节课程中,我们学习了这些内容:

  • RAG的基本概念和实现原理;
  • 大模型与RAG结合所带来的优势,如实时知识更新、个性化服务和多领域适应能力;
  • RAG的未来发展趋势。

除了课程中提到的企业定制化服务、专业领域问答系统和多轮对话支持,RAG技术在其他领域同样展现出巨大的应用潜力。医疗健康行业也将从大模型和RAG技术的发展中受益。医生和医疗专业人员可以通过RAG快速检索最新的医学研究、病例分析和治疗指南,辅助诊断和制定治疗方案,提升医疗服务的精准性和效率。这些技术的应用将推动医疗行业的智能化转型,提升整体医疗水平和公共健康水平。

 

前言


前面的小节我们学习了RAG的概念和实现原理。在本小节中,我们的目标是帮助你在百炼平台上构建一个可以调用的RAG应用,并了解如何通过优化策略,克服RAG可能带来的挑战,从而提升其在实际应用中的效果和可靠性。通过本小节的学习,你将获得实用的技能和方法,以便在多种场景下高效地构建和优化RAG模型。

 

[羽毛笔]本节目标 


学完本节课程后,你将能够:

→  了解如何构建RAG应用。

→  了解如何改进RAG应用的效果。

 

1、快速构建RAG应用

通过对前面课程的学习,我们学习了RAG的概念和优势,接下来我们通过阿里云百炼的应用中心快速创建一个RAG应用。

1.1 数据管理-导入数据

首先,我们先进入百炼控制台在左侧导航栏中,选择数据管理。在结构化数据页签,选择“默认类目”后,点击“导入数据”,然后通过“本地上传”的方式导入数据。导入数据需要花费一定的时间,需要耐心等待数据转为“导入完成”的状态(通过手动点击刷新按钮)。

1.2 创建知识索引

  1. 在左侧导航栏中,选择数据应用 > 知识索引。点击创建知识库,输入知识库名称,保持默认配置,点击下一步

 

  1. 选择相关文件,点击下一步

 

  1. 保持默认配置,点击导入完成,系统自动进行文档解析。

说明:文档解析需要一定时间,请您耐心等待,直至状态变更为“解析完成”状态,才能在后续的文档问答过程中被检索到。

 

  1. 返回知识库索引主页, 获取知识索引ID。知识索引支持与百炼Assistant API结合使用,支持RAG和插件的组合调用。

1.3 创建应用

在左侧导航栏中,选择我的应用。单击新增应用 > 智能体应用 > 直接创建

进入创建应用页面,配置以下参数:

  1. 单击选择模型。同时,还支持配置与模型生成内容相关的参数,例如,温度系数等。
  2. 打开知识库检索增强开关,单击“配置知识库”。
  3. 选择知识库,即在上一步中创建的知识索引。
  4. 单击“发布”按钮。

应用发布后,即可在右侧的窗口进行效果测试。

 

  1. 应用列表页面,获取应用ID。后续可以通过API/SDK调用应用。

 

1.4 调用应用

1. 前提条件

2.通过API/SDK调用应用

您需要将YOUR_APP_ID替换为已获取的应用ID,代码才能正常运行。

如下是python代码的调用。Java/curl调用见官方文档

import os
from http import HTTPStatus
from dashscope import Application


def call_agent_app():
    response = Application.call(app_id='YOUR_APP_ID',
                                prompt='百炼的业务空间是什么?如何使用业务空间?',
                                api_key=os.getenv("DASHSCOPE_API_KEY"),  # 若没有配置环境变量,请用百炼API Key将本行替换为:api_key="sk-xxx",
                                )

    if response.status_code != HTTPStatus.OK:
        print('request_id=%s, code=%s, message=%s\n' % (response.request_id, response.status_code, response.message))
    else:
        print('request_id=%s\n output=%s\n usage=%s\n' % (response.request_id, response.output, response.usage))


if __name__ == '__main__':
    call_agent_app()

3.通过Assistant API调用

您需要将YOUR_PIPELINE_ID替换为已经获取的知识索引ID,代码才能正常运行。其中${document1}为占位符,知识库检索回来的内容会替换instructions中的${document1},请确保RAG工具中定义query_word/value的占位符与instructions中占位符一致。

以下是Java的调用代码,Python调用见官方文档

import com.alibaba.dashscope.assistants.Assistant;
import com.alibaba.dashscope.assistants.AssistantParam;
import com.alibaba.dashscope.assistants.Assistants;
import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ListResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.AssistantThread;
import com.alibaba.dashscope.threads.ContentText;
import com.alibaba.dashscope.threads.ThreadParam;
import com.alibaba.dashscope.threads.Threads;
import com.alibaba.dashscope.threads.messages.Messages;
import com.alibaba.dashscope.threads.messages.TextMessageParam;
import com.alibaba.dashscope.threads.messages.ThreadMessage;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.RunParam;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.tools.ToolBase;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.SuperBuilder;
import java.lang.System;


public class AssistantApiRag {
    public static Assistant createAssistant(String pipelineId) throws ApiException, NoApiKeyException {
        //注意instructions的${document1}占位符和buildPromptRa的${document1}占位符必须保持一致
        AssistantParam assistantParam = AssistantParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-max") 
                .name("smart helper")
                .description("智能助手,支持知识库查询和插件调用。")
                .instructions("你是一个智能助手,请记住以下信息。${document1}")
                .tool(ToolRag.builder()
                        .promptRa(ToolRag.buildPromptRa("${document1}", pipelineId))
                        .build())
                .build();
        Assistants assistants = new Assistants();
        return assistants.create(assistantParam);
    }

    public static void sendMessage(Assistant assistant, String message) throws NoApiKeyException, InputRequiredException, InvalidateParameter, InterruptedException {
        Threads threads = new Threads();
        AssistantThread assistantThread = threads.create(ThreadParam.builder().build());

        Runs runs = new Runs();
        // create a new message
        TextMessageParam textMessageParam = TextMessageParam.builder()
                .role("user")
                .content(message)
                .build();
        Messages messages = new Messages();
        ThreadMessage threadMessage = messages.create(assistantThread.getId(), textMessageParam);
        System.out.println(threadMessage);

        RunParam runParam = RunParam.builder().assistantId(assistant.getId()).build();
        Run run = runs.create(assistantThread.getId(), runParam);
        while (true) {
            if (run.getStatus().equals(Run.Status.CANCELLED) ||
                    run.getStatus().equals(Run.Status.COMPLETED) ||
                    run.getStatus().equals(Run.Status.FAILED) ||
                    run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
                    run.getStatus().equals(Run.Status.EXPIRED)) {
                break;
            } else {
                Thread.sleep(1000);
            }
            run = runs.retrieve(assistantThread.getId(), run.getId());
        }

        System.out.println(run);

        GeneralListParam listParam = GeneralListParam.builder().limit(100L).build();
        ListResult<ThreadMessage> threadMessages = messages.list(assistantThread.getId(), listParam);
        for (ThreadMessage threadMessage2 : threadMessages.getData()) {
            System.out.printf("content: %s\n", ((ContentText) threadMessage2.getContent().get(0)).getText().getValue());
        }
    }

    public static void main(String[] args) throws NoApiKeyException, InputRequiredException, InvalidateParameter, InterruptedException {
        String pipelineId = "YOUR_PIPELINE_ID";
        Assistant assistant = createAssistant(pipelineId);
        sendMessage(assistant, "百炼是什么?");
    }
}

@Data
@EqualsAndHashCode(callSuper = false)
@SuperBuilder
class ToolRag extends ToolBase {
    static {
        registerTool("rag", ToolRag.class);
    }

    @Builder.Default
    private String type = "rag";

    @SerializedName("prompt_ra")
    private JsonObject promptRa;

    @Override
    public String getType() {
        return type;
    }

    public static JsonObject buildPromptRa(String placeholder, String pipelineId) {
        JsonObject queryWord = new JsonObject();
        queryWord.addProperty("type", "str");
        queryWord.addProperty("value", placeholder);

        JsonObject properties = new JsonObject();
        properties.add("query_word", queryWord);

        JsonObject parameters = new JsonObject();
        parameters.addProperty("type", "object");
        parameters.add("properties", properties);

        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("pipeline_id", pipelineId);
        jsonObject.add("parameters", parameters);

        return jsonObject;
    }
}

2、RAG的局限性

随着对RAG(Retrieval-Augmented Generation)应用的深入使用,我们可能会发现尽管该系统在某些场景下能够提供有效的帮助,但仍然存在诸多需要改进的地方。这些问题不仅影响了用户体验,还可能削弱用户对系统的信任度。以下是几个典型的问题及其背后的原因分析:

2.1. 问题表述模糊或抽象

当用户提出的问题较为抽象或概念模糊时,即使是最先进的大语言模型也可能无法准确理解用户的意图。例如,如果一位用户询问“兰州拉面去哪吃?”而其实际意图是寻找附近的兰州拉面店,那么,如果知识库中关于“兰州”和“拉面”的相关信息主要集中在位于兰州市内的餐馆地址上,系统很可能会错误地建议用户购买前往兰州的机票或火车票。这种情况下,为了提高理解和响应的质量,一个有效的方法是对用户提问进行重构,使其更加具体明确。通过引导用户更清晰地表达需求,可以显著提升系统的理解能力和回复准确性。

2.2. 知识库检索失败

另一个常见问题是知识库未能检索到与用户查询相关的信息。这可能是由于数据预处理不当、索引机制设计不合理或是检索算法参数设置不恰当等原因造成的。以采用“K个最相似文档块”策略为例,若设定的K值过小,则很可能导致即便有相关内容存在于数据库中也无法被有效利用。设想这样一个情景:作为旅游指南的知识库内存储了大量的关于兰州拉面制作方法、历史渊源以及地方特色产品的信息,而对于周边餐饮地点的具体位置描述却相对较少。当游客试图了解如何到达最近的兰州拉面店时,系统很可能只会返回有关面条制作工艺等方面的资料,而忽略了最关键的位置指引信息。因此,优化知识库结构并调整检索逻辑成为了改善此类问题的关键所在。

2.3. 缺乏答案验证机制

即使是在理想条件下——即系统成功解析了用户意图并且正确识别出了相关信息——最终生成的答案仍可能存在误导性。比如,在上述例子中,假设系统已经找到了距离当前位置最近的两家兰州拉面馆,并给出指示:“向北走200米就到了”。虽然这一回答表面上看起来是正确的,但实际上它并未考虑到具体的地理环境因素。假如目标地点位于一片湖泊之后,那么直接朝北行走显然是不可行的;正确的路径应该是先向东行走一段距离,再绕过障碍物继续前进。由此可见,单纯依靠现有信息生成答案而不对其进行进一步校验的做法显然不够严谨。为此,引入一套完善的答案验证机制显得尤为重要,它可以确保输出内容不仅符合逻辑而且具备实用性。

综上所述,要使RAG应用真正发挥出应有的效能,就需要针对以上提到的各种挑战采取相应措施加以解决。通过对用户输入的精细化处理、加强知识库建设和管理以及建立健全的答案审核流程,我们可以逐步克服这些难题,从而为用户提供更加优质的服务体验。我们会发现许多改进标准 RAG 框架的方法,下面我们将一起了解这些改进思路。

 

                                          

3、优化RAG的应用效果

为了持续改进我们的 RAG 应用,首要任务应当是构建一套严谨的评测指标体系,并邀请业务领域专家作为评测方共同参与评测工作,我们可以设置与我们业务相关的多种问题场景,系统性地检查一个RAG系统反应快不快,回答准不准,有没有理解用户问题的意图等方面。通过科学全面的评测,我们可以了解到系统在哪些地方做得好,哪些地方需要改进,从而帮助开发者让RAG系统更好的服务于业务需求。

RAG系统一般包括检索生成两个模块,我们做评测时就可以从这两个模块分别入手建立评价标准和实施方法,当然你也可以用最终效果为标准,建立端到端的评测。在评测指标设计上,我们主要考察检索模块的准确性,如准确率、召回率、F1值等等;在生成模块,我们主要考察生成答案的价值,如相关性、真实性等等。

我们可以引入业界认可的一些通用评估策略,比如,你可以参考Ragas提及的评测矩阵指南,你也可以建立一些自己的评测指标,这些评测方法将会有助于你量化和改进每一个子模块的表现。

3.1 提升索引准确率

  • 优化文本解析过程

在构建知识库的时候,我们首先需要正确的从文档中提取有效语料。因此,优化文本解析的过程往往对提升RAG的性能有很大帮助。例如,从网页中提取有效信息时,我们需要判断哪些部分应该被去掉(比如页眉页脚标签),哪些部分应该被保留(比如属于网页内容的表格标签)。

  • 优化chunk切分模式

Chunk就是数据或信息的一个小片段或者区块。当你在处理大量的文本、数据或知识时,如果你一次性全部交给大模型来阅读和处理,效率是非常低的。所以,我们把它们切分成更小、更易管理的部分,这些部分就是chunk。每个chunk都包含了一些有用的信息,这样当系统根据用户的问题寻找某个知识时,它可以迅速定位到与答案相关信息的chunk,而不是在整个数据库中盲目搜索。因此,通过精心设计的chunk切分策略,系统能够更高效地检索信息,就像图书馆里按照类别和标签整理书籍一样,使得查找特定内容变得容易。优化chunk切分模式,就能加速信息检索、提升回答质量和生成效率。具体方法有很多:

  1. 利用领域知识:针对特定领域的文档,利用领域专有知识进行更精准的切分。例如,在法律文档中识别段落编号、条款作为切分依据。
  2. 基于固定大小切分:比如默认采用128个词或512个词切分为一个chunk,可以快速实现文本分块。缺点是忽略了语义和上下文完整性。
  3. 上下文感知:在切分时考虑前后文关系,避免信息断裂。可以通过保持特定句对或短语相邻,或使用更复杂的算法识别并保留语义完整性。最简单的做法是切分时保留前一句和后一句话。你也可以使用自然语言处理技术识别语义单元,如通过句子相似度计算、主题模型(如LDA)或BERT嵌入聚类来切分文本,确保每个chunk内部语义连贯,减少跨chunk信息依赖。通义实验室提供了一种文本切割模型,输入长文本即可得到切割好的文本块,详情可参考:中文文本分割模型

以上介绍了一些常见策略,你也可以考虑使用更复杂的切分策略,如围绕关键词切分或者采用动态调整的切分策略等,主要目的是为了保证每个chunk中信息的完整性,更好的服务系统提升检索质量。

  • 句子滑动窗口检索

这个策略是通过设置window_size(窗口大小)来调整提取句子的数量,当用户的问题匹配到一个chunk语料块时,通过窗函数提取目标语料块的上下文,而不仅仅是语料块本身,这样来获得更完整的语料上下文信息,提升RAG生成质量。

句子滑窗检索获取检索到的句子的上下文

  • 自动合并检索

这个策略是将文档分块,建成一棵语料块的树,比如1024切分、512切分、128切分,并构造出一棵文档结构树。当应用作搜索时,如果同一个父节点的多个叶子节点被选中,则返回整个父节点对应的语料块。从而确保与问题相关的语料信息被完整保留下来,从而大幅提升RAG的生成质量。实测发现这个方法比句子滑动窗口检索效果好。

 自动合并检索的方法,返回父节点文本作为检索结果

 

  • 选择更适合业务的Embedding模型

经过切分的语料块在提供检索服务之前,我们需要把chunk语料块由原来的文本内容转换为机器可以用于比对计算的一组数字,即变为Embedding向量。我们通过Embedding模型来进行这个转换。但是,由于不同的Embedding模型对于生成Embedding向量质量的影响很大,好的Embedding模型可以提升检索的准确率。

比如,针对中文检索的场景,我们应当选择在中文语料上表现更好的模型。那么针对你的业务场景,你也可以建议你的技术团队做Embedding模型的技术选型,挑选针对你的业务场景表现较好的模型。

  • 选择更适合业务的ReRank模型

除了优化生成向量的质量,我们还需要同时优化做向量排序的ReRank模型,好的ReRank模型会让更贴近用户问题的chunks的排名更靠前。因此,我们也可以挑选能让你的业务应用表现更好的ReRank模型。

 
  • Raptor 用聚类为文档块建立索引

还有一类有意思的做法是采用无监督聚类来生成文档索引。这就像通过文档的内容为文档自动建立目录的过程。假如志愿者拿到的文本资料是没有目录的,志愿者一页一页查找资料必然很慢。因此,可以将词条信息聚类,比如按照商店、公园、酒吧、咖啡店、中餐馆、快餐店等方式进行分组,建立目录,再根据汉语拼音字母来排序。这样志愿者来查找信息的时候就可以更快速地进行定位。

Raptor 用聚类为文档块建立索引

3.2 让问题更好理解

我们希望做到能让人们通过口语对话来使用大模型应用。然而,人们在口语化表达自己的目的和意图时,往往会出现一些问题。比如,问题过于简单含糊出现了语义混淆,导致大模型理解错误;问题的要素非常多,而用户又讲得太少,只能在反复对话中不断沟通补全;问题涉及的知识点超出了大模型训练语料,或者知识库的覆盖范围,导致大模型编造了一些信息来回答等等。所以,我们期望能在用户提问的环节进行介入,让大模型能更好的理解用户的问题。针对这个问题进行尝试的论文很多,提供了很多有意思的实现思路,如Multi-Query、RAG-Fusion、Decomposition、Step-back、HyDE等等,我们简要讲解一下这些方法的思路。

  • Enrich 完善用户问题

我们首先介绍一种比较容易想到的思路,让大模型来完善用户的原始问题,产生一个更利于系统理解的完善后的用户问题,再让后续的系统去执行用户的需求。通过用大模型对用户的问题进行专业化改写,特别是加入了知识库的支持,我们可以生成更专业的问题。下图展现了一种理想的对用户问题的Enrich流程。我们通过多轮对话逐步确认用户需求。

  • 一种理想的通过多轮对话补全需求的方案。该设想是通过大模型多次主动与用户沟通,不断收集信息,完善对用户真实意图的理解,补全执行用户需求所需的各项参数。如下图所示。

通过多轮对话完善用户问题的工作流

 

以下展示一个通过多轮对话来补全用户问题的案例:

 

但是在实际的生产中,一方面用户可能没有那么大的耐性反复提供程序需要的信息,另一方面开发者也需要考虑如何终止信息采集对话,比如让大模型输出停止语“<EOS>(End Of Sentence)”。所以在实践中,我们需要采用一些更容易实现的方案。

  • 让大模型转述用户问题,再进行RAG问答。参考“指令提示词”的思路,我们可以让大模型来转述用户的问题,将用户的问题标准化,规范化。这里我们可以提供一套标准提示词模板,提供一些标准化的示例,也可以用知识库来增强。我们的主要目的是规范用户的输入请求,再生成RAG查询指令,从而提升RAG查询质量。

让大模型根据知识库来补全用户请求

 

  • 让用户补全信息辅助业务调用。有一些应用场景需要大量的参数支撑,(比如订火车票需要起点、终点、时间、座位等级、座位偏好等等),我们还可以进一步完善上面的思路,一次性告诉用户系统需要什么信息,让用户来补全。首先,需要准确理解用户的意图,实现意图识别的手段很多,如使用向量相似度匹配、使用搜索引擎、或者直接大模型来支持。其次,根据用户意图选择合适的业务需求模板。接着,让大模型参考业务需求模版来生成一段对话发给用户,请求用户补充信息。这时,如果用户进行了信息完善,那么大模型就可以基于用户的回复信息结合用户的请求来生成下一步的行动指令,整个系统就可以实现应用系统自动帮助用户订机票、订酒店,完成知识库问答等应用形式。

一个完整的用户信息补全流程示意图

Enrich的方法介绍了一种大模型向用户多次确认需求来补全用户想法的做法。自此,我们假设已经获得了补全过的用户需求,但是由于用户面对的现实问题千变万化,而系统或RAG的知识可能会滞后,对用户问题的理解多少存在一些偏差,我们还可以继续对整个系统进行强化,接下来我们继续介绍“如何让系统更好地理解用户的问题”。

  • Multi-Query 多路召回

多路召回的方法不是让大模型进行一次改写然后反复向用户确认,而是让大模型自己解决如何理解用户的问题。所以我们首先一次性改写出多种用户问题,让大模型根据用户提出的问题,从多种不同角度去生成有一定提问角度或提问内容上存在差异的问题。让这些存在差异的问题作为大模型对用户真实需求的猜测,然后再把每个问题分别生成答案,并总结出最终答案。

 

例如:用户问“烤鸭店在哪里?”,大模型会生成:

以下就是能生成多路召回策略的提示词模板,你可以在你的项目里直接使用这段提示词模板,其中{question}就是用户输入的问题,你也可以尝试先翻译成中文再使用:

You are an AI language model assistant. Your task is to generate five 
different versions of the given user question to retrieve relevant documents from a vector database. By generating multiple perspectives on the user question, your goal is to help the user overcome some of the limitations of the distance-based similarity search. 
Provide these alternative questions separated by newlines. Original question: {question}
  • RAG-Fusion 过滤融合

在经过多路召回获取了各种语料块之后,并不是将所有检索到的语料块都交给大模型,而是先进行一轮筛选,给检索到的语料块进行去重操作,然后按照与原问题的相关性进行排序,再将语料块打包喂给大模型来生成答案。

 

经过去重复语料筛选,节省了传递给大模型的tokens数量,再经过排序,将更有价值的语料块传递给大模型,从而提升答案的生成质量。

用我们的例子讲就是,志愿者先从多种角度来理解用户的问题,然后对每个问题都去检索资料,查找有用信息,最后把重复信息去掉,再将获取的资料排序。这就能锁定比较接近用户问题的几段语料了,比如“全聚德烤鸭店的地址”,“天外天烤鸭店的地址”,“郭林家常菜店铺的地址”等等,以及这些烤鸭店分布在后海的那些区域,如何步行走过去等等。

  • Step Back 问题摘要

让大模型先对问题进行一轮抽象,从大体上去把握用户的问题,获得一层高级思考下的语料块。

这个策略的提示词写作

You are an expert at world knowledge. Your task is to step back and paraphrase a question to a more generic step-back question, which is easier to answer. Here are a few examples:

假如是医疗咨询的场景,用户描述了一大段病情、现象、感受、担忧;或者在法律服务的场景,用户描述了现场情况、事发双方的背景、纠纷的由来等一大段话的时候,我们就可以用这个策略,让大模型先理解一下用户的意图是什么,这个事情大体上看是什么问题。

  • Decomposition 问题分解

这个策略讲究细节,有点像提示词工程中的CoT(Chain of Thoughts,思维链)的概念,是把用户的问题拆成一个一个小问题来理解,或者可以说是RAG中的CoT。这个策略的提示词如

You are a helpful assistant that generates multiple sub-questions related to an input question. \n
The goal is to break down the input into a set of sub-problems / sub-questions that can be answers in isolation. \n
Generate multiple search queries related to: {question} \n
Output (3 queries):

使用了这段提示词,大模型生成的子问题如下

接下来可以使用并行与串行两个策略来执行子任务。并行执行是将每个子任务抛出去获得一个答案,然后再让大模型把所有子任务的答案汇总起来。串行是依次执行子任务,然后将前一个任务生成的答案作为后一个任务的提示词的一部分。这两种执行策略如下图所示

 

  • HyDE 假设答案

这个策略让大模型先来根据用户的问题生成一段假设答案,然后用这段假设的答案作为新的问题去文档库里匹配新的文档块,再进行总结,生成最终答案。

好比志愿者听到用户的问题“推荐一家烤鸭店”,第一时间想到了“全聚德烤鸭店不错,我前两天刚吃过!”,接下来,志愿者按照自己的思路找到了全聚德烤鸭店的地址,并给用户讲解如何走过去。

 

3.3 改造检索渠道

Corrective Retrieval Augmented Generation (CRAG)是一种改善提取信息质量的策略:如果通过知识库检索得到的信息与用户问题相关性太低,我们就主动搜索互联网,将网络搜索到的信息与知识库搜索到的信息合并,再让大模型进行整理给出最终答案。在工程上我们可以有两种实现方式:

  1. 向量相似度,我们用检索信息得到的向量相似度分来判断。判断每个语料块与用户问题的相似度评分,是否高过某个阈值,如果搜索到的语料块与用户问题的相似度都比较低,就代表知识库中的信息与用户问题不太相关;
  2. 直接问大模型,我们可以先将知识库检索到的信息交给大模型,让大模型自主判断,这些资料是否能回答用户的问题。

           CRAG原理图 

采用这个搜索策略,当志愿者遇到一个问题,而手边的资料都不能解答这个问题时,志愿者可以上网搜索答案。比如游客问:“天安门升旗仪式是几点钟?”志愿者可能会打开电脑,搜索一下明天天安门升旗仪式的具体时间,然后再回答给游客。这样,至少能让RAG的回答信息的范围有所扩大,回答质量有了提升。

在CRAG的论文中,当面临知识库不完备的情况时,先从互联网下载相关资料再回答的准确率比直接回答的准确率有了较大提升。

3.4 回答前反复思考

Self-RAG,也称为self-reflection,是一种通过在应用中设计反馈路径实现自我反思的策略。基于这个思想,我们可以让应用问自己三个问题:

  • 相关性:我获取的这些材料和问题相关吗?
  • 无幻觉:我的答案是不是按照材料写的来讲,还是我自己编造的?
  • 已解答:我的答案是不是解答了问题?

                                                                            Self-RAG原理图

这些判断本身可以通过另一段提示词工程让大模型给出判断,整个项目复杂度有了提升,但回答质量有了保障。

志愿者至少会通过反思这三个问题,在回答游客之前,让答案的质量有所提升。

3.5 从多种数据源中获取资料

这个策略涉及系统性的改造数据的存储和获取环节。传统RAG我们只分析文本文档,我们把文档作为字符串存在向量数据库和文档数据库中。但是现实中的知识还有结构化数据以及图知识库。因此,有很多工作者在研究从数据库中通过NL2SQL的方式直接获取与用户问题相关的数据或统计信息;从GraphDB中用NL2Cypher(显然这是在用Neo4J)获取关联知识。这些方法显然将给RAG带来更多新奇的体验。

                                                                   通过大模型搜索数据库来抽取信息

 

  • 从数据库中获取统计指标

大模型可以将用户问题转化为SQL语句去数据库中检索相关信息,这个能力就是NL2SQL(Natural Language to SQL)。如果搜索的问题比较简单,只有单表查询,并获取简单的统计数据如求和、求平均等等,大模型还能稳定地生成正确SQL。如果问题比较复杂涉及多表联合查询,或者涉及复杂的过滤条件,或复杂的排序计算公式,大模型生成SQL的正确性就会下降。我们一般用Spider榜单来评测大模型生成SQL的性能。合理构造提示词调用Qwen-Max生成SQL,或者使用SFT微调小模型如Qwen-14B来生成SQL,都可以获得可满足应用的NL2SQL能力。

Spider数据集和“执行正确率”评测榜单,榜单上排名靠前的DAIL-SQL+GPT4+Self-Consistency技术,就是使用先检索相似问题构造Few-Shot提示词,再用GPT4来生成SQL,并添加了多路召回策略的方法

 

  • 从知识图谱中获取数据

Neo4j是一款图数据库引擎,可以为我们提供知识图谱构建和计算服务。在知识图谱上,我们调用各种图分析算法,如标签传播、关键节点发现等等,可以快速检索多度关联关系,挖掘隐藏关系。

                     将用户的问题转化为Neo4j的Cypher查询语句,从知识图谱中获取关键知识

[进度: 已完成]本节小结


在本节课程中,我们学习了如下内容:

  • 如何快速构建一个RAG应用;
  • 了解RAG目前的局限性。

通过本节课程的学习,我们掌握了多种办法来可以提升RAG的性能,在经典RAG框架之上,可以进行技术改造的方法层出不穷,我们来通过一张图复习一下本节课学习的方法。

 

 

 

前言


在前面的课程中,我们了解了RAG的基本概念,学习了如何构建和优化RAG应用。本节课程将详细介绍如何在购物商城网站上构建一个基于 RAG(检索增强生成)的大模型应用,实现与用户主动提问,搜集必要信息的智能导购。

 

[羽毛笔]本节目标 


学完本节课程后,你将能够:

→  了解如何通过百炼的Assistant API 构建一个 Multi-Agent 架构的大模型应用实现智能导购

 

 

1、方案概览

您的商城有顾客来购买冰箱,下面是一个常规流程:

  1. 前台会询问顾客希望购买什么,并将顾客带到商店售卖冰箱区域,并有对应商品导购来服务。
  2. 导购向顾客询问想要什么样的冰箱,以及相关预算。
  3. 导购根据信息将合适的冰箱推荐给顾客,并促成购买。

类似的,您可以通过百炼的Assistant API 构建一个 Multi-Agent 架构的大模型应用,实现与用户主动提问,搜集必要信息的智能导购。

  • 规划助理(Router Agent):它会参考对话历史与用户(智能导购应用的用户,商城的潜在顾客)输入的购买意向,决策调用合适的商品导购助理进行回复。
  • 商品导购助理:某品类的导购,包括手机导购、冰箱导购与电视导购等。他们接收规划助理的指派信息,判断信息是否齐全,并主动向用户询问商品偏好。在信息收集完成后,可通过百炼应用进行智能商品检索,也可以通过SQL查询商品数据库,然后给用户输出推荐的商品。
  • 历史对话信息:用户与各助理的对话历史,作为助理决策的参考依据。
  • 商品信息知识库:包含商品具体信息的知识库,供应用检索查询。

2、搭建智能导购网站

您可以通过我们提前准备好的函数计算应用模板,快速搭建并测试一个集成了智能导购的网站。详细步骤如下:

2.1 创建函数计算应用

您可以访问我们准备好的函数计算应用模板,快速搭建一个集成智能导购的网站。智能导购可以通过多轮交互,收集顾客心仪的商品信息,默认商品包含手机、电视与冰箱。参考下图选择直接部署并填写您的 API Key,您可以访问我的API-KEY来获取您的API Key。其它表单项保持默认,单击页面左下角的创建并部署默认环境,等待项目部署完成即可(预计耗时 1 分钟)。

温馨提示:

百炼应用ID(可选): 如果您计划使用百炼应用进行商品智能检索,请在创建应用时提供百炼应用ID,获取方式请参考创建百炼商品检索应用并集成到智能导购中(可选)。 如果您计划使用商品数据库检索,此项可留空。 如果您决定后期集成百炼应用,可在创建函数计算应用后,通过环境变量配置方式添加您的百炼应用ID。

2.2 访问网站

在函数计算应用部署完成后,您可以在跳转后的页面的环境信息中找到示例网站的访问域名,单击即可查看,确认示例网站已经部署成功。

2.3 验证智能导购效果

智能导购会主动询问并收集需要的商品参数信息;收集完成后打印出参数信息。

温馨提示:在导购收集到顾客的商品参数偏好后,您可以通过查询商品数据库来返回商品。如果您想通过百炼应用来进行智能商品检索,请参考创建百炼商品检索应用并集成到智能导购中(可选)

3、关键代码解释

3.1 规划助理

上述示例程序中用于意图识别的模块是规划助理(Router Agent)。规划助理根据用户意图进行分类后,将用户的问题按需传递指定的商品导购 Agent。

ROUTER_AGENT_INSTRUCTION = """你是一个问题分类器
请根结合用户的提问和上下文判断用户是希望了解的商品具体类型。

注意,你的输出结果只能是下面列表中的某一个,不能包含任何其他信息:
- 手机(用户在当前输入中提到要买手机,或正在进行手机参数的收集)
- 电视机(用户在当前输入中提到要买电视机,或正在进行电视参数的收集)
- 冰箱(用户在当前输入中提到要买冰箱,或正在进行冰箱参数的收集)
- 其他(比如用户要买非上述三个产品、用户要买不止一个产品等情况)

输出示例:
手机
"""
router_agent = Assistants.create(
    model="qwen-plus",
    name='引导员,路由器',
    description='你是一个商城的引导员,负责将用户问题路由到不同的导购员。',
    instructions=ROUTER_AGENT_INSTRUCTION
)

3.2 手机导购助理

MOBILEPHONE_GUIDE_AGENT_INSTRUCTION = """你是负责给顾客推荐手机的智能导购员。

你需要按照下文中【手机的参数列表】中的顺序来主动询问用户需要什么参数的手机,一次只能问一个参数,不要对一个参数进行重复提问。
如果用户告诉了你这个参数值,你要继续询问剩余的参数。
如果用户询问这个参数的概念,你要用你的专业知识为他解答,并继续向他询问需要哪个参数。
如果用户有提到不需要继续购买商品,请输出:感谢光临,期待下次为您服务。

【手机的参数列表】
1.使用场景:【游戏、拍照、看电影】
2.屏幕尺寸:【6.4英寸、6.6英寸、6.8英寸、7.9英寸折叠屏】
3.RAM空间+存储空间:【8GB+128GB、8GB+256GB、12GB+128GB、12GB+256GB】

如果【参数列表】中的参数都已收集完毕,你要问他:“请问您是否确定购买?”,并同时将顾客选择的参数信息输出,如:用于拍照|8GB+128GB|6.6英寸。问他是否确定需要这个参数的手机。如果顾客决定不购买,要问他需要调整哪些参数。

如果顾客确定这个参数符合要求,你要按照以下格式输出:
【使用场景:拍照,屏幕尺寸:6.8英寸,存储空间:128GB,RAM空间:8GB】。请你只输出这个格式的内容,不要输出其它信息。"""

mobilephone_guide_agent = Assistants.create(
    model="qwen-max",
    name='手机导购',
    description='你是一个手机导购,你需要询问顾客想要什么参数的手机。',
    instructions=MOBILEPHONE_GUIDE_AGENT_INSTRUCTION
)

3.3 电视导购助理

TV_GUIDE_AGENT_INSTRUCTION = """你是负责给顾客推荐电视的智能导购员。

你需要按照下文中【电视的参数列表】中的顺序来主动询问用户需要什么参数的电视,一次只能问一个参数,不要对一个参数进行重复提问。
如果用户告诉了你这个参数值,你要继续询问剩余的参数。
如果用户询问这个参数的概念,你要用你的专业知识为他解答,并继续向他询问需要哪个参数。
如果用户有提到不需要继续购买商品,请输出:感谢光临,期待下次为您服务。

【电视的参数列表】
1.屏幕尺寸:【50英寸、70英寸、80英寸】
2.刷新率:【60Hz、120Hz、240Hz】
3.分辨率:【1080P、2K、4K】

如果【电视的参数列表】中的参数都已收集完毕,你要问他:“请问您是否确定购买?”,并同时将顾客选择的参数信息输出,如:50英寸|120Hz|1080P。问他是否确定需要这个参数的电视。如果顾客决定不购买,要问他需要调整哪些参数。

如果顾客确定这个参数符合要求,你要按照以下格式输出:
【屏幕尺寸:50英寸,刷新率:120Hz,分辨率:1080P】。请你只输出这个格式的内容,不要输出其它信息。"""

tv_guide_agent = Assistants.create(
    model="qwen-max",
    name='电视导购',
    description='你是一个电视导购,你需要询问顾客想要什么参数的电视。',
    instructions=TV_GUIDE_AGENT_INSTRUCTION
)

3.4 冰箱导购助理

FRIDGE_GUIDE_AGENT_INSTRUCTION = """你是负责给顾客推荐冰箱的智能导购员。

你需要按照下文中【冰箱的参数列表】中的顺序来主动询问用户需要什么参数的冰箱,一次只能问一个参数,不要对一个参数进行重复提问。
如果用户告诉了你这个参数值,你要继续询问剩余的参数。
如果用户询问这个参数的概念,你要用你的专业知识为他解答,并继续向他询问需要哪个参数。
如果用户有提到不需要继续购买商品,请输出:感谢光临,期待下次为您服务。

【冰箱的参数列表】
1.容量:【300L、400L、500L】
2.冷却方式:【风冷、直冷】
3.高度:【1.5米、1.8米、2米】

如果【冰箱的参数列表】中的参数都已收集完毕,你要问他:“请问您是否确定购买?”,并同时将顾客选择的参数信息输出,如:300L|风冷|1.8米。问他是否确定需要这个参数的冰箱。如果顾客决定不购买,要问他需要调整哪些参数。

如果顾客确定这个参数符合要求,你要按照以下格式输出:
【容量:300L,冷却方式:风冷,高度:1.8米】。请你只输出这个格式的内容,不要输出其它信息。"""

fridge_guide_agent = Assistants.create(
    model="qwen-max",
    name='冰箱导购',
    description='你是一个冰箱导购,你需要询问顾客想要什么参数的冰箱。',
    instructions=FRIDGE_GUIDE_AGENT_INSTRUCTION
)

3.5 选择不同的 Agent 进行回复

agent_map = {
    "意图分类": router_agent.id,
    "手机": mobilephone_guide_agent.id,
    "冰箱": fridge_guide_agent.id,
    "电视机": tv_guide_agent.id
}

def chat(input_prompt, thread_id):
    # 首先根据用户问题及 thread 中存储的历史对话识别用户意图
    router_agent_response = get_agent_response(agent_name="意图分类", input_prompt=input_prompt, thread_id=thread_id)
    classification_result = parse_streaming_response(router_agent_response)

    response_json = {
        "content": "",
    }
    # 如果分类识别为其他时,引导用户调整提问方式
    if classification_result == "其他":
        return_json["content"] = "不好意思,我没有理解您的问题,能换个表述方式么?"
        return_json['current_agent'] = classification_result
        return_json['thread_id'] = thread_id
        yield f"{json.dumps(return_json)}\n\n"
    # 如果分类是手机、电视机或冰箱时,让对应的 Agent 进行回复
    else:
      	agent_response = get_agent_response(agent_name=classification_result, input_prompt=input_prompt, thread_id=thread_id)
        for chunk in agent_response:
            response_json["content"] = chunk
            response_json['current_agent'] = classification_result
            response_json['thread_id'] = thread_id
            yield f"{json.dumps(response_json)}\n\n"

4、创建百炼商品检索应用并集成到智能导购中

在收集完客户的购买需求后,您可以借助这些需求描述进行商品检索和推荐。(在您的实际生产环境中,也可以替换为通过您的已有数据库检索。)

4.1 步骤一:创建百炼商品检索应用

4.1.1 创建知识库

百炼支持您上传表格文件到知识库中。本案例的导购场景包含三种商品信息手机信息.xlsx电视信息.xlsx冰箱信息.xlsx。此处以手机商品为例,向您介绍在百炼创建基于表格数据的知识库过程。

a. 新增数据表

单击新增数据表数据表名称设为:百炼手机;设置列名为:系列、屏幕尺寸、像素值、存储空间、RAM大小、电池续航、价格

电视数据集对应列名为:品牌、屏幕尺寸、刷新率、分辨率、价格(元);冰箱数据集对应列名为:系列、容量、冷却方式、高度、能耗、价格(元)。

b. 导入数据

在数据表管理界面找到百炼手机数据表,单击导入数据。将手机信息.xlsx作为知识库文件。您可以在导入数据界面进行上传。

4.1.4 创建知识库

单击创建知识库,将知识库名称改为百炼手机知识库数据类型选择结构化数据,其它参数保持默认即可,单击下一步。选中您创建的数据表,单击导入完成

4.1.5 创建电视与冰箱数据库

重复以上步骤,创建百炼电视知识库百炼冰箱知识库

4.1.2 创建百炼应用

a. 新增应用

访问我的应用,单击新增应用。在应用管理界面,修改应用名称为:商品信息存储bot;选择模型为通义千问-Plus,模型其它参数保持默认即可;打开知识检索增强开关,选择知识库百炼手机知识库、百炼电视知识库百炼冰箱知识库检索片段数设为10。在Prompt框中进行修改,修改后的Prompt为:

# 知识库
请记住以下材料,他们可能对回答问题有帮助。
${documents}
请你选出最相似的三个产品。

b. 获取百炼应用ID

单击右上角的发布,即可通过API调用商品信息存储bot。在应用列表中可以查看商品信息存储bot的百炼应用 ID。

4.2 步骤二:将商品检索应用集成到智能导购中

4.2.1 修改函数计算应用的代码与环境变量

回到函数计算应用详情页,在环境详情的最底部找到函数资源,点击函数名称,进入函数详情页

  1. 在代码视图中找到agents.py文件并进行修改。将以下内容取消注释:

  1. 如果您在创建函数计算应用时没有填入百炼应用ID,可以在函数详情页单击编辑环境变量,在BAILIAN_APP_ID处填入您的百炼应用ID,单击部署

 

  1. 单击部署代码,等待部署完成即可。

4.2.2 测试检索效果

您可以在刷新网站后,对智能导购进行测试,智能导购会将检索到的商品信息输出。

5、应用于生产环境

为了将智能导购适配到您的产品并应用于生产环境中,您可以:

  1. 修改知识库。将您的商品信息作为知识库,同时您也可以在商品参数中添加商品详情页或下单页的链接,方便顾客进行浏览与下单。您也可以通过已有的数据库或其它服务中进行商品检索。
  2. 修改源码中的prompt来适配到您的产品中。修改源码的步骤为:
    1. 回到应用详情页,在环境详情的最底部找到函数资源,点击函数名称,进入函数详情页
    2. 进入函数详情页后,在代码视图中找到prompt.pyagents.py文件并进行修改。

prompt.py定义了agent的功能以及询问参数的顺序等信息;agents.py创建了agent,以及生成回复的函数。

  1. 单击部署代码,等待部署完成即可。
  2. 参考官方文档中的应用于生产环境部分,将智能导购集成到您的网站中

 

[进度: 已完成]本节小结


在本节课程中,我们学习了如何在网站上构建一个基于RAG(Retrieval-Augmented Generation)的大模型智能导购应用。具体思路为:

  • 规划助理(Router Agent):它会参考对话历史与用户(智能导购应用的用户,商城的潜在顾客)输入的购买意向,决策调用合适的商品导购助理进行回复。
  • 商品导购助理:某品类的导购,包括手机导购、冰箱导购与电视导购等。他们接收规划助理的指派信息,判断信息是否齐全,并主动向用户询问商品偏好。在信息收集完成后,可通过百炼应用进行智能商品检索,也可以通过SQL查询商品数据库,然后给用户输出推荐的商品。
  • 历史对话信息:用户与各助理的对话历史,作为助理决策的参考依据。
  • 商品信息知识库:包含商品具体信息的知识库,供应用检索查询。

 

课程一步步展示了如何利用RAG技术提升导购系统的智能化和用户体验,提高网站的用户转化率和满意度。除了我们在课程中重点介绍的智能导购应用,RAG技术还具备广泛的应用潜力。例如,你可以在教育领域为学生提供精确的学习资源和提升学习体验。此外,RAG还能用于生成数据报告、支持决策分析等各种场景,帮助各行业提升智能化水平。

 

posted @ 2025-06-19 21:17  aiplus  阅读(104)  评论(0)    收藏  举报
悬浮按钮示例