
本案例展示了如何使用LlamaIndex构建一个基于Anthropic函数调用能力的智能代理。该代理能够使用预定义的工具执行特定任务并通过函数调用机制与外部系统交互。1. 案例目标本案例的主要目标是演示如何使用LlamaIndex和Anthropic API构建一个具有函数调用能力的智能代理。具体来说我们将创建一个基于Anthropic的FunctionAgent定义简单的计算工具加法和乘法演示代理如何使用工具执行数学计算展示如何管理代理的上下文和记忆构建一个基于RAG的代理用于查询文档内容2. 技术栈与核心依赖LlamaIndex- 用于构建智能代理和工作流Anthropic API- 提供Claude语言模型和函数调用功能OpenAI API- 提供文本嵌入模型FunctionAgent- 用于构建具有函数调用能力的代理VectorStoreIndex- 用于构建RAG系统QueryEngineTool- 用于将查询引擎封装为工具核心依赖包%pip install llama-index %pip install llama-index-llms-anthropic %pip install llama-index-embeddings-openai3. 环境配置首先需要设置Anthropic API密钥from llama_index.llms.anthropic import Anthropic llm Anthropic(modelclaude-3-opus-20240229, api_keysk-...)对于RAG部分还需要设置OpenAI API密钥from llama_index.embeddings.openai import OpenAIEmbedding embed_model OpenAIEmbedding( model_nametext-embedding-3-large, api_keysk-proj-... ) query_llm Anthropic(modelclaude-3-haiku-20240307, api_keysk-...)4. 案例实现4.1 工具定义定义简单的计算工具def multiply(a: int, b: int) - int: Multiple two integers and returns the result integer return a * b def add(a: int, b: int) - int: Add two integers and returns the result integer return a b4.2 初始化Anthropic代理使用定义好的工具创建FunctionAgentfrom llama_index.core.agent.workflow import FunctionAgent agent FunctionAgent( tools[multiply, add], llmllm, )4.3 代理交互创建一个函数来运行代理并显示详细的工具调用信息from llama_index.core.agent.workflow import ToolCallResult async def run_agent_verbose(query: str): handler agent.run(query) async for event in handler.stream_events(): if isinstance(event, ToolCallResult): print( fCalled tool {event.tool_name} with args {event.tool_kwargs}\nGot result: {event.tool_output} ) return await handler4.4 执行数学计算使用代理执行数学计算response await run_agent_verbose(What is (121 2) * 5?) print(str(response))输出示例Called tool add with args {a: 121, b: 2} Got result: 123 Called tool multiply with args {a: 123, b: 5} Got result: 615 Therefore, (121 2) * 5 6154.5 管理上下文/记忆默认情况下.run()是无状态的。如果要维护状态可以传入一个context对象from llama_index.core.workflow import Context ctx Context(agent) response await agent.run(My name is John Doe, ctxctx) response await agent.run(What is my name?, ctxctx) print(str(response))4.6 构建基于RAG的代理4.6.1 准备数据!mkdir -p data/10k/ !wget https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/10k/uber_2021.pdf -O data/10k/uber_2021.pdf4.6.2 构建查询引擎from llama_index.core.tools import QueryEngineTool from llama_index.core import SimpleDirectoryReader, VectorStoreIndex # 加载数据 uber_docs SimpleDirectoryReader( input_files[./data/10k/uber_2021.pdf] ).load_data() # 构建索引 uber_index VectorStoreIndex.from_documents( uber_docs, embed_modelembed_model ) uber_engine uber_index.as_query_engine(similarity_top_k3, llmquery_llm) query_engine_tool QueryEngineTool.from_defaults( query_engineuber_engine, nameuber_10k, description( Provides information about Uber financials for year 2021. Use a detailed plain text question as input to the tool. ), )4.6.3 创建基于RAG的代理from llama_index.core.agent.workflow import FunctionAgent agent FunctionAgent(tools[query_engine_tool], llmllm, verboseTrue)4.6.4 查询文档内容response await agent.run( Tell me both the risk factors and tailwinds for Uber? ) print(str(response))5. 案例效果5.1 数学计算能力代理成功使用定义的加法和乘法工具执行了复杂的数学计算。具体来说代理正确解析了数学表达式(121 2) * 5代理首先调用加法工具计算121 2 123然后调用乘法工具计算123 * 5 615最后给出了完整的计算过程和结果5.2 上下文记忆能力通过Context对象代理能够记住之前的对话内容。当用户询问我的名字是什么时代理能够正确回答之前提到的John Doe。这展示了代理的状态管理能力。5.3 文档查询能力基于RAG的代理成功查询了Uber 2021年的10-K文档并提取了关于风险因素和增长机会的信息。具体来说代理正确识别了需要使用查询工具来回答问题代理将自然语言问题转换为适合查询引擎的格式代理从查询结果中提取了关键信息并进行了总结代理提供了关于Uber风险因素和增长机会的详细回答5.4 工具调用透明度通过流式事件处理用户可以清楚地看到代理调用了哪些工具、传递了什么参数以及获得了什么结果。这种透明度使得代理的行为更加可理解和可调试。6. 案例实现思路6.1 函数调用机制本案例基于Anthropic的函数调用机制允许语言模型调用预定义的函数。这种机制使得代理能够与外部系统交互执行超出语言模型本身能力的任务如数学计算、数据查询等。6.2 工具定义与封装通过定义Python函数并将其作为工具传递给FunctionAgent我们实现了工具的封装。每个工具都有明确的参数类型和返回类型以及描述其功能的文档字符串。这种设计使得代理能够理解工具的用途并正确调用它们。6.3 代理与工具的交互代理通过函数调用机制与工具交互。当用户提出请求时代理会分析请求并决定是否需要调用工具。如果需要代理会生成适当的函数调用包括函数名和参数。工具执行后代理会处理结果并生成最终回答。6.4 状态管理通过Context对象我们实现了代理的状态管理。Context对象允许在多次调用之间共享状态使代理能够记住之前的对话内容。这种状态管理对于构建有记忆的对话系统至关重要。6.5 RAG集成通过将RAG查询引擎封装为QueryEngineTool我们实现了代理与RAG系统的集成。代理可以使用查询工具从文档中检索信息从而回答基于特定文档的问题。这种扩展使得代理能够访问和利用外部知识库。7. 扩展建议7.1 增强工具能力添加更多类型的工具如数据库查询、API调用、文件操作等实现工具的异步执行提高并发性能添加工具权限管理确保代理只能调用授权的工具7.2 改进代理能力实现多轮对话中的工具链式调用使代理能够解决更复杂的问题添加工具调用失败时的重试机制和错误处理实现工具调用的并行执行提高效率7.3 增强RAG功能集成多模态RAG支持图像、音频等多种数据类型实现实时文档更新机制保持RAG系统的知识新鲜度添加文档来源引用提高回答的可信度和可验证性7.4 优化用户体验实现更丰富的流式输出包括中间步骤和思考过程添加可视化工具调用流程的界面实现用户反馈机制允许用户纠正代理的错误7.5 部署与扩展设计分布式代理架构支持大规模并发请求实现代理的容器化部署提高可移植性和可扩展性添加监控和日志系统跟踪代理性能和使用情况8. 总结本案例展示了如何使用LlamaIndex和Anthropic API构建一个具有函数调用能力的智能代理。通过这个案例我们了解了如何定义工具并将其集成到代理中如何使用FunctionAgent创建具有函数调用能力的代理如何管理代理的上下文和记忆如何将RAG系统与代理集成实现基于文档的问答如何通过流式事件处理监控代理的行为函数调用机制是构建智能代理的关键技术之一它使得代理能够与外部系统交互执行超出语言模型本身能力的任务。通过将各种工具如计算工具、查询工具、API工具等集成到代理中我们可以构建出功能强大的智能系统解决各种复杂问题。本案例中的代理虽然简单但展示了构建智能代理的核心概念和技术。通过扩展工具集、改进代理能力和优化用户体验我们可以构建出更加智能、更加实用的代理系统为各行各业的数字化转型提供支持。