Day10:探索 ReAct 范式基础:融合推理与行动的智能交互模式

摘要:本文聚焦于 ReAct 范式,深入剖析其原理,以通义千问大模型为例,详细阐述它与 Function Call 的结合方式,并梳理 ReAct Agent 的执行流程。通过编写具体代码实现 “用户问天气→模型推理需要调用天气工具→调用工具获取天气→模型整理回答” 的完整流程,帮助读者掌握 ReAct 范式在实际应用中的落地方法。

一、引言

在大语言模型的应用场景中,ReAct 范式为实现更智能、灵活的交互提供了一种强大的思路。它将推理和行动相结合,使得模型能够根据用户问题,合理调用外部工具获取信息,进而给出更准确、有用的回答。今天,我们就围绕 ReAct 范式展开学习,并以通义千问大模型为基础进行实践。

二、核心任务

(一)ReAct 范式解析

ReAct 范式遵循 “推理→动作→观察→再推理” 的循环流程:

  1. 推理:模型接收用户输入后,首先对问题进行理解和分析,推理出解决问题所需的步骤和可能的行动方案。例如,当用户询问 “北京今天的天气如何?”,模型会判断需要获取天气信息,可能推理出调用天气查询工具这一行动。

  2. 动作:基于推理结果,模型决定执行相应的动作,即调用外部工具或函数。在上述天气查询的例子中,就是调用天气查询工具,并传入相关参数(如城市名称)。

  3. 观察:执行动作后,模型获取工具返回的结果,即观察到的信息。对于天气查询,会得到北京当天的天气数据,如温度、天气状况等。

  4. 再推理:模型将观察到的信息纳入考量,再次进行推理,以整理出符合用户需求的最终回答。它会根据获取的天气数据,组织语言,生成如 “北京今天的天气是晴天,温度为 25 摄氏度” 这样的回答。

(二)ReAct 与 Function Call 的结合

Function Call 为 ReAct 范式中的 “动作” 环节提供了具体实现方式。通过定义各种工具函数(如前文的查询天气函数 query_weather),模型可以根据推理结果选择合适的函数进行调用。例如,在天气查询场景下,模型推理出需要调用天气查询函数后,利用 Function Call 机制,按照函数定义的参数要求传递信息,调用函数获取天气数据。

(三)ReAct Agent 执行流程梳理

  1. 接收用户输入:ReAct Agent 获取用户提出的问题,如 “上海明天的天气怎么样?”。

  2. 初始推理:Agent 对用户问题进行理解和分析,确定解决问题需要的工具或函数。在这个例子中,识别到需要调用天气查询函数。

  3. Function Call 准备:根据推理结果,构建函数调用所需的参数。对于天气查询函数,需要准备城市名称(“上海”)和 API 密钥等参数。

  4. 工具调用:使用 Function Call 机制调用相应的工具函数(如 query_weather),将参数传递给函数,获取工具返回的天气数据。

  5. 观察结果:接收工具函数返回的天气信息,如天气状况、温度、风力等。

  6. 最终推理与回答生成:Agent 对获取的天气数据进行整理和分析,以自然语言的形式生成回答,如 “上海明天预计是多云天气,温度在 22 - 28 摄氏度之间”,并返回给用户。

三、补充任务:编写 ReAct 流程代码

import requests
from pydantic import BaseModel, field_validator
import json


# 定义天气查询函数
class WeatherQueryParams(BaseModel):
    city: str
    api_key: str

    @field_validator('city')
    def city_not_empty(cls, v):
        if not v.strip():
            raise ValueError('城市名称不能为空')
        return v

    @field_validator('api_key')
    def api_key_not_empty(cls, v):
        if not v.strip():
            raise ValueError('api_key不能为空')
        return v


def query_weather(params: WeatherQueryParams):
    base_url = "http://api.weatherapi.com/v1/forecast.json"
    params_dict = {
        "key": params.api_key,
        "q": params.city,
        "days": 1
    }
    try:
        response = requests.get(base_url, params=params_dict)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        print(f"查询天气失败: {e}")
        return None


# 模拟通义千问API调用(实际需替换为真实API调用)
def call_qwen_api(api_key, prompt):
    url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {api_key}"
    }
    data = {
        "model": "qwen-plus",
        "messages": [
            {"role": "user", "content": prompt}
        ],
        "stream": False
    }
    try:
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        print(f"调用通义千问API失败: {e}")
        return None


# ReAct流程实现
def react_flow(user_input, api_key):
    # 调用通义千问API
    response = call_qwen_api(api_key, user_input)
    if response and "function_call" in response:
        function_call = response["function_call"]
        function_name = function_call["name"]
        function_args = function_call["parameters"]
        if function_name == "query_weather":
            params = WeatherQueryParams(**function_args)
            weather_data = query_weather(params)
            if weather_data:
                forecast = weather_data["forecast"]["forecastday"][0]
                condition = forecast["condition"]["text"]
                min_temp = forecast["day"]["mintemp_c"]
                max_temp = forecast["day"]["maxtemp_c"]
                answer = f"{params.city}明天的天气是{condition},温度在{min_temp} - {max_temp}摄氏度之间"
            else:
                answer = "天气查询失败"
    elif response:
        answer = response["choices"][0]["message"]["content"]
    else:
        answer = "通义千问API调用或处理出现问题"
    return answer


# 用户输入测试
if __name__ == "__main__":
    api_key = "api_key"
    user_question = "上海明天的天气怎么样?"
    result = react_flow(user_question, api_key)
    print(result)

代码说明

天气查询函数 **query_weather**
  • 接收 WeatherQueryParams 类型的参数,该参数包含城市名称 city 和 API 密钥 api_key

  • 使用 requests 库向天气查询 API 发送请求,请求获取指定城市未来一天的天气预报。

  • 如果请求成功,返回 API 响应的 JSON 数据;若请求失败,打印错误信息并返回 None

通义千问 API 调用函数 **call_qwen_api**
  • 接收 API 密钥 api_key 和用户输入的提示 prompt

  • 根据通义千问 API 的要求构建请求,包括设置请求头、请求体等。

  • 发送 POST 请求到通义千问的 API 地址,若请求成功,返回 API 响应的 JSON 数据;若请求失败,打印错误信息并返回 None

ReAct 流程函数 **react_flow**
  • 接收用户输入 user_input 和 API 密钥 api_key

  • 调用 call_qwen_api 函数获取通义千问的响应。

  • 如果响应中包含 function_call,表明模型判断需要调用函数。检查函数名是否为 query_weather,若是则构建参数调用 query_weather 函数获取天气数据。根据天气数据生成回答。

  • 如果响应中不包含 function_call,直接返回模型的回答。

  • 如果 API 调用或处理过程出现问题,返回相应的错误提示。

四、总结

通过今天的学习,我们深入了解了 ReAct 范式的原理、与 Function Call 的结合方式以及 ReAct Agent 的执行流程,并通过编写代码实现了一个简单的天气查询 ReAct 流程。

ReAct 范式为大语言模型的应用带来了更高的智能性和实用性,能够更好地满足用户多样化的需求。在实际应用中,可以根据具体场景扩展和优化这个流程,结合更多的工具函数和复杂的推理逻辑。记得将 ReAct 流程代码整理保存,以便后续参考和进一步开发。如果在学习过程中遇到问题,仔细检查函数定义、API 调用方式以及数据处理逻辑。

希望大家通过掌握 ReAct 范式,在大语言模型的应用开发中实现更强大、智能的功能。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