【笔记】动手学Ollama 第七章 应用案例 Agent应用

正文详见:7.5 使用 LangChain 实现本地 Agenthttps://datawhalechina.github.io/handy-ollama/#/C7/5.%20%E4%BD%BF%E7%94%A8%20LangChain%20%E5%AE%9E%E7%8E%B0%E6%9C%AC%E5%9C%B0%20Agent

一、LangChain版本

1、安装模型

  • 语言模型:ollama pull gemma:2b

2、初始化Agent工具

  • Class SearchInput(BaseModel)描述输入数据的结构,可以用来检查参数的类型。在此代码中,location则被要求必须是字符串类型。
  • Field()函数给location添加了额外的约束(description="location to search for"),表示location的用途为"要搜索的位置",这些描述信息会成为提示词被AI利用起来,用来理解参数的用途。
  • @tools是一个装饰器(decorator),表明这是一个可以被AI调用的工具。args_schema=SearchInput则表示这个工具的输入参数必须符合SearchInput定义的结构。
  • weather_forecast()函数解释u的一个字符串类型的参数location,但因为使用了args_schema,所以实际上传入的参数是从SearchInput解析出来的带有Field的参数。
  • """天气预报工具。"""字符串是AI Agent最重要的部分之一,Agent会读取这个描述来判断该工具的功能,以确定能在什么时候使用它。

总体来看,AI Agent会:

  1. 分析问题 → 发现与"天气"相关
  2. 查找可用工具 → 找到weather_forecast工具
  3. 解析参数 → 识别出location="杭州"
  4. 验证输入 → 使用SearchInput模型验证
  5. 调用函数 → weather_forecast("杭州")
  6. 得到返回值 → "A dummy forecast for 杭州."
  7. 回答用户 → "根据预报,杭州......"(具体内容取决于返回值)
python 复制代码
from pydantic import BaseModel, Field
from langchain_core.tools import tool  

class SearchInput(BaseModel):
    location: str = Field(description="location to search for")  # 定义一个 Pydantic 模型,用于描述输入模式,并提供描述信息

@tool(args_schema=SearchInput)
def weather_forecast(location: str):
    """天气预报工具。"""
    print(f"Weather for {location}")  # 打印要预报天气的位置
    return f"A dummy forecast for {location}."  # 返回给定位置的虚拟天气预报

3、初始化模型和工具

  • 加载模型gemma:2b
  • 定义工具列表,此处只有一个weather_forecast
python 复制代码
from langchain_community.chat_models import ChatOllama

llm = ChatOllama(model="gemma:2b")
tools = [weather_forecast]

4、创建提示模板

  • hub.pull的作用是是从LangChain Hub(类似于Github)中加载一个预定义的提示模板,其中react-json是一个著名ReAct模板。
  • react-json模板包含如何思考、要采取的动作、动作的输入、观察结果、最终回答,同时支持JSON格式解析,允许模型输出结构化的动作,如:调用那个工具、传什么参数。
  • partial方法的任务是将某些变量(包含工具)注入进提示模板中
    • render_text_description函数将工具转换成一段可读的文本描述。如:

      python 复制代码
      weather_forecast: 天气预报工具。参数: location (str) - location to search for
    • ", ".join则通过遍历tools列表,提取每个工具的名称(函数名)并用","拼接在一起。这样可以限制模型只能选择列出的工具名,防止其胡编乱造

python 复制代码
from langchain import hub
from langchain_core.tools import render_text_description

prompt = hub.pull("hwchase17/react-json")
prompt = prompt.partial(
    tools=render_text_description(tools), 
    tool_names=", ".join([t.name for t in tools]),
)

5、创建Agent

  • create_react_agent函数表明这是一个遵循ReAct架构的AI Agent,该架构的特点是在回答用户问题是进行"思考 → 行动 → 观察 → 回答"循环模式。其输入有三个核心组件:
    • 负责推理和决策的语言模型:llm
    • 可调用的外部工具列表:tools
    • 定制化的提示模板(已注入工具信息):prompt
  • AgentExecutor函数用来封装Agent,使Agent能够自动执行"思考 → 调用工具 → 获取结果 → 继续推理"的完整流程。
    • agent:create_react_agent创建的Agent
    • tools:告诉executor哪些工具可执行
    • handle_parsing_errors:自动处理错误
    • verbose:打印中间步骤日志
    • format:指定模型处处格式
python 复制代码
from langchain.agents import AgentExecutor, create_react_agent

