0基础进大厂,第13天:AI-ReAct——思维链式调用API

引言

在第9天和第10天,我们分别学习了AI的基础入门知识------如何开启与AI的循环对话、如何引入第三方接口。今天来聊聊如何让AI模拟人类做出决策的思维推理过程。

Agent 智能体

  • LLM 开发的一种设计模式,让大模型变得更聪明的一种套路
  • 通过结合LLM和其他工具或数据源,增强其能力

什么是ReAct?

  • ReAct全称:Reasoning and Action
  • Reasoning and Action: 思维链 + 外部工具调用
  • 构建一个智能体
  • 这种思想是让LLM将一个的问题拆分成多个小问题,一步一步解决

准备工作

这里依然选用deepseek的API服务

依赖安装

需要的依赖

  • pip install tools
  • pip install prompt // 提示词设计
  • pip install openai
创建一个llm.py文件
ini 复制代码
// 若为首次引入,需要在终端输入 pip install openai
import openai from OpenAI
client = OpenAI(
    api_key = "放上你的密钥",
    base_url="https://api.deepseek.com/v1"
)
创建一个tools.py文件

这个文件专门用来存放调用外部接口的工具函数,这里自定义一个函数模拟外部接口

python 复制代码
# 工具列表,第三方函数的说明书
tools =[
     {
    "name": "get_closing_price",
    "description": "使用该工具获取指定的股票信息",
    "parameters": {
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "description": "股票名称,例如:贵州茅台、青岛啤酒"
            }
        },
        "required": ["name"]
    }
}
]

def get_closing_price(name):
    if name == "贵州茅台":
        return "1488.21"
    elif name == "青岛啤酒":
        return "67.92"
    else:
        return "未找到相关信息"
创建一个prompt.py文件

这个文件是一个专门用来设计提示词的文件,也是AI-ReAct的核心,提示词会引导大模型该如何思考、并嵌套了变量,告诉大模型应该做出什么样的行动

ini 复制代码
# 使用三引号"""创建多行字符串,可以保留字符串中的换行和格式
REACT_PROMPT = """
{instructions}

TOOLS:
------

您可以使用以下工具:

{tools}

使用工具时,请使用以下格式:

 ``
思考: 我需要使用工具吗? 是
行动: 要采取的行动,必须是[{tool_names}]其中之一
行动输入: 该行动的输入内容
``

然后等待人类使用 Observation 回复您操作的结果。
... (这个思考/行动/行动输入/观察可以重复 N 次)
当您有回应要对人类说,或者不需要使用工具时,您必须使用以下格式:

``
思考: 我需要使用工具吗? 否
最终答案: [在此输入您的回应]
``

开始!

新输入: {input}

"""
创建一个agent.py文件

这是一个主文件

1-20行都是简单的代码,就是导包和定义了一个发送消息的函数

这里主要介绍循环部分,是如何利用提示词模板引导大模型的

python 复制代码
# 导入所需的库
import json  # 用于处理JSON数据
from llm import client  # 导入LLM客户端
from prompt import REACT_PROMPT  # 导入预设的提示模板
from tools import get_closing_price,tools  # 导入工具函数
import re  # 导入正则表达式库

# 定义发送消息到LLM的函数
def send_messages(messages):
    """
    向LLM发送消息并获取响应
    :param messages: 消息列表
    :return: LLM的响应
    """
    response = client.chat.completions.create(
        model="deepseek-chat",  # 使用deepseek-chat模型
        messages=messages,  # 传入消息列表
        temperature=0.1,  # 设置温度参数,控制生成文本的随机性
    )
    return response

if __name__ == "__main__":
    # 设置助手的角色说明
    instructions = "你是一个股票助手,可以回答股票相关的问题"

    # 设置用户查询
    query = "青岛啤酒和贵州茅台的收盘价哪个贵?"
    
    # 使用模板构建完整的提示
    prompt = REACT_PROMPT.format(instructions=instructions,tools=tools,tool_names="get_closing_price",input=query)
    
    # 初始化消息列表
    messages = [{"role": "user", "content": prompt}]

    # 开始对话循环
    while True:
        # 发送消息并获取响应
        # print("发送消息到模型...", messages)

        response = send_messages(messages)
        response_text = response.choices[0].message.content

        # 打印模型的回复
        print("大模型的回复:")
        print(response_text)

        # 检查是否有最终答案
        # 使用正则表达式搜索回复文本中是否包含"Final Answer:",\s*匹配任意空白字符,(.*)捕获冒号后面的所有内容
        final_answer_match = re.search(r'最终答案:\s*(.*)', response_text)
        if final_answer_match:
            # 从正则匹配结果中提取第一个捕获组(括号内匹配到的内容),即"Final Answer:"后面的文本内容
            final_answer = final_answer_match.group(1)
            print("最终答案:", final_answer)
            # 如果有最终答案,结束对话
            break

        # 将模型的回复添加到消息历史
        messages.append(response.choices[0].message)

        # 解析模型回复中的动作和参数
        action_match = re.search(r'Action:\s*(\w+)', response_text)
        action_input_match = re.search(r'Action Input:\s*({.*?}|".*?")', response_text, re.DOTALL)  # 非贪婪匹配,匹配到第一个"}"或"""

        # 如果成功解析到动作和参数
        if action_match and action_input_match:
            tool_name = action_match.group(1)  # 获取工具名称
            params = json.loads(action_input_match.group(1))  # 解析参数
            print("工具名称:", tool_name)
            print("参数:", params)

            if tool_name == "get_closing_price":
                observation = get_closing_price(params["name"])  # 调用工具函数
                print("调用第三方API结果:", observation)
                # 将观察结果添加到消息历史
                messages.append({'role': 'user', 'content': f"observation:{observation}"})

