2026年7月9日 周四晚上19:30,报名腾讯会议了解“如何构建自进化的动态知识库(Brain)”(限30人)
免费POC, 零成本试错
FDE知识库

FDE知识库

学习大模型的前沿技术与行业落地应用


收藏

GraphRAG + AutoGen + Ollama + Chainlit = 本地和免费的多代理 RAG 超级机器人

发布日期:2024-08-03 20:57:25 浏览次数: 3913
作者:程序员二狗蛋

微信搜一搜,关注“程序员二狗蛋”


Rag (RAG) 是一种强大的工具,它使大型语言模型 (LLM) 能够访问真实世界的数据以获得更明智的响应。这是通过将模型与矢量数据库集成以实现实时学习和适应来实现的。此功能使 RAG 成为聊天机器人和虚拟助手等应用的首选,在这些应用中,对实时准确和明智的响应的需求很高。其中一种高级变体,称为图检索增强生成(GraphRAG),将基于图的知识检索与LLMs的优点相结合,进一步增强了自然语言处理的能力。与依赖于向量相似性搜索的传统 RAG 方法不同,GraphRAG 从原始文本构建结构化知识图谱,捕获实体、关系和关键声明。这可以增强 LLM 理解和综合复杂数据集及其关系的能力,从而产生更准确和基于上下文的响应。



AutoGen 是 Microsoft 的一款工具,它通过自动化和优化曾经复杂且需要大量手动工作的工作流程,简化了基于多代理 LLM 的复杂应用程序的开发。将 AutoGen 想象成一个平台,您可以在其中与多个 GPT 交互,而不仅仅是一个。每个 GPT 都充当单独的“代理”,在综合操作中发挥着独特的作用。将 GraphRAG 的检索优势与 AutoGen AI 代理的对话和面向任务的功能相结合,可以产生强大的 AI 助手,能够有效地处理详细的查询、生成和执行代码、创建多页科学报告以及进行数据分析。此外,离线本地 LLM,例如来自 Ollama 或 LM Studio 的 LLM,可确保经济高效且安全的数据处理。本地 LLM 消除了与在线 LLM 相关的高成本和隐私风险,将敏感数据保留在组织内并降低运营费用。

本文将指导您使用 GraphRAG 检索系统构建多代理 AI 应用程序,该系统完全在您的本地机器上运行,并且免费提供。以下是此应用程序的关键组件:

  1. GraphRAG的知识搜索方法通过函数调用与AutoGen代理集成。

  2. GraphRAG(本地和全局搜索)配置为支持来自Ollama的本地模型进行推理和嵌入。

  3. AutoGen 已扩展为支持通过 Lite-LLM 代理服务器从 Ollama 进行非 OpenAI LLM 的函数调用。

  4. Chainlit 用户界面,用于处理连续对话、多线程和用户输入设置。


凭借我的材料科学和计算建模背景,我想通过从 ABAQUS 文档、FEA 工程软件以及碳纤维和聚合物的一些技术数据表中构建知识图谱来测试此应用程序。考虑到该数据集的复杂性,使用本地 LLM 的整体准确性可能会更好。未来的文章将探讨从使用不同模型进行嵌入和推理的基准研究中学到的知识。尽管如此,我还是渴望从该领域的科学期刊和数据中构建更复杂的知识图谱,测试高级工程代码生成任务,并利用对话助手在我的专业知识范围内集思广益。该应用程序看起来像这样。



开发是在 Linux 环境中使用适用于 Linux 的 Windows 子系统 (WSL) 和 Visual Studio Code 在配备 i9 第 13 代处理器、64 GB RAM 和 24 GB Nvidia RTX 4090 的 Windows 11 PC 上完成的。为了获得开发和测试此应用的最佳体验,建议使用 Linux 发行版或 WSL。我尚未在本机 Windows 环境中对此进行测试。有关安装 WSL 以及设置 Python 和 Conda 环境的指南,请参阅本文(此处)。本文末尾提供了其他参考资料和相关信息。

