LangChain4j 与 OpenAI 深度集成:Function Calling、JSON Mode 与结构化输出

LangChain4j 与 OpenAI 深度集成:Function Calling、JSON Mode 与结构化输出

前言

OpenAI 的 API 提供了强大的 Function Calling、JSON Mode、Assistants API 等高级特性,LangChain4j 1.4.0 通过深度集成将这些能力无缝融入 Java 生态。本文将详细介绍如何使用 LangChain4j 调用 OpenAI 的完整功能栈。

一、Function Calling 完整链路

1.1 @Tool 注解定义工具

java 复制代码
import dev.langchain4j.service.tool.Tool;

public class WeatherTools {
    
    @Tool("查询指定城市的天气预报")
    public String getWeather(String city) {
        // 模拟 API 调用
        return city + "今天气温 25°C,晴转多云";
    }
    
    @Tool("查询股票实时价格")
    public String getStockPrice(
        @P("股票代码,例如:AAPL, TSLA") String symbol
    ) {
        // 模拟 API 调用
        return symbol + " 当前股价 $150.25";
    }
    
    @Tool("计算两个数的和")
    public double add(double a, double b) {
        return a + b;
    }
}

1.2 参数自动映射

java 复制代码
public class ComplexTools {
    
    @Tool("创建订单")
    public String createOrder(
        @P("商品名称") String productName,
        @P("数量") int quantity,
        @P("收货地址") String address,
        @P(value = "备注", required = false) String note
    ) {
        return String.format(
            "订单已创建:%s x %d,地址:%s,备注:%s",
            productName, quantity, address, note
        );
    }
    
    // 支持复杂对象
    record OrderItem(String name, int quantity, double price) {}
    
    @Tool("批量创建订单")
    public String batchCreateOrder(@P("订单列表") List<OrderItem> items) {
        double total = items.stream()
            .mapToDouble(item -> item.quantity() * item.price())
            .sum();
        
        return String.format(
            "批量订单已创建,共 %d 件商品,总金额:%.2f",
            items.size(), total
        );
    }
}

1.3 Function Calling 流程

java 复制代码
import dev.langchain4j.service.AiService;

@AiService
public interface Assistant {
    String chat(String message);
}

public class FunctionCallingExample {
    
    public static void main(String[] args) {
        // 1. 创建 OpenAI 模型
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName("gpt-4")
                .build();
        
        // 2. 创建 AI Service
        Assistant assistant = AiServices.builder(Assistant.class)
                .chatLanguageModel(model)
                .tools(new WeatherTools(), new StockTools())
                .build();
        
        // 3. 调用
        String response = assistant.chat("北京今天天气如何?");
        System.out.println(response);
        // 输出: "北京今天气温 25°C,晴转多云"
    }
}

1.4 Function Calling 流程图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                  Function Calling 执行流程                      │
└─────────────────────────────────────────────────────────────┘

用户                      AI Service                  OpenAI
 │                          │                           │
 │ 1. "北京天气如何?"       │                           │
 ├─────────────────────────>│                           │
 │                          │ 2. 构建请求(包含工具Schema)│
 │                          ├───────────────────────────>│
 │                          │  {                         │
 │                          │    "tools": [              │
 │                          │      {                    │
 │                          │        "name": "getWeather",│
 │                          │        "description": "...",│
 │                          │        "parameters": {...} │
 │                          │      }                     │
 │                          │    ]                       │
 │                          │  }                         │
 │                          │                           │
 │                          │ 3. LLM 分析需要调用工具     │
 │                          │<───────────────────────────┤
 │                          │  {                         │
 │                          │    "tool_calls": [         │
 │                          │      {                    │
 │                          │        "id": "call_123",   │
 │                          │        "function": {       │
 │                          │          "name": "getWeather",│
 │                          │          "arguments": "{\"city\":\"北京\"}"│
 │                          │        }                    │
 │                          │      }                     │
 │                          │    ]                       │
 │                          │  }                         │
 │                          │                           │
 │                          │ 4. 执行工具 getWeather("北京") │
 │                          │<───────────────────────────┤
 │                          │                           │
 │                          │ 5. 返回工具执行结果           │
 │                          ├───────────────────────────>│
 │                          │  {                         │
 │                          │    "tool_call_id": "call_123",│
 │                          │    "role": "tool",         │
 │                          │    "content": "北京今天25°C"│
 │                          │  }                         │
 │                          │                           │
 │                          │ 6. LLM 基于工具结果生成最终回答 │
 │                          │<───────────────────────────┤
 │ 7. "北京今天气温 25°C"   │                           │
 │<─────────────────────────┤                           │
 │                          │                           │
 └──────────────────────────┴───────────────────────────┘

