Web开发者快速上手AI Agent:基于Function Calling的多步交互提示词优化实战

Web开发者快速上手AI Agent:基于Function Calling的多步交互提示词优化实战

图片来源网络,侵权联系删。

文章目录

  • [1. 从Web表单到AI多步交互,逻辑从未改变](#1. 从Web表单到AI多步交互,逻辑从未改变)
  • [2. Web开发与AI Agent的天然衔接点](#2. Web开发与AI Agent的天然衔接点)
  • [3. Function Calling核心原理:AI版的RPC调用](#3. Function Calling核心原理:AI版的RPC调用)
  • [4. 实战:用Java+React构建多步交互Agent](#4. 实战:用Java+React构建多步交互Agent)
    • [4.1 后端:Spring Boot定义工具函数](#4.1 后端:Spring Boot定义工具函数)
    • [4.2 Agent主逻辑:多轮交互控制器](#4.2 Agent主逻辑:多轮交互控制器)
    • [4.3 前端:React可视化多步交互](#4.3 前端:React可视化多步交互)
  • [5. 常见问题与Web开发者解决方案](#5. 常见问题与Web开发者解决方案)
    • [5.1 问题:模型不调用函数,或参数错误](#5.1 问题:模型不调用函数,或参数错误)
    • [5.2 问题:多步执行超时或中断](#5.2 问题:多步执行超时或中断)
    • [5.3 问题:敏感函数被滥用(如删除数据库)](#5.3 问题:敏感函数被滥用(如删除数据库))
  • [6. 总结与Web开发者的AI学习路径](#6. 总结与Web开发者的AI学习路径)

1. 从Web表单到AI多步交互,逻辑从未改变

在传统Web开发中,我们经常处理这样的场景:用户填写一个表单(比如"查北京明天天气"),前端发送请求到后端,后端调用第三方API(如和风天气),拿到数据后再返回给前端渲染。整个过程是线性、可控、可调试的。

而如今,当我们将大语言模型(LLM)引入应用时,如果只是简单地"问一句答一句",就浪费了AI的真正潜力。Function Calling(函数调用)机制 ,正是让AI具备"主动调用工具"能力的关键------它允许模型在回答过程中,自主决定是否需要调用外部函数,并等待结果后再继续推理。

这就像让AI拥有了"后端开发能力":它能像你写的Controller一样,根据用户意图决定调用哪个Service。

对于Web开发者而言,Function Calling不是新概念,而是你已掌握的API调用思维在AI世界的自然延伸。本文将带你用熟悉的Java+React技术栈,实战构建一个支持多步交互的AI Agent应用。

2. Web开发与AI Agent的天然衔接点

很多Web开发者误以为AI开发必须从零学起Python、PyTorch。其实不然------现代AI Agent应用的核心架构,与Web服务高度相似

Web开发概念 AI Agent对应概念 类比说明
RESTful API Function (Tool) 每个工具函数就是一个可被调用的"端点"
Controller Agent Prompt + LLM 决定调用哪个工具、如何组合结果
Request Body Function Arguments 模型生成的JSON参数,直接传给函数
JWT / OAuth Tool Permission Control 控制哪些Agent能调用敏感函数
Frontend State Conversation History 多轮对话上下文 = 前端状态管理

举个例子:你在Vue中用axios.post('/api/weather', {city: '北京'}),在Agent中就是模型生成{"name": "get_weather", "arguments": {"city": "北京"}}

这种一致性意味着:你不需要成为AI专家,只需把已有Web工程能力"平移"到AI场景

3. Function Calling核心原理:AI版的RPC调用

Function Calling的本质,是让大模型在生成文本前,先输出一个"函数调用指令"。这个指令包含:

  • 要调用的函数名(name
  • 函数所需的参数(arguments,JSON格式)

然后由你的程序执行该函数,将结果"塞回"给模型,让它继续生成最终回答。

用Web思维理解三步流程:

Your Function (e.g., WeatherService) LLM Agent User Your Function (e.g., WeatherService) LLM Agent User "北京明天天气怎么样?" 分析意图 → 需要调用get_weather 调用 get_weather(city="北京") 返回 {"temp": 5, "desc": "晴"} "北京明天晴,气温5°C。"

这不就是典型的"前端→后端→第三方服务→后端→前端"流程吗?只不过现在"后端决策者"换成了AI。

关键在于:你定义的函数描述(function schema)必须足够清晰,就像写Swagger文档一样。模型靠这个"文档"决定何时调用、传什么参数。

外链图片转存中...(img-ZsoJXt2j-1767541792166)

4. 实战:用Java+React构建多步交互Agent

我们将构建一个支持"查天气+查新闻"的Agent。用户问:"北京明天天气如何?有什么重要新闻?",Agent应分两步调用不同工具。

4.1 后端:Spring Boot定义工具函数

首先,定义两个工具函数(Service):

java 复制代码
// WeatherService.java
@Service
public class WeatherService {
    public String getWeather(String city) {
        // 模拟调用第三方API
        return "{\"temp\": 5, \"desc\": \"晴\"}";
    }
}

// NewsService.java
@Service
public class NewsService {
    public String getTopNews(String category) {
        return "[{\"title\": \"AI Agent技术突破\", \"source\": \"TechNews\"}]";
    }
}

然后,构建Function Calling所需的函数描述列表(相当于API文档):

java 复制代码
// FunctionRegistry.java
@Component
public class FunctionRegistry {
    public List<ChatCompletionTool> getTools() {
        return Arrays.asList(
            ChatCompletionTool.builder()
                .type(ToolType.FUNCTION)
                .function(FunctionDefinition.builder()
                    .name("get_weather")
                    .description("获取指定城市的天气信息")
                    .parameters(ObjectMapperFactory.create() // 定义参数结构
                        .readValue("{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"]}", JsonNode.class))
                    .build())
                .build(),
            ChatCompletionTool.builder()
                .type(ToolType.FUNCTION)
                .function(FunctionDefinition.builder()
                    .name("get_top_news")
                    .description("获取最新新闻")
                    .parameters(ObjectMapperFactory.create()
                        .readValue("{\"type\":\"object\",\"properties\":{\"category\":{\"type\":\"string\"}},\"required\":[]}", JsonNode.class))
                    .build())
                .build()
        );
    }
}

4.2 Agent主逻辑:多轮交互控制器

java 复制代码
// AgentService.java
@Service
public class AgentService {
    @Autowired private OpenAiClient openAiClient; // 假设已集成OpenAI SDK
    @Autowired private FunctionRegistry functionRegistry;
    @Autowired private WeatherService weatherService;
    @Autowired private NewsService newsService;

    public String handleUserQuery(String userMessage, List<Message> history) {
        List<Message> messages = new ArrayList<>(history);
        messages.add(new UserMessage(userMessage));

        while (true) {
            ChatCompletionResponse response = openAiClient.chatCompletion(messages, functionRegistry.getTools());
            
            if (response.hasToolCalls()) {
                // 模型要求调用函数
                ToolCall toolCall = response.getToolCalls().get(0);
                String result = executeTool(toolCall);
                
                // 将函数结果"塞回"对话历史
                messages.add(new AssistantMessage("", toolCall));
                messages.add(new ToolMessage(result, toolCall.getId()));
            } else {
                // 无函数调用,返回最终答案
                return response.getContent();
            }
        }
    }

    private String executeTool(ToolCall toolCall) {
        switch (toolCall.getFunction().getName()) {
            case "get_weather":
                String city = parseArgument(toolCall, "city");
                return weatherService.getWeather(city);
            case "get_top_news":
                return newsService.getTopNews("tech");
            default:
                throw new IllegalArgumentException("Unknown function: " + toolCall.getFunction().getName());
        }
    }
}

4.3 前端:React可视化多步交互

使用useReducer管理对话状态,清晰展示每一步:

jsx 复制代码
// AgentChat.jsx
import { useReducer, useEffect } from 'react';

const initialState = { messages: [], status: 'idle' };

function chatReducer(state, action) {
  switch (action.type) {
    case 'user_send':
      return { ...state, messages: [...state.messages, { role: 'user', content: action.text }] };
    case 'agent_think':
      return { ...state, status: 'thinking' };
    case 'agent_tool_call':
      return {
        ...state,
        messages: [...state.messages, { 
          role: 'assistant', 
          tool_calls: [{ name: action.toolName, args: action.args }] 
        }]
      };
    case 'tool_result':
      return {
        ...state,
        messages: [...state.messages, { 
          role: 'tool', 
          content: action.result,
          tool_call_id: action.id 
        }]
      };
    case 'agent_reply':
      return {
        ...state,
        messages: [...state.messages, { role: 'assistant', content: action.text }],
        status: 'idle'
      };
    default:
      return state;
  }
}

export default function AgentChat() {
  const [state, dispatch] = useReducer(chatReducer, initialState);

  const handleSubmit = async (text) => {
    dispatch({ type: 'user_send', text });
    dispatch({ type: 'agent_think' });

    const response = await fetch('/api/agent', {
      method: 'POST',
      body: JSON.stringify({ message: text, history: state.messages })
    });
    const data = await response.json();

    // 假设后端返回完整的交互步骤(简化版)
    data.steps.forEach(step => {
      if (step.type === 'tool_call') {
        dispatch({ type: 'agent_tool_call', toolName: step.name, args: step.args });
        dispatch({ type: 'tool_result', id: step.id, result: step.result });
      } else if (step.type === 'reply') {
        dispatch({ type: 'agent_reply', text: step.content });
      }
    });
  };

  return (
    <div>
      {state.messages.map((msg, i) => (
        <div key={i} className={`message ${msg.role}`}>
          {msg.role === 'tool' ? `[工具调用结果: ${msg.content}]` : msg.content}
        </div>
      ))}
      {/* 输入框... */}
    </div>
  );
}

通过这种方式,前端不仅能展示最终答案,还能让用户看到AI"思考过程"------极大提升可信度。

5. 常见问题与Web开发者解决方案

5.1 问题:模型不调用函数,或参数错误

原因:函数描述(schema)不够清晰,如同API文档缺失字段说明。

解决

  • 使用严格JSON Schema定义参数(必填/类型/示例);
  • 在提示词中强调:"你必须使用提供的工具,不要自行编造数据"。

5.2 问题:多步执行超时或中断

类比:Web请求超时。

解决

  • 设置Agent最大调用步数(如最多3次函数调用);
  • 前端增加"取消"按钮,中断长流程。

5.3 问题:敏感函数被滥用(如删除数据库)

类比:未鉴权的DELETE接口。

解决

  • executeTool中加入权限检查:

    java 复制代码
    if ("delete_user".equals(toolName) && !currentUser.isAdmin()) {
        throw new SecurityException("无权限");
    }
  • 对高危函数设置白名单。

6. 总结与Web开发者的AI学习路径

Function Calling不是魔法,而是将你已有的Web工程能力扩展到AI领域的桥梁。通过本文实战,你应该意识到:

  • AI Agent = 智能Controller:它根据用户输入决定调用哪些"Service"(工具函数);
  • 提示词 = 路由规则 + 业务逻辑注释:告诉模型"你能做什么、怎么调用";
  • 多步交互 = 可视化的工作流:前端展示每一步,提升用户体验。

推荐学习路径(针对Web开发者):

  1. 入门:用JavaScript/Java封装几个简单工具函数(如计算器、时间查询),接入OpenAI或Ollama;
  2. 进阶:学习LangChain.js或LlamaIndex.ts,它们提供了Web友好的Agent抽象;
  3. 工程化:将Agent部署为微服务,通过API网关统一管理;
  4. 创新:结合前端框架(如Next.js)构建全栈AI应用。

真实可靠资源推荐:

记住:你不需要成为AI科学家,只需做会用AI的Web工程师------这才是当前市场的稀缺能力。

相关推荐
创客匠人老蒋11 小时前
从“经验驱动”到“系统智能”:实体门店经营的结构性升级
大数据·人工智能
安达发公司11 小时前
安达发|APS自动排产排程排单软件:让汽车零部件厂排产不“卡壳”
大数据·人工智能·汽车·aps高级排程·aps排程软件·aps自动排产排程排单软件
不知疲倦的仄仄11 小时前
第一天:从 ByteBuffer 内存模型到网络粘包处理实战
java·网络·nio
Tinachen8811 小时前
YonBIP旗舰版本地开发环境搭建教程
java·开发语言·oracle·eclipse·前端框架
草莓熊Lotso11 小时前
脉脉独家【AI创作者xAMA】| 多维价值与深远影响
运维·服务器·数据库·人工智能·脉脉
V搜xhliang024611 小时前
常规超声联合影像组学预测肾透明细胞癌核分级的列线图模型构建和验证
人工智能·计算机视觉
星火开发设计11 小时前
堆排序原理与C++实现详解
java·数据结构·c++·学习·算法·排序算法
柠檬071111 小时前
opencv 未知函数记录-detailEnhance
人工智能·opencv·计算机视觉
七七powerful11 小时前
docker28.1.1和docker-compose v.2.35.1安装
java·docker·eureka
空山新雨后、11 小时前
ComfyUI、Stable Diffusion 与 ControlNet解读
人工智能