这是源代码存储库的链接。现在,让我们开始吧!!

安装模型依赖项和克隆存储库。

从 Ollama 安装语言模型以进行推理和嵌入

# Mistral for GraphRAG Inference
ollama pull mistral

# Nomic-Embed-Text for GraphRAG Embedding
ollama pull nomic-embed-text

# LLama3 for Autogen Inference
ollama pull llama3

# Host Ollama on a local server: http://localhost:11434
ollama serve

创建 conda 环境并安装这些依赖项

# Create and activate a conda environment
conda create -n RAG_agents python=3.12
conda activate RAG_agents

# Lite-LLM proxy server for Ollama
pip install 'litellm[proxy]'

# Install Ollama
pip install ollama

# Microsoft AutoGen
pip install pyautogen "pyautogen[retrievechat]"

# Microsoft GraphRAG
pip install graphrag

# Text-Token Encoder-Decoder
pip install tiktoken

# Chainlit Python application
pip install chainlit

# Clone my Git-hub repository
git clone https://github.com/karthik-codex/autogen_graphRAG.git

# (BONUS) To Convert PDF files to Markdown for GraphRAG
pip install marker-pdf

# (BONUS) Only if you installed Marker-pdf since it removes GPU CUDA support by default
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

您将在我的 GitHub 存储库中找到以下文件。

  1. /requirements.txt— 包含上述所有软件包的列表

  2. /utils/settings.yaml— 包含使用 Ollama 的 Mistral 7B 和 Nomic-Text-Embedding 进行 GraphRAG 离线嵌入和索引的 LLM 配置。 您将使用此文件来替换首次在工作目录中初始化 GraphRAG 时创建的文件。

  3. /utils/chainlit_agents.py— 包含包括 AutoGen 的助手和用户代理代理的类定义。这允许跟踪多个代理,并在UI中显示其消息。(感谢 Chainlit 团队构建了 模板)。

  4. /utils/embedding.py包含修改后的嵌入函数,用于使用 Ollama 进行本地搜索查询的 GraphRAG 嵌入。您将使用此文件来替换 GraphRAG 包中的文件(更多信息见下文)

  5. utils/openai_embeddings_llm.py—C使用 Ollama 保留了修改后的嵌入函数,用于 GraphRAG 索引和嵌入。您将使用此文件来替换 GraphRAG 包中的文件(更多信息见下文)。

  6. /appUI.py包含主要的异步函数,用于设置代理、定义 GraphRAG 搜索函数、跟踪和处理消息,并在 Chainlit UI 中显示它们。

  7. /utils/pdf_to_markdown.py— 包含将 PDF 文件转换为 Markdown 文件以进行 GraphRAG 摄取的函数的奖励文件。

创建 GraphRAG 知识库。

在存储库的根文件夹中初始化 GraphRAG

#make a new folder "input" to place your input files for GraphRAG (.txt or .md)
mkdir -p ./input

# Initialize GraphRAG to create the required files and folders in the root dir
python -m graphrag.index --init--root .

# Move the settings.yaml file to replace the one created by GraphRAG --init
mv ./utils/settings.yaml ./

配置 GraphRAG 设置以支持 Ollama 的本地模型

下面是一个片段,展示了用于创建索引和嵌入的 LLM 的配置。GraphRAG 需要 32k 上下文长度进行索引,因此 Mistral 成为所选模型。对于嵌入,选择了 Nomic-embed-text,尽管您可以尝试使用 Ollama 中的其他嵌入。无需设置 ,因为不需要访问这些本地模型的端点。settings.yaml${GRAPHRAG_API_KEY}

