RAG 是一种强大且极具潜力的工具,它通过将模型与矢量数据库集成,使LLMs能够实时获取和利用现实世界的数据,从而生成更明智、更精准的响应。这种能力为大型语言模型的实际应用打开了新大门,尤其是在需要实时学习和快速适应的场景中。
这一特性使 RAG 成为聊天机器人、虚拟助理等应用程序的首选解决方案,这些应用对实时准确且合乎逻辑的响应有着极高的需求。而 RAG 的高级形式——图检索增强生成(GraphRAG),更进一步扩展了其应用边界。GraphRAG 将基于图的知识检索与LLMs的强大生成能力相结合,进一步提升了自然语言处理的表现力。
与传统 RAG 方法主要依赖矢量相似性搜索不同,GraphRAG 从原始文本中构建结构化的知识图,精准捕捉实体、关系以及关键论断。这种结构化的知识表示赋予 LLMs 更强的能力,使其能够理解和综合复杂数据集中的信息及其内在关系,从而生成更准确、更贴合上下文的响应。
AutoGen 是微软推出的一款创新工具,旨在通过自动化和优化曾经复杂且需要大量手动操作的工作流程,简化基于多代理大型语言模型(LLMs)的复杂应用程序开发。可以将 AutoGen 想象为一个多功能平台,用户可以与多个 GPT 代理协作,而不仅仅是与单一模型交互。在 AutoGen 中,每个 GPT 都扮演着独特的“代理”角色,在综合运作中各司其职,共同实现更高效的任务完成。
当 GraphRAG 的检索能力与 AutoGen AI 代理的对话和任务导向功能相结合时,便可打造强大的 AI 助手。这些助手不仅能够处理复杂的查询,还能生成并执行代码、撰写多页科学报告,以及进行深入的数据分析,满足各类高难度需求。
值得一提的是,AutoGen 还支持集成本地 LLMs(例如来自 Ollama 或 LM Studio 的模型)。本地 LLMs 的应用为用户提供了经济高效且数据安全的选择。与在线 LLMs 相比,本地模型能够显著降低运行成本,同时消除潜在的隐私风险——敏感数据可以完全保留在组织内部,既保障了数据安全,也提升了运营效率。
通过 AutoGen 的灵活特性和 GraphRAG 的增强能力,用户能够轻松构建更智能、更可靠的 AI 解决方案,从而在多种场景中发挥巨大潜力。
本文将指导您使用 GraphRAG 检索系统构建一个多代理 AI 应用程序。该应用程序完全在您的本地计算机上运行,并且免费提供,确保经济高效和数据隐私。以下是构建该应用程序的关键组件:
-
GraphRAG 的知识搜索与 AutoGen 代理集成
GraphRAG 的知识搜索方法通过函数调用与 AutoGen 代理无缝集成,结合双方的优势实现高效检索与任务执行。 -
支持 Ollama 的本地模型
GraphRAG 配置了本地和全局搜索功能,支持 Ollama 提供的本地 LLMs,用于推理和嵌入生成。这种配置确保了对敏感数据的完全控制,同时降低了运行成本。 -
AutoGen 的扩展功能
AutoGen 通过 Lite-LLM 代理服务器实现了对 Ollama 提供的非 OpenAI LLMs 的函数调用支持。此扩展大幅提升了系统的灵活性,使用户可以充分利用本地模型的能力。 -
Chainlit 用户界面
应用程序配备了 Chainlit UI,用于处理连续对话、多线程操作以及用户输入设置,确保用户能够轻松管理复杂的任务流。
通过这些关键组件的协同工作,您可以构建一个功能强大的 AI 系统,适用于多种场景,从高效检索到复杂任务自动化,均可实现卓越性能。
一、安装 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
# 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
二、在存储库的根文件夹中初始化 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 ./
下面是来自settings.yaml的片段,说明了用于创建索引和嵌入的LLMs的配置。 GraphRAG 需要 32k 上下文长度进行索引,因此选择 Mistral 模型。对于嵌入,选择 Nomic-embed-text,尽管您可以尝试 Ollama 的其他嵌入。无需设置${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 文件都可以使用。您可以使用/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)。
# Create knowledge graph - this takes some time
python -m graphrag.index --root .
# Test GraphRAG
python -m graphrag.query --root . --method global "<insert your query>"
以下是在运行应用程序之前初始化服务器的命令。我选择 Llama3:8b 来测试这个应用程序。如果您的硬件允许,您可以使用更大的型号。有关 Lite- LLM的更多信息可以在此链接中找到。现在,您已准备好从另一个终端运行该应用程序。确保您处于正确的 conda 环境中。
# start server from terminal
litellm --model ollama_chat/llama3
# run app from another terminal
chainlit run appUI.py
Import python libraries 导入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 代理通过 Lite- LLM代理服务器利用 Ollama 的模型。这是必要的,因为 AutoGen 不支持通过非 OpenAI 推理模型调用函数。代理服务器允许使用 Ollama 模型进行函数调用和代码执行。
创建了三个 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)
这是应用程序的核心部分,它创建了两个代理的群聊,定义了一个函数“state_transition”来管理对话顺序,并提供异步 RAG 查询功能。
你会注意到INPUT_DIR ,ROOT_DIR, RESPONSE_TYPE, COMMUNTIY参数基于 bool 参数LOCAL_SEARCH传递到本地和全局搜索 GraphRAG 查询函数中。 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("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”函数来协调对话中的发言人选择,以实现更复杂的工作流程。
尽管这一实现尚不完美,但它为开发更复杂的应用程序提供了一个绝佳的起点。通过整合多个功能模块和编码代理,它为构建复杂的工作流程奠定了坚实基础。
同时,这种设计使您能够灵活地自定义代理交互,根据实际需求不断增强功能,为未来的创新和扩展提供了无限可能。
参考:https://ai.gopubby.com/microsofts-graphrag-autogen-ollama-chainlit-fully-local-free-multi-agent-rag-superbot-61ad3759f06f
三、如何系统学习掌握AI大模型?
AI大模型作为人工智能领域的重要技术突破,正成为推动各行各业创新和转型的关键力量。抓住AI大模型的风口,掌握AI大模型的知识和技能将变得越来越重要。
学习AI大模型是一个系统的过程,需要从基础开始,逐步深入到更高级的技术。
这里给大家精心整理了一份
全面的AI大模型学习资源
,包括:AI大模型全套学习路线图(从入门到实战)、精品AI大模型学习书籍手册、视频教程、实战学习、面试题等,资料免费分享
!
1. 成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。
2. 大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)
3. 大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。
4. 2024行业报告
行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。
5. 大模型项目实战
学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。
6. 大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。
全套的AI大模型学习资源已经整理打包,有需要的小伙伴可以
微信扫描下方CSDN官方认证二维码
,免费领取【保证100%免费
】