【笔记】动手学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
相关推荐
省四收割者2 小时前
Go语言入门(10)-数组
数据结构·经验分享·笔记·vscode·算法·golang
喜欢你,还有大家2 小时前
Linux笔记8——shell编程基础-2
linux·服务器·笔记
泽虞2 小时前
《LINUX系统编程》笔记p3
linux·运维·服务器·c语言·笔记·面试
firshman_start3 小时前
文件包含的学习笔记
笔记·学习
shuououo6 小时前
集成算法学习笔记
笔记·学习·算法
雪下的新火7 小时前
Unity-HDRP场景搭建-那山
经验分享·笔记·unity·游戏引擎·场景搭建
我爱学嵌入式8 小时前
C语言:第18天笔记
c语言·开发语言·笔记
Y4090018 小时前
Java算法之排序
java·数据结构·笔记·算法
DFT计算杂谈9 小时前
VASPKIT模版INCAR笔记
笔记