encoding_model: cl100k_base
skip_workflows: []
llm:
api_key: ${GRAPHRAG_API_KEY}
type: openai_chat # or azure_openai_chat
model: mistral
model_supports_json: true
api_base: http://localhost:11434/v1
.
.
.
embeddings:
async_mode: threaded # or asyncio
llm:
api_key: ${GRAPHRAG_API_KEY}
type: openai_embedding # or azure_openai_embedding
model: nomic_embed_text
api_base: http://localhost:11434/api
.
.
.
input:#Change input file pattern to.md, or .txt
type: file # or blob
file_type: text # or csv
base_dir: "input"
file_encoding: utf-8
file_pattern: ".*\\.md$"

您可以在根目录的“input”文件夹中指定包含输入文件的文件夹。文本和 Markdown 文件都可以使用。您可以使用 将 PDF 转换为 markdown 文件,然后将其放置在“输入”文件夹中。处理多种文件格式尚未弄清楚,但这是一个可以解决的问题。/utils/pdf_to_markdown.py

在运行 GraphRAG 进行索引、创建嵌入和执行本地查询之前,您必须修改 Python 文件并位于 GraphRAG 包中。如果不进行此修改,GraphRAG 在创建嵌入时将抛出错误,因为它无法将“nomic-embed-text”识别为 Ollama 的有效嵌入模型。在我的设置中,这些文件位于 和openai_embeddings_llm.py embedding.py/home/karthik/miniconda3/envs/RAG_agents/lib/python3.12/site-packages/graphrag/llm/openai/openai_embeddings_llm.py/home/karthik/miniconda3/envs/RAG_agents/lib/python3.12/site-packages/graphrag/query/llm/oai/embedding.py

您可以使用命令找到这些文件。sudo find / -name openai_embeddings_llm.py

创建嵌入和知识图谱。

最后,我们创建嵌入并使用全局或局部搜索方法测试知识图谱。完成嵌入过程后,您可以在 GraphRAG 工作目录的“output”文件夹中找到输出工件(.parquet 文件)和报告(.json 和 .logs),该文件夹是本例中的根文件夹。

# Create knowledge graph - this takes some time
python -m graphrag.index --root .

# Test GraphRAG
python -m graphrag.query --root . --method global "<insert your query>"

启动 Lite-LLM 服务器并从终端运行应用程序

以下是在运行应用程序之前初始化服务器的命令。我选择了Llama3:8b来测试这个应用程序。如果硬件允许,可以使用更大的模型。有关Lite-LLM的更多信息,请访问此链接。现在,您已准备好从另一个终端运行应用程序。请确保您处于正确的 conda 环境中。

# start server from terminal
litellm --model ollama_chat/llama3

# run app from another terminal
chainlit run appUI.py

细分:appUI.py 的核心组成部分

导入 python 库

import autogen
from rich import print
import chainlit as cl
from typing_extensions import Annotated
from chainlit.input_widget import (
Select, Slider, Switch)
from autogen import AssistantAgent, UserProxyAgent
from utils.chainlit_agents import ChainlitUserProxyAgent, ChainlitAssistantAgent
from graphrag.query.cli import run_global_search, run_local_search

您会注意到正在从 chainlit_agents 导入两个类。这些用于 AutoGen 代理的包装类使 Chainlit 能够跟踪他们的对话并处理终止或其他用户输入。您可以在此处阅读有关此内容的更多信息。

配置 AutoGen 代理

AutoGen 代理通过 Lite-LLM 代理服务器利用 Ollama 的模型。这是必要的,因为 AutoGen 不支持通过非 OpenAI 推理模型调用函数。代理服务器允许使用 Ollama 模型进行函数调用和代码执行。

# LLama3 LLM from Lite-LLM Server for Agents #
llm_config_autogen = {
"seed": 40,# change the seed for different trials
"temperature": 0,
"config_list": [{"model": "litellm",
"base_url": "http://0.0.0.0:4000/",
'api_key': 'ollama'},
],
"timeout": 60000,
}

在聊天开始时实例化代理并输入用户设置

