FunctionCall 与 AI-ReAct:让大模型更聪明的交互方式

182 阅读4分钟

如何让大模型突破知识限制,准确执行复杂任务?FunctionCall和ReAct模式正在改变我们与大模型的交互方式。

一、大模型的局限性:幻觉问题

大语言模型(LLM)在自然语言处理方面表现出色,但存在一个致命弱点:幻觉问题。当模型遇到知识边界时,它会生成看似合理实则错误的答案

# 示例:大模型可能编造虚假答案
response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "user", "content": "请告诉我XX公司2025年的股票预测价格"}
    ]
)
print(response.choices[0].message.content)
# 输出:根据市场分析,XX公司2025年股价预计达到$150...

这种“一本正经胡说八道”的现象就是幻觉问题。为了解决这个问题,我们引入了FunctionCallReAct模式。

二、FunctionCall:给大模型装上“工具手”

FunctionCall的核心思想是:让大模型理解它能使用哪些外部工具,而不是强迫它记住所有知识。

工具定义:创建函数说明书

# 定义可用的工具函数
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_closing_price",
            "description": "获取指定股票的收盘价",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "股票名称"}
                },
                "required": ["name"]
            }
        }
    }
]

工具实现:连接真实数据源

# 实际获取股票价格的函数
def get_closing_price(name):
    if name == '青岛啤酒': return '67.92'
    elif name == '贵州茅台': return '1488.21'
    else: return '未找到该股票'

模型调用:大模型自主选择工具

# 发送请求时带上工具说明
response = client.chat.completions.create(
    model='deepseek-reasoner',
    messages=messages,
    tools=tools,  # 关键:告诉模型可用的工具
    tool_choice='auto'  # 让模型自主决定是否使用工具
)

三、ReAct模式:思考-行动-观察的智能循环

ReAct(Reason + Action)是一种让大模型分步思考、执行、验证的智能体模式,解决了复杂任务的执行问题。

ReAct工作流程

  1. 思考(Reason):分析是否需要工具
  2. 行动(Act):调用合适的函数
  3. 观察(Observe):获取函数结果
  4. 重复直到得出最终答案

ReAct提示词设计

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

TOOLS:
------

您可以使用以下工具:

{tools}

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

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

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

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

开始!

新输入: {input}

"""

完整ReAct实现

# ReAct智能体核心逻辑
while True:
    # 1. 模型生成响应
    response = send_messages(messages)
    response_text = response.choices[0].message.content
    
    # 2. 检查是否获得最终答案
    if "最终答案:" in response_text:
        final_answer = re.search(r'最终答案:\s*(.*)', response_text).group(1)
        print("最终答案:", final_answer)
        break
    
    # 3. 解析工具调用
    tool_name = re.search(r'行动:\s*(\w+)', response_text).group(1)
    params = json.loads(re.search(r'行动输入:\s*({.*?})', response_text).group(1))
    
    # 4. 执行工具调用
    if tool_name == "get_closing_price":
        result = get_closing_price(params["name"])
        messages.append({'role': 'user', 'content': f"Observation:{result}"})

四、实战案例:股票价格比较助手

结合FunctionCallReAct,我们创建一个能准确回答股票问题的智能体:

# 用户查询:比较两个股票的价格
query = "青岛啤酒和贵州茅台的收盘价哪个贵?"

# 构建初始消息
prompt = REACT_PROMPT.format(
    instructions="你是一个股票助手",
    tools=json.dumps(tools),
    tool_names="get_closing_price",
    input=query
)
messages = [{"role": "user", "content": prompt}]

# 执行ReAct循环
while True:
    # 模型响应示例:
    # ```
    # 思考: 我需要使用工具吗? 是
    # 行动: get_closing_price
    # 行动输入: {"name": "青岛啤酒"}
    # ```
    response = send_messages(messages)
    
    # ...(处理响应,调用工具)
    
    # 最终输出:
    # 思考: 我需要使用工具吗? 否
    # 最终答案: 贵州茅台的收盘价(1488.21元)比青岛啤酒(67.92元)贵

五、总结

FunctionCallReAct模式代表了LLM开发的新阶段:

  1. 从全能到利用工具:模型不再需要知道所有答案,而是学会调用专业工具
  2. 从单次到循环思考:通过多次Reason-Act循环解决复杂问题
  3. 从封闭到开放生态:任何API都可以成为模型的"感官"和"手脚"

随着工具生态的完善,大模型正在从“知道一切”的百科全书,进化为“会使用工具”的智能体!