AI-ReAct案例的整体工作逻辑

这个案例实现了一个 ReAct(Reasoning and Acting) 模式的AI Agent,它可以:

  1. 推理:分析问题并决定是否需要使用工具
  2. 行动:调用外部工具获取信息
  3. 观察:处理工具返回的结果
  4. 循环:重复上述过程直到得出最终答案

对话循环部分代码详解

让我逐步分析 agent.py 中的对话循环:

python 复制代码
while True:
    # 1. 发送消息并获取响应
    response = send_messages(messages)
    response_text = response.choices[0].message.content
    
    # 2. 检查是否有最终答案
    final_answer_match = re.search(r'最终答案:\s*(.*)', response_text)
    if final_answer_match:
        final_answer = final_answer_match.group(1)
        print("最终答案:", final_answer)
        break  # 找到最终答案,退出循环
    
    # 3. 将模型回复添加到消息历史
    messages.append(response.choices[0].message)
    
    # 4. 解析模型回复中的动作和参数
    action_match = re.search(r'Action:\s*(\w+)', response_text)
    action_input_match = re.search(r'Action Input:\s*({.*?}|".*?")', response_text, re.DOTALL)
    
    # 5. 如果解析到动作,执行工具调用
    if action_match and action_input_match:
        tool_name = action_match.group(1)
        params = json.loads(action_input_match.group(1))
        
        if tool_name == "get_closing_price":
            observation = get_closing_price(params["name"])
            # 将观察结果添加到消息历史
            messages.append({'role': 'user', 'content': f"observation:{observation}"})

为什么需要正则表达式?

正则表达式在这里起到了结构化解析的作用:

1. 检测最终答案

python 复制代码
final_answer_match = re.search(r'最终答案:\s*(.*)', response_text)
  • "最终答案"这四个字是我们模板里提供的,大模型会很大可能按照模板进行回复
  • 检测AI回复中是否包含"最终答案:"
  • \s* 匹配任意空白字符
  • (.*) 捕获冒号后面的所有内容
  • 如果找到,说明AI已经完成推理,可以结束循环

2. 解析工具调用

python 复制代码
action_match = re.search(r'Action:\s*(\w+)', response_text)
action_input_match = re.search(r'Action Input:\s*({.*?}|".*?")', response_text, re.DOTALL)
  • 从AI的回复中提取工具名称和参数
  • 第一个正则提取"Action:"后面的工具名
  • 第二个正则提取"Action Input:"后面的JSON参数或字符串参数

工作流程示例

以查询"青岛啤酒和贵州茅台的收盘价哪个贵?"为例:

第一轮对话:

css 复制代码
用户输入 → AI回复:
思考: 我需要使用工具吗? 是
行动: get_closing_price  
行动输入: {"name": "青岛啤酒"}

系统处理:

  • 正则表达式解析出工具名和参数
  • 调用 get_closing_price("青岛啤酒")
  • 返回结果"67.92"
  • 将结果添加到消息历史

第二轮对话:

makefile 复制代码
AI收到observation:67.92 → AI回复:
思考: 我需要使用工具吗? 是
行动: get_closing_price
行动输入: {"name": "贵州茅台"}

第三轮对话:

makefile 复制代码
AI收到observation:1488.21 → AI回复:
思考: 我需要使用工具吗? 否
最终答案: 贵州茅台的收盘价(1488.21)比青岛啤酒(67.92)贵

关键设计特点

  1. 状态保持 :通过 messages 列表维护完整的对话历史
  2. 结构化交互:使用预定义的格式让AI按照特定模式回复
  3. 工具集成:通过正则表达式解析实现工具调用
  4. 循环推理:直到找到最终答案才结束

这种设计让AI能够像人类一样进行多步推理,在需要时主动获取外部信息,最终给出综合的答案。

相关推荐
小白的程序空间3 分钟前
Anaconda Prompt中删除库虚拟环境【保姆级教程】
linux·开发语言·python
kinlon.liu8 分钟前
深度解析 AI 提示词工程(Prompt Engineering)
人工智能·prompt·提示词
semantist@语校11 分钟前
从Prompt到结构建模:如何以数据驱动重构日本语言学校体系?以国际日本语学院为例
数据结构·人工智能·ai·prompt·github·数据集·知识图谱
EulerBlind16 分钟前
【工具】Pycharm隐藏侧边灯泡提示
ide·python·pycharm
深度学习实战训练营20 分钟前
基于LSTM的机场天气分析及模型预测
人工智能·rnn·lstm
CareyWYR23 分钟前
大语言模型的上下文工程(Context Engineering for Large Language Models)
人工智能
FL162386312932 分钟前
使用目标检测yolo11去训练微藻细胞检测数据集YOLO格式703张6类别步骤和流程
人工智能·yolo·目标检测
PythonicCC36 分钟前
Python高级数据类型:字典(Dictionary)
开发语言·python
赵英英俊1 小时前
Python day18
python
斟的是酒中桃1 小时前
基于YOLOv8的火灾智能检测系统设计与实现
人工智能·深度学习·yolo·pyqt