1.5 并行工具执行(1.4.0 新特性)

java 复制代码
@AiService
public interface ConcurrentAssistant {
    
    @UserMessage("同时查询{{city1}}和{{city2}}的天气")
    String queryWeather(
        @P("城市1") String city1,
        @P("城市2") String city2
    );
}

// LangChain4j 1.4.0 会并发调用两次 getWeather
String response = assistant.queryWeather("北京", "上海");
// AI 会同时发送两个工具调用请求,提高效率

二、JSON Mode 强制输出

2.1 启用 JSON Mode

java 复制代码
OpenAiChatModel model = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName("gpt-4o")
        .responseFormat("json_object")  // 强制 JSON 输出
        .build();

String jsonResponse = model.generate("请返回一个用户对象,包含 name 和 age");
// 输出: {"name": "张三", "age": 25}

2.2 JSON Schema 验证

java 复制代码
import dev.langchain4j.model.output.structured.Description;

public class User {
    private String name;
    
    @Description("用户年龄,范围 0-120")
    private int age;
    
    @Description("用户邮箱,必须包含 @")
    private String email;
    
    // getters and setters
}

@AiService
public interface JsonAssistant {
    
    User extractUser(String text);
}

// 使用
User user = assistant.extractUser("我叫张三,25岁,邮箱是zhangsan@example.com");
// 自动验证 Schema

2.3 结构化数据提取

java 复制代码
public class NewsExtractor {
    
    public record News(
        String title,
        String summary,
        String author,
        LocalDateTime publishTime,
        List<String> tags
    ) {}
    
    @AiService
    public interface NewsAssistant {
        
        @UserMessage("从以下文本中提取新闻信息:\n{{it}}")
        News extractNews(String text);
    }
    
    // 使用
    String text = """
        北京时间 2024-08-28 10:00,科技日报报道,
        LangChain4j 1.4.0 正式发布,带来了 Agentic 增强、
        MCP 流式传输等新特性。作者:张三。
        标签:AI、Java、开源
        """;
    
    News news = assistant.extractNews(text);
    // news.title() == "LangChain4j 1.4.0 正式发布"
    // news.author() == "张三"
    // news.tags() == ["AI", "Java", "开源"]
}

2.4 JSON Mode 流程图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                   JSON Mode 执行流程                           │
└─────────────────────────────────────────────────────────────┘

┌─────────┐    ┌──────────────┐    ┌─────────────┐    ┌───────┐
│  用户    │ -> │ @AiService  │ -> │  OpenAI     │ -> │  LLM   │
│ 输入文本 │ -> │  接口代理    │ -> │  API        │ -> │  gpt-4 │
└─────────┘    └──────────────┘    └─────────────┘    └───────┘
    │                │                  │               │
    │ 1. 调用方法      │ 2. 构建 JSON     │ 3. 发送请求   │ 4. 返回
    │ extractUser()   │ Schema 提示      │ responseFormat │ JSON
    │                 │                  │: "json_object"│
    └────────────────┴──────────────────┴───────────────┘
                           │
                    5. JSON 解析
                    6. 映射到 POJO
                    7. 返回给用户

JSON Mode 优势:
- 强制 JSON 输出,无需额外解析
- 支持 JSON Schema 验证
- 自动处理复杂嵌套结构

三、Assistants API 支持

3.1 创建 Assistant

java 复制代码
import dev.langchain4j.model.openai.assistant.*;

// 1. 创建 Assistant
Assistant assistant = OpenAiAssistant.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .description("客服助手,回答产品相关问题")
        .instructions("你是一个友好的客服助手,用简洁的语言回答问题")
        .model(OpenAiChatModelName.GPT_4O)
        .tools(new CustomerServiceTools())  // 注册工具
        .build();

