为了账号安全,请及时绑定邮箱和手机立即绑定

基于Autogen框架的检索增强生成(RAG)详解

使用检索增强生成(RAG)框架,可以从数据库中提取与特定用户查询相关的文档,并用于丰富大型语言模型(LLM)的提示。这使得我们可以使用最新的和私人的数据来调用大模型,从而大大提高答案质量。

这是我的系列文章中的第三篇,旨在帮助增强LLM调用的RAG框架进行系统性探索。Autogen是一个独特的框架,非常重视定义和执行代理。RAG功能是相对新的一项特性,在项目源代码中的agentchat.contrib包中结构化。该包一直在不断改进,承诺结合RAG文档访问和代理,以实现新颖的应用场景。

这篇文章会教你所有开始使用Autogen框架入门所需的内容。从初始化向量数据库到加载文档,再到相似搜索,以及调用LLM,涵盖完整的RAG流程。

这篇文章用的是Python v3.11和autogen v1.0.16,代码示例在更新版本里也能运行,但可能需要稍微调整一下代码。

本文最初发表在我的博客上 admantium.com

AutoGen 和 ChromaDB:

有三种不同的方法可以将Autogen与ChromaDB配合起来:

  • 使用外部 chromadb 客户端连接到 ChromaDB 服务器,获取相关文档并手动添加到提示里
  • 使用内部 ChromaVectorDB 类创建一个内存存储,然后使用模板提示来注入相关文档
  • 使用 RetrieveAssistantAgentRetrieveUserProxyAgent 构建一个独立的流水线来,从给定的文件路径中消费文档,拆分文本内容,填充内存中的数据存储,并使其可供代理使用,并
  • 使用 RetrieveAssistantAgentRetrieveUserProxyAgent 并添加现有的向量数据库到其中

在这篇文章中,我们将研究之前文章中提到的Langchain和Haystack这两个框架中的选项4,以评估AutoGen RAG。

向量数据库的设置。

agentchat.contrib.vectordb.chromadb 包定义了可以用来访问已持久化数据库的 ChromaDB 对象。

    从autogen.agentchat.contrib.vectordb.chromadb导入ChromaVectorDB模块  

    # 初始化向量数据库chroma  
    chroma = ChromaVectorDB(path="./chroma_db_haystack")  
    print(chroma.get_collection("documents"))  
    # 名称为'documents', ID为UUID('571a3195-9aed-429c-87e3-d0832b5ecf07'), 元数据为None, 租户为'default_tenant', 数据库为'default_database'

客户端对象使用默认的ChromaDB嵌入模型all-MiniLM-L6-v2,它正是用来编码数据的那个模型。

相似性搜索

进行一次相似度搜索会接收一个查询,通过定义的嵌入函数将其转换为向量,然后检索最相关的文档内容。

chroma.retrieve_docs(["书中提到了哪些行星?"])  
# 获取的结果如下
# [[({  
# 'id': 'a2c1ee4a2d489e1596d2b0572e517ea929ac6cca7b7a5080c6ec7496f3918f23',  
# 'metadata': {  
#   'file_path': '../ebooks/battletech_decision_at_thunder_rift.txt',  
#   '页码': 1,  
#   '源ID': '5828aceb56fba19d8dc05ddcbd7b279cdd4b22d5025343cc1542004127ee3464'  
# },  
# '内容': 'hours, and Singh’s report would bring the Duke and ###'  
# })]]

搜索会从已存储的数据库中检索相关文档。

RAG 管道

在 Autogen 中,LLM 的调用通常通过定义一个代理和一个用户代理来实现,其中用户代理允许人工输入。由于输入的消息是由用户提供的,因此可以手动创建一个包含占位符的提示,并用手动执行查询得到的结果填充该占位符。

然而,正如前面提到的,Autogen 还提供特定的代理类型,这些代理能够自动访问配置的向量数据库来获取相关内容并填充内部提示——请参阅 Autogen 博客文章 使用 AutoGen 的检索增强生成(RAG)应用 以获取更多信息。

