集成和关键组件的图形摘要
R检索增强生成 (RAG) 是一种功能强大的工具,它使大型语言模型 (LLM) 能够访问现实世界的数据,从而做出更明智的响应。这是通过将模型与矢量数据库集成以进行实时学习和适应来实现的。此功能使 RAG 成为聊天机器人和虚拟助手等应用程序的首选,这些应用程序对实时准确且合理的响应需求很高。这种技术的高级变体称为图形检索增强生成 (GraphRAG),它将基于图形的知识检索的优势与 LLM 相结合,进一步增强了自然语言处理的能力。与依赖矢量相似性搜索的传统 RAG 方法不同,GraphRAG 从原始文本构建结构化知识图谱,捕获实体、关系和关键声明。这可以增强 LLM 理解和综合复杂数据集及其关系的能力,从而产生更准确且基于上下文的响应。
摘自麻省理工学院 Markus Beuhler 的一篇论文(链接在此处)
AutoGen 是 Microsoft 推出的一款工具,它通过自动化和优化曾经非常复杂且需要大量人工的工作流程,简化了基于多代理 LLM 的复杂应用程序的开发。将 AutoGen 想象成一个可以与多个 GPT 交互的平台,而不仅仅是一个。每个 GPT 都充当单独的“代理”,在综合操作中发挥着独特的作用。将 GraphRAG 的检索优势与 AutoGen AI 代理的对话和面向任务的功能相结合,可以打造出强大的 AI 助手,能够高效处理详细查询、生成和执行代码、创建多页科学报告以及进行数据分析。此外,离线本地 LLM(例如 Ollama 或 LM Studio 的 LLM)可确保经济高效且安全的数据处理。本地 LLM 消除了与在线 LLM 相关的高成本和隐私风险,将敏感数据保留在组织内部并降低运营费用。
本文将指导您使用 GraphRAG 检索系统构建多智能体 AI 应用程序,该系统完全在本地机器上运行,并且免费使用。以下是此应用程序的关键组件:
-
GraphRAG 的知识搜索方法通过函数调用与 AutoGen 代理集成。
-
GraphRAG(本地和全局搜索)配置为支持来自 Ollama 的本地模型进行推理和嵌入。
-
AutoGen 已扩展,以支持通过 Lite-LLM 代理服务器从 Ollama 使用非 OpenAI LLM 进行函数调用。
-
Chainlit UI 用于处理连续对话、多线程和用户输入设置。
G鉴于我的材料科学和计算建模背景,我想通过从 ABAQUS(一种 FEA 工程软件)的文档以及一些碳纤维和聚合物的技术数据表构建知识图谱来测试此应用程序。考虑到此数据集的复杂性,使用本地 LLM 的整体准确性可能会更好。未来的文章将探索使用不同模型进行嵌入和推理的基准研究的经验。尽管如此,我还是渴望从该领域的科学期刊和数据中构建更复杂的知识图谱,测试高级工程代码生成任务,并利用对话助手集思广益,探讨我专业范围内的科学主题。应用程序如下所示。
带有示例查询的主应用程序 UI。最后两个有相同的查询,但第一个是全局搜索,而第二个是本地搜索。
小部件设置在本地和全局搜索之间切换,设置社区级别和代长度。
开发是在 Linux 环境中使用 Windows Subsystem for Linux (WSL) 和 Visual Studio Code 在 Windows 11 PC 上完成的,该 PC 配备 i9 第 13 代处理器、64 GB RAM 和 24 GB Nvidia RTX 4090。为了在开发和测试此应用程序时获得最佳体验,建议使用 Linux 发行版或 WSL。我尚未在原生 Windows 环境中对此进行测试。有关安装 WSL 和设置 Python 和 Conda 环境的指南,请参阅本文(此处)。本文末尾提供了其他参考资料和相关信息。
这是源代码存储库的链接。现在,让我们开始吧!
安装模型依赖项并克隆存储库。
安装来自 Ollama 的语言模型以进行推理和嵌入
\# Mistral 用于 GraphRAG 推理
ollama pull mistral
\# Nomic-Embed-Text 用于 GraphRAG 嵌入
ollama pull nomic-embed-text
\# LLama3 用于 Autogen 推理
ollama pull llama3
\# 在本地服务器上托管 Ollama:http://localhost:11434
ollama serve
创建 conda 环境并安装这些依赖项
\# 创建并激活 conda 环境
conda create -n RAG\_agents python=3.12
conda activate RAG\_agents
\# Ollama 的 Lite-LLM 代理服务器
pip install 'litellm\[proxy\]'
\# 安装 Ollama
pip install ollama
\# Microsoft AutoGen
pip install pyautogen "pyautogen\[retrievechat\]"
\# Microsoft GraphRAG
pip install graphrag
\# 文本令牌编码器-解码器
pip install tiktoken
\# Chainlit Python 应用程序
pip install chainlit
\# 克隆我的 Git-hub 存储库
git clone https://github.com/karthik-codex/autogen\_graphRAG.git
\# (奖励)将 PDF 文件转换为 GraphRAG 的 Markdown
pip install marker-pdf
\# (奖励)仅当您安装了 Marker-pdf 时,因为它默认会删除 GPU CUDA 支持
conda install pytorch torchvision torchaudio pytorch-cuda=12.1-c pytorch-c nvidia
您将在我的 GitHub 存储库中找到以下文件。
-
/requirements.txt
—包含上述所有软件包的列表 -
/utils/settings.yaml
—包含使用 Mistral 7B 和 Ollama 的 Nomic-Text-Embedding 进行 GraphRAG 离线嵌入和索引的 LLM 配置。 您将使用此文件替换首次在工作目录中初始化 GraphRAG 时创建的文件。 -
/utils/chainlit_agents.py
—包含包括 AutoGen 助手和用户代理的类定义。这允许跟踪多个代理并将其消息显示在 UI 中。(感谢 Chainlit 团队构建模板_)__。_ -
/utils/embedding.py
—包含使用 Ollama 进行本地搜索查询的 GraphRAG 嵌入修改后的嵌入函数。您将使用此文件替换 GraphRAG 包中的文件(更多信息见下文) -
utils/openai_embeddings_llm.py
—包含使用 Ollama 进行 GraphRAG 索引和嵌入的修改后的嵌入函数。您将使用此文件替换 GraphRAG 包中的文件(更多信息见下文)。 -
/appUI.py
—包含设置代理、定义 GraphRAG 搜索功能、跟踪和处理消息以及在 Chainlit UI 中显示它们的主要异步函数。 -
/utils/pdf_to_markdown.py
—奖励文件包含将 PDF 文件转换为 markdown 文件以供 GraphRAG 提取的功能。
创建 GraphRAG 知识库。
在存储库的根文件夹中初始化 GraphRAG
\# 创建一个新文件夹“input”来放置 GraphRAG 的输入文件(.txt 或 .md)
mkdir -p ./input
\# 初始化 GraphRAG 以在根目录中创建所需的文件和文件夹
python -m graphrag.index --init --root 。
\# 移动 settings.yaml 文件以替换由 GraphRAG 创建的文件 --init
mv ./utils/settings.yaml ./
配置 GraphRAG 设置以支持来自 Ollama 的本地模型
下面是一段settings.yaml
说明 LLM 创建索引和嵌入的配置的代码片段。GraphRAG 需要 32k 上下文长度才能进行索引,因此 Mistral 是所选模型。对于嵌入,选择了 Nomic-embed-text,但您可以尝试使用 Ollama 的其他嵌入。无需设置${GRAPHRAG_API_KEY}
,因为不需要访问这些本地模型的端点。
encoding\_model: cl100k\_base
skip\_workflows: \[\]
llm:
api\_key: $ {GRAPHRAG\_API\_KEY}
类型: openai\_chat \# 或 azure\_openai\_chat
模型: mistral
model\_supports\_json: true
api\_base: http://localhost:11434/v1
。。。嵌入:async\_mode:threaded \# 或 asyncio llm:api\_key:${GRAPHRAG\_API\_KEY}类型:openai\_embedding \# 或 azure\_openai\_embedding模型:nomic\_embed\_text api\_base:http://localhost:11434 / api 。。。输入:#将输入文件模式更改为.md 或 .txt类型:文件#或 blob文件类型:文本#或 csv base\_dir:“输入”文件编码:utf-8文件模式:“。\*\\\\.md$”
您可以在根目录中的“input”文件夹中指定包含输入文件的文件夹。文本和 markdown 文件都可以使用。您可以使用将/utils/pdf_to_markdown.py
PDF 转换为 markdown 文件,然后将其放在“input”文件夹中。处理多种文件格式的问题尚未解决,但这是一个可以解决的问题。
在运行 GraphRAG 进行索引、创建嵌入和执行本地查询之前,您必须修改 GraphRAG 包中的 Python 文件openai_embeddings_llm.py
和embedding.py
。如果没有进行此修改,GraphRAG 在创建嵌入时会抛出错误,因为它不会将“nomic-embed-text”识别为来自 Ollama 的有效嵌入模型。在我的设置中,这些文件位于/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),在本例中,该文件夹是根文件夹。
\# 创建知识图谱 - 这需要一些时间
python -m graphrag.index --root .
\# 测试 GraphRAG
python -m graphrag.query --root . --method global "<插入您的查询>"
启动 Lite-LLM 服务器并从终端运行应用程序
下面是在运行应用程序之前初始化服务器的命令。我选择了 Llama3:8b 来测试这个应用程序。如果硬件允许,您可以使用更大的模型。有关 Lite-LLM 的更多信息,请访问此链接。现在,您可以从另一个终端运行该应用程序。确保您处于正确的 conda 环境中。
\# 从终端启动服务器
litellm --model ollama\_chat/llama3
\# 从另一个终端运行应用程序
chainlit run appUI.py
细分:appUI.py 的核心组件
导入 Python 库
导入autogen
从rich导入 打印
导入chainlit作为cl
从typing\_extensions导入Annotated
从chainlit.input\_widget导入(
Select、Slider、Switch)
从autogen导入AssistantAgent、UserProxyAgent
从utils.chainlit\_agents导入ChainlitUserProxyAgent、ChainlitAssistantAgent
从graphrag.query.cli导入run\_global\_search、run\_local\_search
_您会注意到从chainlit_agents_导入了两个类。这些 AutoGen 代理的包装器类使 Chainlit 能够跟踪其对话并处理终止或其他用户输入。您可以在此处阅读更多相关信息。
配置 AutoGen 代理
AutoGen 代理通过 Lite-LLM 代理服务器利用来自 Ollama 的模型。这是必要的,因为 AutoGen 不支持通过非 OpenAI 推理模型进行函数调用。代理服务器允许使用 Ollama 模型进行函数调用和代码执行。
\# 来自 Lite-LLM 服务器的 LLama3 LLM,用于代理 #
llm\_config\_autogen = {
“seed” : 40 , \# 更改不同试验的种子
“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) 本地搜索" , initial= True ),
Select(
id = "Gen\_type" ,
label= "(GraphRAG) 内容类型" ,
values=\[ "优先列表" , "单段落" , "多段落" , "多页报告" \],
initial\_index= 1 ,
),
Slider(
id = "社区" ,
label= "(GraphRAG) 社区级别" ,
initial= 0 ,
min = 0 ,
max = 2 ,
step= 1 ,
),
\]
).send()
response\_type = settings\[ "Gen\_type" \]
community = settings\[ "社区" \]
local\_search = settings\[ "Search\_type" \]
cl.user\_session.设置(“Gen\_type”,response\_type)
cl.user\_session.设置(“Community”,community)
cl.user\_session.设置(“Search\_type”,local\_search)
retriever = AssistantAgent(
name= “Retriever”,
llm\_config=llm\_config\_autogen,
system\_message= “”“仅执行函数query\_graphRAG来查找上下文。
当提供答案时输出‘TERMINATE’。”“”,
max\_consecutive\_auto\_reply= 1,
human\_input\_mode= “NEVER”,
description= “Retriever Agent”
)
user\_proxy = ChainlitUserProxyAgent(
name= “User\_Proxy”,
human\_input\_mode= “始终”,
llm\_config=llm\_config\_autogen,
is\_termination\_msg=lambda x:x.get(“content”,“”)。rstrip()。endswith(“TERMINATE”),
code\_execution\_config = False,
system\_message = '''人类管理员。与检索器交互以提供任何上下文''',
description = “用户代理代理”
)
print(“设置代理。”)
cl.user\_session。设置(“查询代理”,user\_proxy)
cl.user\_session。设置(“检索器”,检索器)
msg = cl.Message(content = f“”“您好!您今天想完成什么任务?
“”“,
author = “User\_Proxy”)
await msg.send()
print(“消息已发送。”)
except Exception as e:
print(“错误:”,e)
通过
我选择不使用 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)打印( " on\_settings\_update" , settings)
使用来自代理和用户的传入消息更新 UI。
这是应用程序的核心部分,它创建了一个有两个代理的群聊,定义了一个函数“state_transition”来管理对话序列,并提供异步RAG查询功能。
您会注意到,INPUT_DIR ,ROOT_DIR,
RESPONSE_TYPE,
COMMUNTIY
基于 bool 参数传递到本地和全局搜索 GraphRAG 查询函数中的参数LOCAL_SEARCH
。ROOT_DIR,
设置为’.’
— 如果您在不同的目录中初始化了 GraphRAG,请注意这一点。
异步函数“query_graphRAG”调用 GraphRAG 全局或本地搜索方法。您会注意到函数await cl.Message(content=result.response).send()
内部的一行async def query_graphRAG
直接检索 RAG 查询的输出并保留检索到的内容的文本格式。
@cl.on\_message
async def run\_conversation ( message:cl.Message ):
print ( "正在运行对话" )
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 ( "设置群聊" )
trieser = cl.user\_session.get( "Retriever" )
user\_proxy = cl.user\_session.get( "查询代理" )
def state\_transition ( last\_speaker, groupchat ):
messages = groupchat.messages
如果last\_speaker是user\_proxy:
return trieser
如果last\_speaker是withdrawer:
如果messages\[- 1 \]\[ "content" \].lower()不在 \[ 'math\_expert' , 'physics\_expert' \]中: return user\_proxy else :如果messages\[- 1 \]\[ "content" \].lower() == 'math\_expert' : return user\_proxy else:返回user\_proxy else:传递返回None async def query\_graphRAG( question:Annotated \[ str,'包含您想要从 RAG 搜索中获取的信息的查询字符串' \])-> str:如果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)等待cl.Message(content = result)。send()返回\[retriever\]中的调用者的结果: d\_retrieve\_content = caller.register\_for\_llm( description = “检索代码生成和问答内容。”,api\_style= "函数" )(query\_graphRAG)
对于\[user\_proxy, triest\]中的代理:
agents.register\_for\_execution()(d\_retrieve\_content)
groupchat = autogen.GroupChat(
agent=\[user\_proxy, triest\],
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 ,
)
\# -------------------- 对话逻辑。根据您要完成的任务进行编辑以更改您的第一条消息。 ----------------------------------------- #
如果 len (groupchat.messages) == 0:
等待cl.make\_async(user\_proxy.initiate\_chat)( manager,message=CONTEXT,)
elif len (groupchat.messages) < MAX\_ITER:
等待cl.make\_async(user\_proxy.send)( manager,message=CONTEXT,)
elif len (groupchat.messages) == MAX\_ITER:
等待cl.make\_async(user\_proxy.send)( manager,message= “exit”,)
对于此应用程序,我们只需要两个代理。您可以添加/修改代理并配置“state_transition”函数来协调对话中的说话者选择,以实现更复杂的工作流程。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。