agent = create_react_agent(llm, tools, prompt) 
agent_executor = AgentExecutor(agent=agent, tools=tools, handle_parsing_errors=True, verbose=False, format="json")  

6、运行Agent

python 复制代码
print(agent_executor.invoke({"input":"What is the weather in Paris?"}))

7、使用对话历史

在使用对话历史时,需要使用 react-chat Prompt 模板。在 invoke 时,加入 chat_history

python 复制代码
prompt = hub.pull("hwchase17/react-chat")

# 构建 ReAct agent
agent_history = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent_history, tools=tools, verbose=False)

agent_executor.invoke(
    {
        "input": "what's my name? Only use a tool if needed, otherwise respond with Final Answer",
        "chat_history": "Human: Hi! My name is Bob\nAI: Hello Bob! Nice to meet you",
    }
)

你可以看到在输出的地方有一行警告信息,这是因为新版的lnagchain自带了langsmith。langsmith是一个在线的调式与监控平台,可以记录Agent调式的整个流程,由于我们并没有设置langsmith的API,所以出现了报错。

二、LlamaIndex版本

1、安装模型

  • ollama pull qwen2:0.5b

2、初始化Agent工具

FunctionTool.from_defaults()方法用于把普通函数包装成AI可调用的工具

  • fn:指定要包装的原始函数
  • name:工具名称,AI或系统内部通过name引用该函数
  • description:描述工具功能,直接告诉AI工具能做什么
  • return_direct:表示AI调用工具后,直接将结果返回给用户,不再需要进过AI加工
python 复制代码
from llama_index.core.tools import FunctionTool

# Define tools
def multiply(a: float, b: float) -> float:
    """Multiply two integers and return the result integer"""
    return a * b

# Create FunctionTool instances
multiply_tool = FunctionTool.from_defaults(
    fn=multiply,
    name="MultiplyTool",
    description="A tool that multiplies two floats.",
    return_direct=True
)

3、初始化LLM和Agent

通过ReActAgent.from_tools()方法创建具备工具调用能力的ReAct架构的智能体

  • tools:一个包含可用工具的列表,此时只存入了一个工具,Agent也只能使用该工具
  • llm:大语言模型
  • verbose=True:开启"详细模式",Agent运行时,会打印出每一步的思考过程
python 复制代码
from llama_index.llms.ollama import Ollama
from llama_index.core.agent import ReActAgent

# 初始化 LLM
llm = Ollama(model="qwen2:0.5b", request_timeout=360.0)

# 初始化 ReAct Agent(新写法)
agent = ReActAgent(
    llm=llm,
    tools=[multiply_tool],  # 注意:参数名是 tools,不是 [multiply_tool] 作为位置参数
    verbose=True
)

4、进行对话(不调用Agent)

python 复制代码
# direct response
res_llm = llm.complete("What is 2.3 × 4.8 ? Calculate step by step")
print(res_llm)

在不调用Agent的情况下,可以看到,仅凭借该模型(qwen2.0)的能力,无法实现带有小数点的数字相乘的计算

5、进行对话(调用Agent)

python 复制代码
# use agent
response = agent.chat("What is 2.3 × 4.8 ? Calculate step by step")
response.response
相关推荐
Yawesh_best16 小时前
告别系统壁垒!WSL+cpolar 让跨平台开发效率翻倍
运维·服务器·数据库·笔记·web安全
Ccjf酷儿18 小时前
操作系统 蒋炎岩 3.硬件视角的操作系统
笔记
习习.y18 小时前
python笔记梳理以及一些题目整理
开发语言·笔记·python
在逃热干面19 小时前
(笔记)自定义 systemd 服务
笔记
DKPT20 小时前
ZGC和G1收集器相比哪个更好?
java·jvm·笔记·学习·spring
QT 小鲜肉21 小时前
【孙子兵法之上篇】001. 孙子兵法·计篇
笔记·读书·孙子兵法
星轨初途1 天前
数据结构排序算法详解(5)——非比较函数:计数排序(鸽巢原理)及排序算法复杂度和稳定性分析
c语言·开发语言·数据结构·经验分享·笔记·算法·排序算法
QT 小鲜肉1 天前
【孙子兵法之上篇】001. 孙子兵法·计篇深度解析与现代应用
笔记·读书·孙子兵法
love530love1 天前
【笔记】ComfUI RIFEInterpolation 节点缺失问题(cupy CUDA 安装)解决方案
人工智能·windows·笔记·python·插件·comfyui
愚戏师1 天前
MySQL 数据导出
数据库·笔记·mysql