我花了一些时间才用 ChromaDB 客户端让其运行起来,还遇到了一些问题。总之,所需步骤如下:

  1. 确保持久化的ChromaDB在集合autogen-docs中包含文档
  2. 定义一个AutoGen ChromaVectorDB客户端
  3. 定义一个RetrieveAssistantAgentRetrieveUserProxyAgent(在retrieve_config对象中,将ChromaDB客户端作为vector_db传入,而不是client
  4. 启动LiteLLM以将Ollama LLM引擎包装成符合OpenAI API规范的接口
  5. 在用户对象上调用initiate_chat函数,并在context对象中确定应使用多少文档来提供答案(默认值为20,可能超出您的LLM上下文窗口)

如下是完整的代码:

    from autogen.agentchat.contrib.vectordb.chromadb import ChromaVectorDB  
    chroma = ChromaVectorDB(path="./chroma_db_haystack")  

    from autogen.agentchat.contrib.retrieve_assistant_agent import RetrieveAssistantAgent  
    from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent  
    config_list = [  
      {  
        "model": "llama3",  
        "base_url": "http://localhost:4000/",  
        "api_key": "ollama",  
      }  
    ]  
    SYSTEM_PROMPT = """  
    您是一位知识渊博的图书管理员,将回答您主管的问题。  
    限制:  
    - 分步骤思考。  
    - 准确且精确。  
    - 简要回答,用词简练。  
    - 反思您的答案,如果您认为您的答案不准确,重复这个答案。  
    """  
    系统消息 = {'role': 'system',  
          'content': SYSTEM_PROMPT}  
    agent = RetrieveAssistantAgent(  
      name="librarian",  
      system_message=SYSTEM_PROMPT,  
      human_input_mode="从不",  
      llm_config={  
        "config_list": config_list,  
        "timeout": 180,  
        "temperature": 0.2},  
    )  
    user = RetrieveUserProxyAgent(  
        name="user",  
        human_input_mode="从不",  
        max_consecutive_auto_reply=3,  
        retrieve_config={  
            "task": "问答",  
            "docs_path": None,  
            "vector_db": chroma,  
            "embedding_model": "all-MiniLM-L6-v2",  
            "get_or_create": False,  
        },  
        code_execution_config=False,  
    )  
    msg = "这本书中提到了哪些行星?"  
    user.initiate_chat(agent, message=user.message_generator, problem=msg, n_results= 3)
比如说

这是一个例子。

一个连接到LiteLLM封装器的Autogen代理,该封装器封装了一个Ollama LLaMA3模型,并通过分块的“Thunder Rift决策”电子书内容访问向量数据库,提供了如下非常详细的回答:

一个连接到LiteLLM封装器的Autogen代理,该封装器围绕Ollama LLaMA3模型,并能访问包含《Thunder Rift抉择》分块内容的向量数据库,给出了以下回复:

    Q: Singh是谁?  

    A: 看来你在读一本关于Grayson这个角色的小说或故事。Grayson正试图招募一些士兵来对抗Gayal山的海盗。他难以从英联邦获得支持,但他决心要成功。  
    小说还介绍了名叫Tor的角色,Tor被Singh关押。Singh试图从Tor那里获取关于一支可能正在训练当地人对抗海盗的雇佣兵部队的信息。
    请继续往下读!
    Q: 小说中提到了哪些星球?
    A: 看来你在读William H. Keith的《决战雷霆裂谷》(Decision at Thunder Rift),这是《机甲战纪》系列中的一本书。故事发生在一个名为Trellwan的星球上,那里有一个叛徒试图破坏监视站的监控和摄像头。主角Grayson是一名astech,正在修理设备时注意到一些可疑的行为,决定进一步调查,从而揭露了一个可能对星球产生重大影响的阴谋。
    故事似乎正向着雷霆裂谷的关键时刻发展,这可能是在书中非常关键的一刻。我不会剧透更多内容,但看起来Grayson和他的盟友即将面对一些严峻的挑战!  
    你觉得《机甲战纪》系列怎么样?
    Q: Grayson使用了哪款机甲?
    A: 看来我们有一段来自科幻小说或游戏的令人激动的段落,可能出自《机甲战纪》宇宙!
    故事似乎发生在一个凤凰鹰机甲与敌人的机甲之间的战斗中,主角Grayson正试图理清形势。场景非常紧张,到处都是激光射击和爆炸。  
    我们可以看到凤凰鹰机甲已经严重受损,失去了右臂和主炮,但仍继续战斗。飞行员Carlyle受了重伤,努力保持清醒状态。  
    同时,Riviera正在协调基地安全部队的反应,包括Xiang正带领一支巡逻队赶往现场。形势似乎非常危急,一个可能的敌人机甲,可能是Marauder型,正在基地内肆虐。
    这段描述以Grayson发现敌人机甲的徽标结束,这可能对于理解攻击的动机非常重要。
结尾

Autogen 是一个独特的框架,重点在于首先支持代理,其次是RAG功能。正如博客文章中所述,可以通过其 agentchat.contrib 包来添加RAG功能。本文展示了如何定义一个完整的RAG支持对话,包括加载预填充的ChromaDB实例和代理调用LLM。与之前测试的LangChain和Haystack框架相比,它提供了非常准确的答案,我认为这得益于相似度搜索和代理内部使用的提示。此外,Autogen特别有趣,因为它可以支持多个自主代理共同完成任务,当这些代理可以自由访问包含最新或私密信息的RAG数据库时,它还可以支持几种新的场景应用。这将在后续的文章中进一步探讨。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消