Agno实战自主式AI应用
在这篇教程中,我将展示如何在本地机器或专用云服务器上使用免费的LLM模型创建一个简单的聊天机器人。
我们将开发一个应用程序,回答关于《Gloomhaven》棋盘游戏规则的问题。这款游戏很有趣,但有时规则会让你头昏脑涨。
我们的智能助手将帮助我们解决游戏中的一些棘手情况,并提供相关规则书中的链接。
完整的示例代码可以在这个仓库中找到。
1、工具概述
有许多更简单的方法可以通过无代码或低代码框架实现这一点,但我们将会深入探讨底层概念和框架,并使用最少的高级工具。
我们将使用Agno,这是一个易于启动的自主框架。它的优点之一是对各种向量数据库的广泛支持,例如pgVector、Pinecone 和 LanceDB。
我们将让演示在完全本地的LLM上运行。与本地LLM相比,OpenAI 更容易使用。然而,OpenAI 就像电子烟:看起来无害,但长期来看它会让人上瘾且昂贵,并且你可能并不需要它。此外,OpenAI 收集所有你的数据以创造强大的超级智能来奴役人类。
2、什么是RAG?
RAG通过从外部来源检索相关信息增强模型,通常是向量数据库。它处理各种格式的文档集合,将其拆分为块。然后,它使用专门的模型——嵌入器——为每个块创建向量嵌入,这些嵌入存储在向量数据库中。
嵌入器是一种函数(神经网络),它将文本块转换为更方便的表示形式。例如,“一杯牛奶”可以是一个数字向量,如[0.23, 1.58, ..., 8.45]。类似的短语将以相似的向量表示。然后,这些向量及其相应文本块的位置被存储在向量数据库中。
当用户提出问题时,标准RAG为其创建一个嵌入,搜索数据库以查找几个最近的嵌入向量,并返回相应的文本块。例如,用户可以提供提示“喝”,RAG 将返回“一杯牛奶”和其他在我们的文档中引用的饮料。这是RAG管道中的“检索”部分。
之后,在将用户的原始查询传递给LLM之前,将其扩展以包括这些文本块作为附加信息,就像给LLM的一个提示,帮助其给出正确的答案而不会产生幻觉。这是RAG管道中的“增强”部分。
3、什么是自主式RAG?
另一方面,自主式RAG允许模型使用特殊工具以嵌入方式查询向量数据库。这样,模型可以决定是否需要访问相关信息以回答问题,使用哪些查询以及访问多少次。如果第一次查询不够充分,模型还可以查询更多额外的信息。
自主式RAG系统功能更强大,但预测性较差,调试起来更复杂,设置起来更具挑战性。对于像我们这样的简单应用,经典RAG更受欢迎。
4、开发环境
我在一台配备4070Ti的PC上测试了这个教程。如果你的机器足够快,可以直接跳到下一节。否则,你可能想租一台GPU机器用于开发。要这样做,请查看如何在neuralrack.ai上租用GPU机器。我已经使用这个服务测试了本文中的代码。
5、依赖项
首先,如果你还没有在之前的步骤中创建Python虚拟环境,我们需要先创建一个。
python3 -m venv venv
source venv/bin/activate
使用以下命令安装所需的依赖项。你也可以使用示例源代码中的requirements.txt文件。
pip install lancedb pylance tantivy agno ollama streamlit pypdf sqlalchemy
然后安装Ollama。Ollama 是一个易于使用的工具,用于在本地运行LLM模型。
curl -fsSL https://ollama.com/install.sh | sh
6、选择LLM
不同的模型适用于不同的应用。你可以在LLM排行榜网站ProLLM上找到比较结果。另一个重要的因素是模型的大小及其运行成本。
例如,如果你的计算资源有限,可以使用gemma3模型的1b或4b版本。对于RTX 4090(24GB内存),你可以使用27b版本。如果你有一台有两个或更多的RTX 4090机器,你可以运行llama3.3或deepseek-r1:70b。要运行Llama4,你需要至少一个H100。
嵌入模型是一个单独的模型,仅用于创建嵌入向量。它们通常小得多,所以我们使用Ollama提供的顶级表现模型之一,即mxbai-embed-large。
下载你想要使用的Ollama模型。一个是用于聊天客户端,另一个是用于嵌入。
ollama pull gemma3:27b
ollama pull mxbai-embed-large
7、简单的RAG代理
要使用Agno框架与RAG一起工作,我们必须首先创建一个包含所有文档的知识库。知识库包含我们将引用的Gloomhaven规则。创建知识库意味着将其转换为嵌入模型的向量表示,如前面几节所述。我们使用LanceDB因为它是一个简单的向量数据库,可以在本地使用。
from agno.embedder.ollama import OllamaEmbedder
from agno.models.ollama import Ollama
from agno.knowledge.pdf_url import PDFUrlKnowledgeBase
from agno.vectordb.lancedb import LanceDb, SearchType
embedder = OllamaEmbedder(id="mxbai-embed-large", dimensions=1024)
vector_db = LanceDb(
table_name="gloomhaven",
uri="/tmp/lancedb",
search_type=SearchType.hybrid,
embedder=embedder
)
knowledge_base = PDFUrlKnowledgeBase(
urls=["https://cdn.1j1ju.com/medias/8d/c5/21-gloomhaven-rulebook.pdf"],
vector_db=vector_db
)
加载知识库。你只需要做一次。脚本将在你的文件系统中创建一个本地数据库,因此你不需要每次运行时都执行以下操作:
knowledge_base.load(upsert=True)
让我们先使用传统的RAG。在创建Agno代理时,必须提供知识库并设置标志 add_context=True 来启用RAG。标志 add_history_to_messages=True 和 num_history_responses=10 允许该代理在同一会话中使用简单的、固定长度的内置聊天历史记录。
from agno.agent import Agent
agent = Agent(
model=Ollama(id="gemma3:27b", options={"num_ctx": 16192}),
# Enable RAG
knowledge=knowledge_base,
add_context=True,
# Add references to the original documents
add_references=True,
description="You are an expert in the rules of the board game gloomhaven.",
instructions=[
"Use additional data provided for the corresponding rules.",
"Cite the rules book with the corresponding information at the end of the answer to a question"
],
search_knowledge=False,
add_history_to_messages=True,
num_history_responses=10,
markdown=True,
# debug_mode=True,
)
使用 RAG 运行 ollama 模型时,必须指定上下文大小,我们通过向模型添加 options={“num_ctx”: 16192}
来实现。更大的上下文需要更多的 GPU 内存,因此请根据可用硬件调整上下文大小。
默认大小 2048 通常不足以满足 RAG 应用程序的需求。在将模型从 OpenAI 更改为本地 LLM 后,我在调试应用程序时花了不少时间才弄清楚这一点。
我们可以像这样测试代理。
prompt = "Summarize game rules in three sentences"
response = agent.run(prompt)
print(response.content)
运行此代码后我们将得到类似的结果:
如果我们想将其更改为 Agentic RAG,只需对代理进行一些小的更改。请记住,Agentic RAG 功能更强大,它使 LLM 能够灵活地多次查询数据库。然而,这也会使应用程序的可预测性降低。
from agno.agent import Agent
agent = Agent(
model=Ollama(id="gemma3:27b", options={"num_ctx": 16192}),
# Enable RAG
knowledge=get_knowledge_base(),
# Add references to the original documents
add_references=True,
description="You are an expert in the rules of the board game gloomhaven.",
instructions=[
"Use additional data provided for the corresponding rules.",
"Cite the rules book with the corresponding information at the end of the answer to a question"
],
# Add a tool to search the knowledge base which enables agentic RAG.
search_knowledge=True,
add_history_to_messages=True,
num_history_responses=10,
show_tool_calls=True,
markdown=True,
# debug_mode=True,
)
8、聊天机器人 UI
让我们创建一个简单的 Web 界面,让聊天机器人运行并回答我们的问题。
我们将使用 Streamlit(一个开源 Python 框架)来创建一个交互式 Web 应用。Gradio 是一个不错的选择。利用 Gradio 和 HuggingFace Spaces 是与好友分享应用的好方法。
Streamlit 框架的工作原理是每次我们与网页交互时都会重新运行脚本。这意味着保存不同运行之间可用的数据至关重要。
此脚本应与我们的模型 Python 文件放在一个单独的文件中;我们将其命名为 app.py。
首先,我们将知识库创建过程封装在一个函数中,并使用 @st.cache_resource 装饰器。这将确保该函数仅在脚本启动时运行一次,并且其结果将被缓存,并在同一会话的不同运行中甚至在其他会话(每个会话对应一个打开的 Web 应用选项卡)中重复使用。
import streamlit as st
from agno.agent import Agent
from agno.embedder.ollama import OllamaEmbedder
from agno.models.ollama import Ollama
from agno.knowledge.pdf_url import PDFUrlKnowledgeBase
from agno.vectordb.lancedb import LanceDb, SearchType
@st.cache_resource
def get_knowledge_base():
embedder = OllamaEmbedder(id="mxbai-embed-large", dimensions=1024)
vector_db = LanceDb(
table_name="gloomhaven",
uri="/tmp/lancedb",
search_type=SearchType.keyword,
embedder=embedder
)
knowledge_base = PDFUrlKnowledgeBase(
urls=["https://cdn.1j1ju.com/medias/8d/c5/21-gloomhaven-rulebook.pdf"],
vector_db=vector_db
)
# Load the knowledge base on the first run
knowledge_base.load(upsert=True)
return knowledge_base
现在,让我们创建一个生成器函数,每次返回一个文本标记。我们将用它来模拟聊天机器人响应中的打字机效果。
def stream_response(agent, prompt):
response = agent.run(prompt, stream=True)
for chunk in response:
yield chunk.content
Streamlit 有一个 st.session_state 字段,可用于存储整个会话的数据。让我们用消息历史记录和当前会话中要使用的代理来初始化它。
if 'messages' not in st.session_state:
st.session_state.messages = []
if 'agent' not in st.session_state:
st.session_state.agent = Agent(
model=Ollama(id="gemma3:27b", options={"num_ctx": 16192}),
knowledge=get_knowledge_base(),
add_context=True,
add_references=True,
description="You are an expert in the rules of the board game gloomhaven.",
instructions=[
"Use additional data provided for the corresponding rules.",
"Cite the rules book with the corresponding information at the end of the answer to a question"
],
search_knowledge=False,
add_history_to_messages=True,
num_history_responses=10,
show_tool_calls=True,
markdown=True,
debug_mode=True,
)
agent = st.session_state.agent
接下来,让我们为一个简单的聊天机器人创建 Web 界面。这里的主要组件是 st.chat_input(用户将使用它来输入问题)和 st.chat_message(用于显示上一个问题的答案以及机器人之前的聊天记录)。
st.title("Chat with the Gloomhaven expert")
prompt = st.chat_input("Your question")
if prompt:
st.session_state.messages.append({'role': 'user', 'text': prompt})
for message in st.session_state.messages:
with st.chat_message(message['role']):
st.write(message['text'])
with st.chat_message('assistant'):
response = st.write_stream(stream_response(agent, prompt))
st.session_state.messages.append({'role': 'assistant', 'text': response})
使用以下命令运行脚本:
streamlit run app.py
然后,转到链接查看聊天机器人界面:http://localhost:8501 — 如果在本地运行,http://:8501 — 如果在远程服务器上运行。
你可以在代理中使用 debug_mode=True 标志来启用调试模式。在这种情况下,您可以查看日志或正在运行的启用 RAG 的代理,查看从数据库中提取了哪些文本块,并检查它们与所提问题的对应程度。
9、结束语
本教程教我们如何使用 RAG 实现一个基本的 AI 代理,该代理可以使用本地 LLM 查询知识库。使用本地 LLM 比依赖现成的 OpenAI 端点更复杂,但它提供了更大的灵活性,可以节省计算成本,并允许您开发具有严格安全要求的应用程序。
我使用了 Agno 代理框架、mxbai-embed-large 嵌入、LanceDB 矢量数据库、Ollama LLM 运行器、Streamlit UI 框架和 NeuralRack GPU 租赁服务。
示例代码可在此处获取。
原文链接:How to Develop your First (Agentic) RAG Application?
汇智网翻译整理,转载请标明出处