RAG 实现生成工作总结和工作任务查询功能

需求是,能根据上下文自动生成各部门的工作总结,并能根据上下文回答具体问题。

先看下实现效果,生成工作总结:

在这里插入图片描述

针对具体问题的回答:

在这里插入图片描述

实现的基本思路:

  • 使用 LlamaIndex
  • 创建 2 个检索器
    • 基于摘要索引(SummaryIndex)检索器,用于检索工作总结方面的问题
    • 基于向量索引 (VectorStoreIndex) 检索器,用于检索具体工作的具体问题
  • 通过 RouterQueryEngine 实现一个基于智能体的 RAG,由 RouterQueryEngine 通过 LLM 判断使用上述哪个检索器回答问题。

实现的笔记见 工作任务查询的实现原型笔记

下面介绍实现的步骤和使用中的设想和总结。

加载数据

数据来源于对每日个人工作任务日志的非结构化文档,在原型中简化为:

"开发部韩宇轩,simple-rag 产品,实现新特性:针对文档的摘要索引。通过摘要索引,为用户生成的总结性能有大幅度提升。经测试评估,准确率达到了95%,以前是45%。",
"开发部陈逸飞,simple-rag 产品,修正bug:中文断句不完整。之前断句不完整,造成嵌入相似度准确率不高。目前的做法是更换splitter实现,并且对分块参数做了优化。",
"开发部郑千,simple-rag 产品,修正bug:聊天界面 markdown 格式显示错误。bug的现象是部分字体显示不全,更换实现库,解决了这个问题。",
"产品部林晓琪,simple-rag 产品,提交新特性需求:多数据源的融合检索查询。用户反映以及我们测试,在某些功能下,大文档的检索召回率不高,造成回答效果不好。希望通过增加新的检索方法,并融合现在的检索结果,提高检索召回率。",
"产品部林晓琪,江南皮革厂客服助手项目,和客户开会,沟通需求。确定了客服助手的基本功能,并约定了下一次沟通时间和沟通内容。",
"运维部李泽言,江南皮革厂客服平台,系统扩容,解决了负载过高造成服务卡的问题。服务卡的主要原因是算力不足,原来是2张a100 40G,目前扩到了4张。今天业务高峰时间负载不到60%,问题解决。",
"销售部韩雪薇,天津化工集团后勤服务平台,准备标书商务部分,完成公司资质方面的文案。资质文案主要包括: 相关软件著作权证书、银行资质证明、国安资质证书和验资报告等,已经整理成word文件。",
"法务部张峻宁,完成审核了与深圳做大事公司的商务合同。之前对方提出了多个版权方面的条款,经过沟通,以及有关方面的查询,修改了相关条款,消除了商业风险,和客户达成了共识。目前已经提交给办公室。",

实际数据可能还需要编写自定义的解析器,增加元数据(比如,所属部门、姓名、日志日期和所属项目等)。

数据在后续索引使用前,需要再切分为文本块。这里简化了,直接手动生成文本块(Node):

nodes=[ TextNode(text=item, id_=f"node_{index}") for index, item in enumerate(items)]

创建和使用摘要索引

摘要索引用于创建总结或者摘要形式的问答,比如 郑千完成了哪些工作? 等。

创建摘要索引

summary_index = SummaryIndex(nodes)

摘要索引在使用时,通过 LLM 逐条文本块生成摘要,因此可以最大程度的保留原始语义,并能大幅减少文本长度,实现总结和摘要的作用。

这种索引的特点是,创建过程很快,因为啥也不做,但是检索时很慢,因为要逐条文本块使用 LLM 生成摘要。

选取合适的 LLM

因此这里需要设置 LLM 供后面使用:

Settings.llm=OpenAILike(
    model="qwen2",
...

测试了多个 LLM,云端 LLM 比较稳定正确的有:

  • gpt-3.5-turbo/gpt-4-turbo
  • qwen-turbo 及更高级版本
  • glm-3-turbo/glm-4/glm-4-air
  • Baichuan3-Turbo (但是Baichuan4有问题)
  • ERNIE-4.0-8K(之前的版本都不行,生成内容时报错)
  • hunyuan-pro (standard/lite 不行)

本地 LLM 测试的情况:

  • glm4:8b, 基本可用,明显好于 qwen2:7b, 但也不是很稳定,有时候生成的内容有遗漏
  • qwen2:7b, 不可用,路由时经常解析错
  • qwen2:72b, 不可用,路由时经常解析错
  • llama3.1:8b,不可用,工作摘要混杂了举例部分文字
  • yi:9b,不可用,工作摘要混杂了举例部分文字
  • yi-34b-chat, 能运行,有问题,一个任务描述摘要会拆分成好几个条目
  • deepseek-v2:16b, 不可用,摘要遗漏内容并混杂示例内容

因为生产环境要求本地模型,为了解决 markdown 格式生成摘要遗漏问题和正确路由问题,做了如下处理:

  • LLMSingleSelector 单独指定 glm4 模型,确保路由正常
  • 文本生成使用 qwen2:72b, 为了解决 markdown 格式摘要偶尔遗漏内容问题:
    • 提示词改为基于 json 格式,未出现遗漏内容情况
    • 程序解决 json 格式的输出展示

创建查询引擎

创建:

summary_retriever=summary_index.as_retriever()

response_synthesizer = get_response_synthesizer(
    response_mode="tree_summarize",
    streaming=True,
)

summary_query_engine = RetrieverQueryEngine(
    retriever=summary_retriever,
    response_synthesizer=response_synthesizer,
)

生成工作总结:

response = summary_query_engine.query(
    "给出涉及的所有部门所有人的任务摘要输出,输出示例如下:"
    """
    产品部:

    - 张三
        - xxx产品,提交新特性需求: xxx
        - xxx项目,和客户开会,xxxxx
        - ...
    - 李四
        - xxxx
        - ...
    - 王五
      - ...

    开发部:
    
    - 赵六
      - xxx产品,修正bug:xxxx
      - xxx项目,实现新特性:xxxx
      ...
    - 于七
      - xxx产品,修正bug:xxxx
      - xxx项目,实现新特性:xxxx
      ...
    ...

    xxx部:
    ...
    """
)

response.print_response_stream()

运行:

在这里插入图片描述

也可以生成指定人员的工作总结:

response = summary_query_engine.query("林晓琪完成哪些任务,列表说明")

# 林晓琪完成了以下任务:
# - 提交了simple-rag产品的多数据源融合检索查询的新特性需求,旨在提高大文档的检索召回率,以# 改善回答效果。
# - 参与了江南皮革厂客服助手项目的客户需求沟通会议,确认了客服助手的基本功能,并安排了下次会议的时间和内容。

创建和使用向量索引

创建向量索引

向量索引需要使用嵌入模型:

Settings.embed_model = OllamaEmbedding(
    model_name="quentinz/bge-large-zh-v1.5",
    ...

使用相同的文本节点列表创建向量索引(这一步需要耗时不到2秒,因为要将节点文本向量化,用于后面的向量检索):

vector_index = VectorStoreIndex(nodes)

创建向量检索器

向量查询的第一步是检索,默认是 top_k=2, 即从向量索引中选取相似度最大的2个节点:

vector_retriever=vector_index.as_retriever()

可以测试效果:

vector_retriever.retrieve("为什么要做多数据源的融合检索查询?是谁提出的?")

输出检索到的结果:

[NodeWithScore(node=TextNode(id_=‘node_2’, embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text=‘产品部林晓琪,simple-rag 产品,提交新特性需求:多数据源的融合检索查询。用户反映以及我们测试,在某些功能下,大文档的检索召回率不高,造成回答效果不好。希望通过增加新的检索方法,并融合现在的检索结果,提高检索召回率。’, mimetype=‘text/plain’, start_char_idx=None, end_char_idx=None, text_template=‘{metadata_str}\n\n{content}’, metadata_template=‘{key}: {value}’, metadata_seperator=‘\n’), score=0.5919122817844211), NodeWithScore(node=TextNode(id_=‘node_0’, embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text=‘开发部韩宇轩,simple-rag 产品,实现新特性:针对文档的摘要索引。通过摘要索引,为用户生成的总结性能有大幅度提升。经测试评估,准确率达到了95%,以前是45%。’, mimetype=‘text/plain’, start_char_idx=None, end_char_idx=None, text_template=‘{metadata_str}\n\n{content}’, metadata_template=‘{key}: {value}’, metadata_seperator=‘\n’), score=0.3938835184407688)]

创建查询器并执行查询:

response_synthesizer = get_response_synthesizer(
    response_mode="tree_summarize",
    streaming=True,
)

vector_query_engine = RetrieverQueryEngine(
    retriever=vector_retriever,
    response_synthesizer=response_synthesizer,
)

response = vector_query_engine.query("为什么要做多数据源的融合检索查询?是谁提出的")
response.print_response_stream()

# 做多数据源的融合检索查询是为了提高大文档的检索召回率,从而改善回答效果。这个需求是由产品部的林晓琪提出的。

路由查询引擎合

路由查询引擎,封装和使用了 LLM 智能体(Agent)功能,让 LLM 根据提示词决定具体使用哪个查询器生成回答。

创建查询工具

将之前的摘要查询引擎和向量查询引擎分别分装为工具(Tool),设置提示词:

summary_tool = QueryEngineTool.from_defaults(
    query_engine=summary_query_engine,
    description=(
        "对工作任务总结方面的问题很有用。"
    ),
)

vector_tool = QueryEngineTool.from_defaults(
    query_engine=vector_query_engine,
    description=(
        "适用于回答工作任务相关的具体问题。"
    ),
)

创建路由查询器

路由查询器支持单选和多选路由,这里使用单选 LLMSingleSelector.

summarizer = TreeSummarize(streaming=True, use_async=False)

query_engine = RouterQueryEngine(
    selector=LLMSingleSelector.from_defaults(
        llm=OpenAILike(
            model="glm4",
            ...
        )
    ),
    query_engine_tools=[
        summary_tool,
        vector_tool,
    ],
    summarizer=summarizer
)

使用路由查询器查询

总结性的问题,路由将根据提示词识别并使用摘要索引查询:

response = query_engine.query(
    "给出涉及的所有部门所有人的任务摘要输出,输出示例如下:"
    """
    产品部:

    - 张三
        - xxx产品,提交新特性需求: xxx
        - xxx项目,和客户开会,xxxxx
        - ...
    - 李四
        - xxxx
        - ...
    - 王五
      - ...

    开发部:
    
    - 赵六
      - xxx产品,修正bug:xxxx
      - xxx项目,实现新特性:xxxx
      ...
    - 于七
      - xxx产品,修正bug:xxxx
      - xxx项目,实现新特性:xxxx
      ...
    ...

    xxx部:
    ...
    """
)

response.print_response_stream()

有时需要通过提示词明确要求总结,否则会有不稳定情况:

response = query_engine.query(
    "列表简要回答,林晓琪做了哪些工作任务"
    "这是总结性质的问题"
)

response.print_response_stream()

具体问题, 路由将调用向量索引查询器回答问题:

response = query_engine.query("为什么要做多数据源的融合检索查询?是谁提出的")

response.print_response_stream()

总结

  • 本文介绍了使用 LlamaIndexRouterQueryEngine 根据提示词切换使用不同的索引查询器回答问题的方法步骤
  • 为演示基本过程,简化了生产环境下的细节处理,包括
    • 为了保持生成内容不遗漏内容,生产系统使用的是json格式输出
    • 复杂的提示词对用户不友好,总结任务是通过标签和按钮生成提示词的
    • 数据加载实际上复杂的多,需要单独编写解析器
  • 本文的结论是,使用本地模型是可以稳定实现一般的工作日志场景的 RAG 需求的
    • 需要针对具体环境和需求测试选型 LLM
    • 一般模型越大,执行越稳定
    • 随着开源 LLM 的快速迭代发展,小尺寸模型会趋于符合要求

那么,如何系统的去学习大模型LLM?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

所有资料 ⚡️ ,朋友们如果有需要全套 《LLM大模型入门+进阶学习资源包》,扫码获取~

篇幅有限,部分资料如下:

👉LLM大模型学习指南+路线汇总👈

💥大模型入门要点,扫盲必看!
在这里插入图片描述
💥既然要系统的学习大模型,那么学习路线是必不可少的,这份路线能帮助你快速梳理知识,形成自己的体系。
在这里插入图片描述

👉大模型入门实战训练👈

💥光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

👉国内企业大模型落地应用案例👈

💥《中国大模型落地应用案例集》 收录了52个优秀的大模型落地应用案例,这些案例覆盖了金融、医疗、教育、交通、制造等众多领域,无论是对于大模型技术的研究者,还是对于希望了解大模型技术在实际业务中如何应用的业内人士,都具有很高的参考价值。 (文末领取)
在这里插入图片描述
💥《2024大模型行业应用十大典范案例集》 汇集了文化、医药、IT、钢铁、航空、企业服务等行业在大模型应用领域的典范案例。

在这里插入图片描述

👉LLM大模型学习视频👈

💥观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 (文末领取)
在这里插入图片描述

👉640份大模型行业报告👈

💥包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
在这里插入图片描述

👉获取方式:

这份完整版的大模型 LLM 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

😝有需要的小伙伴,可以Vx扫描下方二维码免费领取🆓

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值