// 2. 创建 Thread
Thread thread = assistant.createThread();

// 3. 添加消息
thread.addUserMessage("我想了解产品价格");

// 4. 运行 Assistant
Run run = thread.run();

// 5. 等待完成
Run completedRun = run.awaitCompletion();

// 6. 获取响应
List<AssistantMessage> messages = thread.messages();
String response = messages.get(messages.size() - 1).text();

3.2 文件操作

java 复制代码
// 上传文件
File file = new File("product_manual.pdf");
FileId fileId = assistant.uploadFile(file);

// 创建带文件的 Assistant
Assistant fileAssistant = OpenAiAssistant.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .instructions("基于上传的文件回答问题")
        .files(fileId)
        .build();

// 使用文件
Thread thread = fileAssistant.createThread();
thread.addUserMessage("产品手册中提到哪些功能?");
thread.run().awaitCompletion();

3.3 多轮对话管理

java 复制代码
// 创建 Thread
Thread thread = assistant.createThread();

// 多轮对话
thread.addUserMessage("什么是 LangChain4j?");
thread.run().awaitCompletion();
System.out.println(thread.lastMessage().text());

thread.addUserMessage("它支持哪些模型?");
thread.run().awaitCompletion();
System.out.println(thread.lastMessage().text());

thread.addUserMessage("如何快速开始?");
thread.run().awaitCompletion();
System.out.println(thread.lastMessage().text());

// Thread 自动管理历史消息

四、图像输入

4.1 单图输入

java 复制代码
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiChatModelName;

// 创建支持视觉的模型
ChatLanguageModel visionModel = OpenAiChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .modelName(OpenAiChatModelName.GPT_4O)
        .build();

// 图文混合输入
UserMessage message = UserMessage.from(
    ImageContent.from("https://example.com/screenshot.png"),
    TextContent.from("请解释这张截图中的错误信息")
);

String response = visionModel.generate(message);

4.2 多图对比

java 复制代码
UserMessage comparison = UserMessage.from(
    TextContent.from("对比这两张图片的差异:"),
    ImageContent.from("https://example.com/before.png"),
    ImageContent.from("https://example.com/after.png")
);

String diff = visionModel.generate(comparison);

4.3 Base64 图像

java 复制代码
// 从文件读取
byte[] imageBytes = Files.readAllBytes(Paths.get("diagram.png"));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);

UserMessage message = UserMessage.from(
    ImageContent.from("data:image/png;base64," + base64Image),
    TextContent.from("请分析这个架构图")
);

String analysis = visionModel.generate(message);

4.4 图像处理流程图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                   图像处理流程                                  │
└─────────────────────────────────────────────────────────────┘

┌─────────┐    ┌──────────────┐    ┌─────────────┐    ┌───────┐
│  图像源  │ -> │ ImageContent │ -> │ UserMessage │ -> │  GPT-4 │
│  URL/   │ -> │  创建        │ -> │  构建图文    │ -> │  Vision │
│  Base64 │ -> │              │ -> │  混合消息    │ -> │  API   │
└─────────┘    └──────────────┘    └─────────────┘    └───────┘
    │                │                  │               │
    │ 1. 加载图像     │ 2. 创建          │ 3. 构建消息   │ 4. 视觉
    │               ImageContent       UserMessage    │    理解
    └────────────────┴──────────────────┴───────────────┘
                           │
                    5. 返回文字描述
                    6. 分析图像内容

支持的操作:
- 图像描述(Image Captioning)
- OCR 文字识别
- 图表分析
- 代码截图解释
- 图像对比

五、完整实战示例

5.1 智能客服系统

java 复制代码
@AiService
public interface CustomerServiceAssistant {
    
    // 查询订单
    @Tool("查询订单状态")
    String queryOrder(@P("订单号") String orderId);
    
    // 退换货
    @Tool("处理退换货请求")
    String processReturn(
        @P("订单号") String orderId,
        @P("退换货原因") String reason
    );
    
    // 聊天
    String chat(@UserMessage String message);
}

public class CustomerServiceSystem {
    
    private final CustomerServiceAssistant assistant;
    