我创建了三个 Chainlit 小部件(开关、选择和滑块)作为用户设置,以选择 GraphRAG 搜索类型、社区级别和内容生成类型。启用后,开关小部件将使用 GraphRAG 本地搜索方法进行查询。内容生成的选择选项包括“优先级列表”、“单个段落”、“多个段落”和“多页报告”。滑块小组件使用选项 0、1 和 2 选择社区生成级别。您可以在此处阅读有关 GraphRAG 社区的更多信息。

@cl.on_chat_start
async def on_chat_start():
try:
settings = await cl.ChatSettings(
[
Switch(id="Search_type", label="(GraphRAG) Local Search", initial=True),
Select(
id="Gen_type",
label="(GraphRAG) Content Type",
values=["prioritized list", "single paragraph", "multiple paragraphs", "multiple-page report"],
initial_index=1,
),
Slider(
id="Community",
label="(GraphRAG) Community Level",
initial=0,
min=0,
max=2,
step=1,
),

]
).send()

response_type = settings["Gen_type"]
community = settings["Community"]
local_search = settings["Search_type"]

cl.user_session.set("Gen_type", response_type)
cl.user_session.set("Community", community)
cl.user_session.set("Search_type", local_search)

retriever = AssistantAgent(
name="Retriever",
llm_config=llm_config_autogen,
system_message="""Only execute the function query_graphRAG to look for context.
Output 'TERMINATE' when an answer has been provided."""
,
max_consecutive_auto_reply=1,
human_input_mode="NEVER",
description="Retriever Agent"
)

user_proxy = ChainlitUserProxyAgent(
name="User_Proxy",
human_input_mode="ALWAYS",
llm_config=llm_config_autogen,
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
code_execution_config=False,
system_message='''A human admin. Interact with the retriever to provide any context''',
description="User Proxy Agent"
)

print("Set agents.")

cl.user_session.set("Query Agent", user_proxy)
cl.user_session.set("Retriever", retriever)

msg = cl.Message(content=f"""Hello! What task would you like to get done today?
"""
,
author="User_Proxy")
await msg.send()

print("Message sent.")

except Exception as e:
print("Error: ", e)
pass

我选择不将 Chainlit 包装类用于检索器助理代理。这使我能够禁用对检索器输出的跟踪,并直接从 GraphRAG 函数捕获响应。原因是当响应通过检索器时,文本会丢失其格式,包括空格和段落缩进。在生成包含主标题和副标题的多页报告时,这个问题尤为明显。我可以通过绕过 Chainlit 包装器并直接从 GraphRAG 函数检索输出来保留原始格式。您将在下面看到我是如何实现这一目标的。

更新输入设置中的更改

此函数会检测设置中对选择、切换和滑块小部件所做的任何更改,以便它可以在后续查询中反映这些更改。

@cl.on_settings_update
async def setup_agent(settings):
response_type = settings["Gen_type"]
community = settings["Community"]
local_search = settings["Search_type"]
cl.user_session.set("Gen_type", response_type)
cl.user_session.set("Community", community)
cl.user_session.set("Search_type", local_search)
print("on_settings_update", settings)

使用来自代理和用户的传入消息更新 UI。

这是应用程序的核心部分,它创建一个带有两个代理的群聊,定义一个函数“state_transition”来管理对话序列,并提供异步 RAG 查询功能。

您会注意到根据 bool 参数传递到本地和全局搜索 GraphRAG 查询函数中的参数。设置为 — 如果您在不同的目录中初始化了 GraphRAG,请注意这一点。INPUT_DIR ,ROOT_DIR,RESPONSE_TYPE,COMMUNTIYLOCAL_SEARCHROOT_DIR,’.’

异步函数“query_graphRAG”调用 GraphRAG 全局或本地搜索方法。您会注意到函数内部的行,该行直接检索 RAG 查询的输出并保留检索内容的文本格式。await cl.Message(content=result.response).send()async def query_graphRAG

@cl.on_message
async def run_conversation(message: cl.Message):
print("Running conversation")
CONTEXT = message.content

