如果我们想要对一些敏感信息进行针对化的操作,不仅仅是接口大模型去进行回复。
比如我们现在数据库里面有一些菜品,那么用户提问,店里有多少套餐,那么云端大模型肯定是不知道的,我们希望捕获这些关键字然后进行自己的业务查询或者处理,这个时候就可以使用function-call
- 注意: qwq-32b,deepseek不支持(deepseek-v3支持)
使用流程:
- 问大模型:店铺有多少套餐
- 大模型识别出问题,提取倒关键字“xx”店铺,“套餐”
- 大模型就会调用写好的方法
- 将方法的结果,并结合上下文请求搭建模型
- 大模型响应
编写一工具类
服务类是基于 langchain4j 框架实现的工具调用服务
- 通过 @Service 注解被 Spring 容器管理
- 使用 @Tool 注解标记可被 AI 调用的方法,AI 会根据工具描述决定何时调用这些方法
- @P(“地区”) 和 @P(“姓名”) 用于标注方法参数的语义,帮助 AI 理解需要提取的信息(如用户输入中的地区和姓名)
package com.yd.langchain4j_springboot.service;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Service;
@Service
public class ToolsService {
// 告诉AI 什么对话才调用这个方法
@Tool("某个地区有多少个名字的")
public Integer changshaNameCount(
@P("地区")
String location,
// 告诉AI 需要提取的信息
@P("姓名")
String name){
// todo...
System.out.println(name);
System.out.println(location);
// 结果
return 10;
}
@Tool("退票")
public String cancelBooking(
@P("订单号")
String bookingNumber,
// 告诉AI 需要提取的信息
@P("姓名")
String name){
// todo... 业务方法,退票数据库操作
System.out.println(name);
System.out.println(bookingNumber);
// 结果
return "退票成功";
}
}
AiConfig
通过 tools(toolsService) 将该服务注入 AI 助手配置
Assistant assistant = AiServices.builder(Assistant.class)
.tools(toolsService) // 关键集成点
// 其他配置...
.build();
@Configuration
public class AiConfig{
//支持多用户独立对话的助手接口
public interface AssistantUnique{
// 使用@MemoryId注解区分不同用户的对话历史
String chat(@MemoryId int memoryId,@UserMessage String message);
TokenStream stream(@MemoryId int memoryId,@UserMessage String message);
}
@Bean
public AssistantUnique assistantUnique(ChatLanguageModel qwenChatModel,
StreamingChatLanguageModel qwenStreamingChatModel,
ToolsService toolsService) {
AssistantUnique assistant = AiServices.builder(AssistantUnique.class)
.tools(toolsService)
.chatLanguageModel(qwenChatModel)
.streamingChatLanguageModel(qwenStreamingChatModel)
//根据传入的 memoryId 来创建或获取对应的 ChatMemory 实例
.chatMemoryProvider(memoryId->
MessageWindowChatMemory.builder()
.maxMessages(10)
.id(memoryId)
.build()
)
.build();
return assistant;
}
}
效果
系统预设角色
基础大模型是没有目的性的
如果我们开发的是一个智能票务助手, 需要它以票务助手的角色跟我对话,可以通过以下设置
@SystemMessage 注解
langchain4j 框架,用于定义 AI 助手的角色、行为准则和上下文信息
@V 注解
- 注入系统变量(如当前日期、时间)
- 传递上下文参数(如用户 ID、会话 ID)
- 在系统提示中实现动态
- 内容替换
AiConfig
//支持多用户独立对话的助手接口
public interface AssistantUnique{
// 使用@MemoryId注解区分不同用户的对话历史
String chat(@MemoryId int memoryId,@UserMessage String message);
TokenStream stream(@MemoryId int memoryId,@UserMessage String message);
// 带系统提示和动态参数的流式响应
// 带系统提示的流式响应方法(取消注释并正确应用注解)
@SystemMessage("""
您是“Tuling”航空公司的客户聊天支持代理。请以友好、乐于助人且愉快的方式来回复。
您正在通过在线聊天系统与客户互动。
在提供有关预订或取消预订的信息之前,您必须始终从用户处获取以下信息:预订号、客户姓名。
请讲中文。
今天的日期是 {{currentDate}}.
""")
String chat(
@MemoryId int memoryId,
@UserMessage String message,
@V("currentDate") String currentDate
);
}
@Bean
public AssistantUnique assistantUnique(ChatLanguageModel qwenChatModel,
StreamingChatLanguageModel qwenStreamingChatModel,
ToolsService toolsService) {
AssistantUnique assistant = AiServices.builder(AssistantUnique.class)
// .tools(toolsService)将tool注释避免function-call的作用
.chatLanguageModel(qwenChatModel)
.streamingChatLanguageModel(qwenStreamingChatModel)
//根据传入的 memoryId 来创建或获取对应的 ChatMemory 实例
.chatMemoryProvider(memoryId->
MessageWindowChatMemory.builder()
.maxMessages(10)
.id(memoryId)
.build()
)
.build();
return assistant;
}
Controller
我们定义一个新的controller
@RequestMapping(value = "/memoryId_chat")
public String memoryChat(@RequestParam(defaultValue="我是谁") String message, Integer userId) {
return assistantUnique.chat(userId,message);
}
@RequestMapping(value = "/memoryId_chat_SystemMessage")
public String memoryChatSystemMessage(@RequestParam(defaultValue = "1") int userId,
@RequestParam(defaultValue = "我是谁") String message,
@RequestParam(defaultValue = "2025-07-02") String currentDate) {
return assistantUnique.chat(userId,message,currentDate);
}
效果
-
首先进行普通记忆接口memoryId_chat访问,询问今天日期和角色,得到的并非正确
-
进行预设询问memoryId_chat_SystemMessage接口
-
再使用普通接口memoryId_chat,也将会有之前的记忆