    public CustomerServiceSystem() {
        OpenAiChatModel model = OpenAiChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .modelName("gpt-4o")
                .responseFormat("json_object")  // JSON Mode
                .build();
        
        this.assistant = AiServices.builder(CustomerServiceAssistant.class)
                .chatLanguageModel(model)
                .tools(new OrderTools(), new ReturnTools())
                .build();
    }
    
    public String handleCustomerRequest(String message) {
        return assistant.chat(message);
    }
}

// 使用
CustomerServiceSystem system = new CustomerServiceSystem();

// 场景 1:查询订单
String response1 = system.handleCustomerRequest("查询订单号 123456");
// AI 会自动调用 queryOrder("123456")

// 场景 2:退换货
String response2 = system.handleCustomerRequest(
    "我要退货,订单号 123456,原因是商品有瑕疵"
);
// AI 会自动调用 processReturn("123456", "商品有瑕疵")

// 场景 3:普通聊天
String response3 = system.handleCustomerRequest("你们的工作时间是什么?");
// AI 直接回答

六、常见问题

Q1: Function Calling 失败怎么办?

A: 检查以下几点:

java 复制代码
// 1. 确保 @Tool 注解描述清晰
@Tool("查询天气,参数为城市名称(中文或英文)")
String getWeather(String city);

// 2. 使用 @P 注解描述参数
@Tool("创建订单")
String createOrder(
    @P("商品名称,必填") String productName,
    @P("数量,必填,正整数") int quantity
);

// 3. 检查模型是否支持工具调用
OpenAiChatModel.builder()
    .modelName("gpt-4")  // gpt-4 和 gpt-3.5-turbo 支持
    .build();

Q2: JSON Mode 返回非 JSON 怎么办?

A: LangChain4j 会自动重试,也可以手动修复:

java 复制代码
AiServices.builder(Assistant.class)
    .chatLanguageModel(model)
    .jsonRepairStrategy(JsonRepairStrategy.AUTO_FIX)
    .build();

Q3: 如何处理图像中的文字识别?

A: 使用 GPT-4 Vision 的 OCR 能力:

java 复制代码
UserMessage message = UserMessage.from(
    ImageContent.from("screenshot.png"),
    TextContent.from("请识别图片中的所有文字")
);

String text = visionModel.generate(message);

七、小结

本文深入介绍了 LangChain4j 与 OpenAI 的深度集成,包括:

  1. Function Calling:@Tool 注解、参数映射、并行执行
  2. JSON Mode:强制 JSON 输出、Schema 验证、结构化数据提取
  3. Assistants API:创建 Assistant、Thread 管理、文件操作
  4. 图像输入:单图/多图输入、Base64 编码、视觉理解
  5. 完整实战:智能客服系统集成

核心思想: 通过 LangChain4j 的抽象层,无缝使用 OpenAI 的所有高级特性。

下一步学习:

  • 文章 6:《LangChain4j 本地模型与 Ollama:私有化部署的零成本方案》

参考文献:

相关推荐
luckyzlb14 小时前
01-milvus
ai·milvus·spring ai·langchain4j·springaialibaba
洛阳泰山20 小时前
开源智能体搭建平台MaxKB4j 技术文档
java·开源·llm·springboot·agent·rag·langchain4j
猫吻鱼2 天前
【LangChain4j 06】【结构化输出】
langchain4j
猫吻鱼4 天前
【LangChain4j 05】【RAG】
langchain4j
长路 ㅤ   22 天前
05、LangChain4j快速对接生图模型(百炼平台、智谱)
java开发·通义万相·智谱glm·langchain4j·ai生图
长路 ㅤ   25 天前
Milvus系列之02、Spring+Milvus实现RAG检索增强
向量数据库·apache tika·langchain4j·知识库构建·hanlp分词
长路 ㅤ   25 天前
适配AI平台的HTTP插件系统设计
langchain4j·ai插件系统·http工具调用·语雀知识库·coze插件设计
马克Markorg1 个月前
SpringBoot + LangChain4j 打造企业级 RAG 智能知识库,多工具集成方案
spring boot·向量数据库·rag·qdrant·langchain4j·增强知识检索库
长路 ㅤ   1 个月前
长路的AI领域技术博客汇总文档
向量数据库·大模型部署·langchain4j·智能体agent·ai后端技术