MAX_ITER = 10
INPUT_DIR = None
ROOT_DIR = '.'
RESPONSE_TYPE = cl.user_session.get("Gen_type")
COMMUNITY = cl.user_session.get("Community")
LOCAL_SEARCH = cl.user_session.get("Search_type")

print("Setting groupchat")

retriever = cl.user_session.get("Retriever")
user_proxy= cl.user_session.get("Query Agent")

def state_transition(last_speaker, groupchat):
messages = groupchat.messages
if last_speaker is user_proxy:
return retriever
if last_speaker is retriever:
if messages[-1]["content"].lower() not in ['math_expert','physics_expert']:
return user_proxy
else:
if messages[-1]["content"].lower() == 'math_expert':
return user_proxy
else:
return user_proxy
else:
pass
return None

async def query_graphRAG(
question: Annotated[str, 'Query string containing information that you want from RAG search']
) -> str:
if LOCAL_SEARCH:
result = run_local_search(INPUT_DIR, ROOT_DIR, COMMUNITY ,RESPONSE_TYPE, question)
else:
result = run_global_search(INPUT_DIR, ROOT_DIR, COMMUNITY ,RESPONSE_TYPE, question)
await cl.Message(content=result).send()
return result

for caller in [retriever]:
d_retrieve_content = caller.register_for_llm(
description="retrieve content for code generation and question answering.", api_style="function"
)(query_graphRAG)

for agents in [user_proxy, retriever]:
agents.register_for_execution()(d_retrieve_content)

groupchat = autogen.GroupChat(
agents=[user_proxy, retriever],
messages=[],
max_round=MAX_ITER,
speaker_selection_method=state_transition,
allow_repeat_speaker=True,
)
manager = autogen.GroupChatManager(groupchat=groupchat,
llm_config=llm_config_autogen,
is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),
code_execution_config=False,
)

# -------------------- Conversation Logic. Edit to change your first message based on the Task you want to get done. ----------------------------- #
if len(groupchat.messages) == 0:
await cl.make_async(user_proxy.initiate_chat)( manager, message=CONTEXT, )
elif len(groupchat.messages) < MAX_ITER:
await cl.make_async(user_proxy.send)( manager, message=CONTEXT, )
elif len(groupchat.messages) == MAX_ITER:
await cl.make_async(user_proxy.send)( manager, message="exit", )

对于此应用程序,我们只需要两个代理。您可以添加/修改座席并配置“state_transition”功能,以编排对话中的发言者选择,以实现更复杂的工作流程。

最后的思考

这是我第一次涉足 AI 代理、LLM 和 RAG,在过去的几周里,我绕过了许多基础知识,直接投入到创建这个实现中。虽然这种实现并不完美,但它是开发更复杂应用程序的绝佳模板。它为集成多个功能和编码代理奠定了坚实的基础,应该使您能够构建复杂的工作流程、自定义代理交互并根据需要增强功能。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询

扫码登录
登录即表示您同意《53AI网站服务协议》
服务协议

欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。

在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。

一、 定义

本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。

会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。

知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。

二、 账号注册与登录

登录方式:本网站支持以下登录方式,您可根据实际情况选择:

微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。

手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。

账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。

实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。

未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。

三、 服务内容与规范

知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。

服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。

禁止行为:您在使用服务时不得实施以下行为:

利用技术手段批量爬取、下载、转存知识库内容;

将知识库内容用于商业目的或未经授权地向第三方传播;

干扰本网站正常运行或侵犯其他用户合法权益;

发布违法违规信息或从事违反公序良俗的活动。

四、 知识产权声明

权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。

有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。

侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。

五、 个人信息保护

我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。

您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。

您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。

六、 免责声明

内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。

不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。

第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。

七、 违约责任

如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。

如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。

八、 法律适用与争议解决

本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。

因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。

九、 其他

本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。

本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。

我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。


已查阅