【笔记】动手学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
相关推荐
~patience~7 小时前
WAV 逆向分析工具使用笔记
笔记
滴啦嘟啦哒7 小时前
【具身笔记】【π0.5 微调与仿真】五、在MuJoCo中实现可视化仿真
笔记·python·vla·具身
xier_ran7 小时前
【infra之路】AI 编译器学习笔记(十三):AI 编译器全景——TVM、XLA、IREE 与其他
人工智能·笔记·学习
连山齐名7 小时前
ai应用开发的学习笔记
服务器·笔记·学习
乔旭伟7 小时前
中小厂生产管理系统选型笔记:驱动方式、主线链路与成本结构
笔记·需求分析·规格说明书
xier_ran7 小时前
【infra之路】AI 编译器学习笔记(十四):为什么要 tiling,以及矩阵计算单元的“固定“
人工智能·笔记·学习
如旧呀8 小时前
origin绘制等距的HSD置信区间
笔记·origin
问心无愧05138 小时前
[极客大挑战 2019]Upload
笔记
蒸蒸yyyyzwd9 小时前
CMU 11-768 p1-3 笔记
笔记
Generalzy9 小时前
Qt 桌面开发入门:PySide6 学习路线、架构原理与技术选型
笔记·python·学习