主题
在 LlamaIndex 里,我们把“agent”定义为一种使用 LLM、记忆与工具来处理外部用户输入的具体系统。与之相对的是“agentic(智能体式)”一词,它通常指 agent 的上级概念,即任何在流程中引入了 LLM 决策的系统。
在 LlamaIndex 里创建一个 agent 只需几行代码:
import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI
# Define a simple calculator tool
def multiply(a: float, b: float) -> float:
"""Useful for multiplying two numbers."""
return a * b
# Create an agent workflow with our calculator tool
agent = FunctionAgent(
tools=[multiply],
llm=OpenAI(model="gpt-4o-mini"),
system_prompt="You are a helpful assistant that can multiply two numbers.",
)
async def main():
# Run the agent
response = await agent.run("What is 1234 * 4567?")
print(str(response))
# Run the agent
if __name__ == "__main__":
asyncio.run(main())1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
调用这个 agent 会启动一轮特定的动作循环:
Agent 取到最新消息加上聊天历史
工具的 schema 与聊天历史一起通过 API 发送出去
Agent 要么直接给出回答,要么返回一组工具调用
- 每个工具调用都会被执行
- 工具调用的结果被加入聊天历史
- 带着更新后的历史再次调用 Agent,它要么直接回答,要么选择继续调用
FunctionAgent 是一类利用 LLM 服务商的函数/工具调用能力来执行工具的 agent。其他类型的 agent,例如 ReActAgent 与 CodeActAgent,则采用不同的提示词策略来执行工具。
想了解 agent 及其能力的更多内容,可以查看agent 指南。
提示
有些模型可能不支持流式 LLM 输出。流式默认是开启的,如果遇到报错,你随时可以用 FunctionAgent(..., streaming=False) 把它关掉。
工具
工具可以只是简单的 Python 函数,也可以用 FunctionTool、QueryEngineTool 这类做进一步定制。LlamaIndex 还用所谓 Tool Specs 为常见 API 提供了成套的预定义工具。
关于配置工具,可阅读工具指南
记忆
构建 agent 时,记忆是核心组件。默认情况下,所有 LlamaIndex agent 都用 ChatMemoryBuffer 作为记忆。
要定制它,可以在 agent 之外先声明好再传进去:
from llama_index.core.memory import ChatMemoryBuffer
memory = ChatMemoryBuffer.from_defaults(token_limit=40000)
response = await agent.run(..., memory=memory)1
2
3
4
5
2
3
4
5
关于配置记忆的更多内容,见记忆指南
多模态 Agent
一些 LLM 支持多种模态,例如图像与文本。借助带内容块的聊天消息,我们可以把图像传给 agent 参与推理。
举个例子,假设你手上有这份演示文稿里某页幻灯片的截图。
你可以把这张图交给 agent 推理,会看到它读懂了图像并据此行动。
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.llms import ChatMessage, ImageBlock, TextBlock
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o-mini", api_key="sk-...")
def add(a: int, b: int) -> int:
"""Useful for adding two numbers together."""
return a + b
workflow = FunctionAgent(
tools=[add],
llm=llm,
)
msg = ChatMessage(
role="user",
blocks=[
TextBlock(text="Follow what the image says."),
ImageBlock(path="./screenshot.png"),
],
)
response = await workflow.run(msg)
print(str(response))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
多智能体系统
你可以把多个 agent 组成一个多智能体系统,其中每个 agent 都能把控制权交接给另一个 agent,从而在完成任务的过程中相互协调。
from llama_index.core.agent.workflow import AgentWorkflow
multi_agent = AgentWorkflow(agents=[FunctionAgent(...), FunctionAgent(...)])
resp = await agent.run("query")1
2
3
4
5
2
3
4
5
这只是构建多智能体系统的一种方式。继续了解多智能体系统。
手工构建 Agent
尽管 FunctionAgent、ReActAgent、CodeActAgent、AgentWorkflow 这些 agent 类已经封装掉了很多细节,但有时你还是想自己写更底层的 agent。
直接使用 LLM 对象,你就能快速实现一个基础的 agent 循环,同时对工具调用与错误处理保有完全控制。
from llama_index.core.llms import ChatMessage
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
def select_song(song_name: str) -> str:
"""Useful for selecting a song."""
return f"Song selected: {song_name}"
tools = [FunctionTool.from_defaults(select_song)]
tools_by_name = {t.metadata.name: t for t in [tool]}
# call llm with initial tools + chat history
chat_history = [ChatMessage(role="user", content="Pick a random song for me")]
resp = llm.chat_with_tools([tool], chat_history=chat_history)
# parse tool calls from response
tool_calls = llm.get_tool_calls_from_response(
resp, error_on_no_tool_call=False
)
# loop while there are still more tools to call
while tool_calls:
# add the LLM's response to the chat history
chat_history.append(resp.message)
# call every tool and add its result to chat_history
for tool_call in tool_calls:
tool_name = tool_call.tool_name
tool_kwargs = tool_call.tool_kwargs
print(f"Calling {tool_name} with {tool_kwargs}")
tool_output = tool(**tool_kwargs)
chat_history.append(
ChatMessage(
role="tool",
content=str(tool_output),
# most LLMs like OpenAI need to know the tool call id
additional_kwargs={"tool_call_id": tool_call.tool_id},
)
)
# check if the LLM can write a final response or calls more tools
resp = llm.chat_with_tools([tool], chat_history=chat_history)
tool_calls = llm.get_tool_calls_from_response(
resp, error_on_no_tool_call=False
)
# print the final response
print(resp.message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
示例 / 模块指南
更完整的示例与模块指南清单见模块指南页。