1,定义工具注解类:
1.1
- package com.jinhei;
-
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- /**
- * 工具方法注解
- * 用于标识一个方法为 AI 工具, 使其能够被 AI 助手调用
- */
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Tool {
- /**
- * 工具方法的描述信息
- * 用于向 AI 助手说明该方法的功能
- * @return 方法的描述
- */
- String description();
- }
复制代码 1.2
- package com.jinhei;
-
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- /**
- * 工具参数注解
- * 用于标识工具的方法的参数, 提供参数的描述信息
- * 帮助 AI 助手理解每个参数的用途
- */
- @Target(ElementType.PARAMETER)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface ToolParam {
- /**
- * 参数的描述信息
- * 用于向 AI 助手说明该参数的含义和用途
- * @return 参数的描述
- */
- String description();
-
- }
复制代码 2,定义代理工具类:
- package com.jinhei;
-
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import java.io.FileWriter;
- import java.io.IOException;
-
- /**
- * 代理工具类 - 为AI提供可调用的功能
- */
- public class AgentTools {
- // JSON解释器 - 用来读懂JSON格式的数据
- private final ObjectMapper objectMapper = new ObjectMapper();
-
- /**
- * 将制定内容写入到本地文件中
- * @param jsonInput 包含 'filePath' 和 'content' 的 JSON 字符串
- * @return 执行结果
- */
- @Tool(description = "将指定内容写入本地文件") //这个注解告诉 AI , 这是一个可用的工具
- public String putFile(@ToolParam(description = "包含 'filePath' 和 'content' 的 JSON 字符串") String jsonInput) {
- //第一步: 尝试执行写文件操作(就像尝试完成一项任务)
- try {
- //1.1 解析JSON输入: 读懂"文件保存单"
- //把json字符串解析成树形结构, 方便提取数据
- JsonNode rootNode = objectMapper.readTree(jsonInput);
-
- //提取文件路径: 从"文件保存单"上面找到"保存位置"这一项
- String filePath = rootNode.get("filePath").asText();
-
- //提取文件内容: 从"文件保存单"上面找到"文件内容"这一项
- String content = rootNode.get("content").asText();
-
- //1.2执行写文件: 真正的把内容写到磁盘上
- try (FileWriter writer = new FileWriter(filePath)) {
- //把内容写到文件中
- writer.write(content);
- //成功!告诉AI任务完成了
- return String.format("成功将内容写入文件 '%s'", filePath);
- } catch (IOException e) {
- //写文件失败(比如磁盘没有权限或者磁盘满了等等)
- return String.format("写入文件 '%s' 时发生错误: '%s'", filePath, e.getMessage());
- }
-
- } catch (Exception e) {
- //解析json失败 (比如: AI给的格式不对, 缺少必要的字段)
- return String.format("解析 Action input 或执行 putFile 工具时出错: %s", e.getMessage());
- }
-
-
- }
-
-
- }
复制代码 3,工具操作说明:
- package com.jinhei;
-
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * 工具说明书 - 负责提取和格式化工具信息
- */
- public class ToolUtil {
-
- /**
- * 获取工具类的描述信息
- *
- * 这个方法会扫描传入的类,找出所有带有@Tool注解的方法,
- * 然后把这些工具的信息整理成格式化的文字描述。
- *
- * 就像打开一个工具箱,把里面每个工具的名称、用途、使用方法
- * 都记录下来,写成一份"工具使用说明书"
- *
- * @param clazz 要扫描的工具类(比如 AgentTools.class)
- * @return 格式化后的工具描述文本,供AI理解使用
- */
- public static String getToolDescription(Class<?> clazz) {
- //第一步: 准备容器 - 用来存放收集到的工具信息
- List<String> toolNameList = new ArrayList<>();
-
- //存储每个工具的完整描述(格式化后的文本)
- List<String> formattedToolList = new ArrayList<>();
-
- //第二步: 扫描类中的所有方法
- for (Method declaredMethod : clazz.getDeclaredMethods()) {
- //2.1检查方法是否有@Tool注解
- if (declaredMethod.isAnnotationPresent(Tool.class)) {
- //2.2 获取工具的注解信息
- // 作用:获取方法上的整个@Tool注解对象
- // 返回:一个完整的注解对象,包含所有属性
- Tool toolAnnotation = declaredMethod.getAnnotation(Tool.class);
-
- //获取工具的名称
- String toolName = declaredMethod.getName();
-
- //获取工具的描述
- // 作用:从注解对象中提取description属性的值
- // 返回:具体的字符串描述
- String toolDescription = toolAnnotation.description();
-
- //获取参数的描述
- String paramDescription = declaredMethod.getParameters()[0]
- .getAnnotation(ToolParam.class)
- .description();
-
- //2.3格式化工具信息
- String formattedTool = String.format(
- "- toolName=%s, toolDescription=%s, paramDescription=%s",
- toolName, toolDescription, paramDescription
- );
-
- //2.4 存储到容器中
- formattedToolList.add(formattedTool);
- toolNameList.add(toolName);
- }
- }
-
- //第三步: 拼接最终结果
- //3.1 将所有的工具描述用换行符拼接起来
- String formattedTools = String.join("/n/n", formattedToolList);
-
- //3.2将所有工具名称用逗号拼接起来
- String toolNames = String.join(",", toolNameList);
-
- //第四步: 输出一下调试信息
- // System.out.println(formattedTools);
- // System.out.println(toolNames);
-
- //第五步: 返回格式化后的工具描述
- return formattedTools;
- }
-
- public static void main(String[] args) {
- getToolDescription(AgentTools.class);
- }
-
-
- }
复制代码 4,测试工具:
- package com.jinhei;
-
- import com.alibaba.fastjson2.JSONObject;
- import com.openai.client.OpenAIClient;
- import com.openai.client.okhttp.OpenAIOkHttpClient;
- import com.openai.models.chat.completions.ChatCompletion;
- import com.openai.models.chat.completions.ChatCompletionCreateParams;
-
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.HashMap;
-
- /**
- * 调用模型
- */
- public class AiChat {
- private static final String TEMPLATE = """
- 你是一位能力强大的 AI 助手,擅长通过逻辑推理与调用工具来解决问题。
- 你可以使用的工具如下:
- {tools}
- **重要: 你必须严格按照以下 JSON 格式返回工具调用请求: **
- ```json
- {
- "toolName": "工具名称",
- "params": "{参数 JSON 字符串}"
- }
- ```
-
- 注意:
- 1. 只能返回上述 JSON 格式, 不要添加任何解释文字
- 2. params 字段必须是字符串格式的 JSON
- 3. 不要使用markdown 代码块标记
- 当前用户的问题是:
- {input}
- """;
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
- //第0步: 准备工作 - 注册可用的工具
- HashMap<String, Method> tools = new HashMap<>();
- // 获取AgentTools类中的putFile方法。第一个参数是方法名,第二个参数是该方法的参数类型(String)。返回一个Method对象,用于后续动态调用该方法或获取其注解信息。
- tools.put("putFile", AgentTools.class.getMethod("putFile", String.class));
-
- //第1步: 创建AI客户端 - 建立与AI服务的连接通道
- OpenAIClient aiClient = OpenAIOkHttpClient.builder()
- .apiKey(AiConfig.API_KEY) //设置API密钥
- .baseUrl(AiConfig.BASE_URL) //设置服务地址
- .build();//建造完成
-
- //第2步: 准备要问的问题
- //2.1用户的实际问题
- String promptString = "将1+1的结果写到文件中, 文件名为haha.txt";
-
- //2.2 替换模板中的工具占位符
- String prompt = TEMPLATE.replace("{tools}", ToolUtil.getToolDescription(AgentTools.class));
-
- //2.3替换模板中的用户问题占位符
- prompt = prompt.replace("{input}", promptString);
-
- //第3步: 构建请求参数 - 把问题打包成AI能理解的格式
- ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
- .addUserMessage(prompt) //添加用户消息: 你说的话
- .model(AiConfig.LLM_NAME) //指定用哪个AI大模型来处理
- .build();//打包完成 - 准备发送
-
- //第4步: 发送请求并获取回复 - 把信寄出去, 等待回信
- ChatCompletion chatCompletion = aiClient.chat() //打开聊天功能
- .completions() //开启补全模式(AI回复)
- .create(params); //发送请求并等待响应
-
- //第5步: 提取AI的回答 - 拆开回信, 取出内容
- //5.1 获取AI返回的原始信息
- String message = chatCompletion.choices().get(0).message().content().get();
- System.out.println(message);
- //5.2清理消息格式
- // message = message.replace("```tool_code", "");
- // message = message.replace("```", "");
- // message = message.replace("```json", "");
-
- System.out.println(message);
- //5.3解析JSON
- JSONObject jsonObject = JSONObject.parseObject(message);
-
- //获取工具的名称
- String toolName = jsonObject.getString("toolName");
- System.out.println(toolName);
- String toolParams = jsonObject.getString("params");
- System.out.println(toolParams);
-
- //第6步: 执行工具调用
- //6.1 从工具注册表中找到对应的方法
- Method toolMethod = tools.get(toolName);
-
- //6.2创建工具实例并且执行方法
- Object result = toolMethod.invoke(new AgentTools(), toolParams);
-
- //第7步: 显示结果
- System.out.println(result);
-
- }
-
- }
复制代码 5,引入依赖
- <!-- 解析JSON -->
- <dependency>
- <groupId>com.alibaba.fastjson2</groupId>
- <artifactId>fastjson2</artifactId>
- <version>2.0.56</version>
- </dependency>
复制代码 6,写入文件:
- package com.jinhei;
-
- import com.alibaba.fastjson2.JSONObject;
- import com.openai.client.OpenAIClient;
- import com.openai.client.okhttp.OpenAIOkHttpClient;
- import com.openai.models.chat.completions.ChatCompletion;
- import com.openai.models.chat.completions.ChatCompletionCreateParams;
-
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.HashMap;
-
- /**
- * 调用模型
- */
- public class AiChat {
- private static final String TEMPLATE = """
- 你是一位能力强大的 AI 助手,擅长通过逻辑推理与调用工具来解决问题。
- 你可以使用的工具如下:
- {tools}
- **重要: 你必须严格按照以下 JSON 格式返回工具调用请求: **
- ```json
- {
- "toolName": "工具名称",
- "params": "{参数 JSON 字符串}"
- }
- ```
-
- 注意:
- 1. 只能返回上述 JSON 格式, 不要添加任何解释文字
- 2. params 字段必须是字符串格式的 JSON
- 3. 不要使用markdown 代码块标记
- 当前用户的问题是:
- {input}
- """;
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
- //第0步: 准备工作 - 注册可用的工具
- HashMap<String, Method> tools = new HashMap<>();
- // 获取AgentTools类中的putFile方法。第一个参数是方法名,第二个参数是该方法的参数类型(String)。返回一个Method对象,用于后续动态调用该方法或获取其注解信息。
- tools.put("putFile", AgentTools.class.getMethod("putFile", String.class));
-
- //第1步: 创建AI客户端 - 建立与AI服务的连接通道
- OpenAIClient aiClient = OpenAIOkHttpClient.builder()
- .apiKey(AiConfig.API_KEY) //设置API密钥
- .baseUrl(AiConfig.BASE_URL) //设置服务地址
- .build();//建造完成
-
- //第2步: 准备要问的问题
- //2.1用户的实际问题
- String promptString = "将1+1的结果写到文件中, 文件名为haha.txt";
-
- //2.2 替换模板中的工具占位符
- String prompt = TEMPLATE.replace("{tools}", ToolUtil.getToolDescription(AgentTools.class));
-
- //2.3替换模板中的用户问题占位符
- prompt = prompt.replace("{input}", promptString);
-
- //第3步: 构建请求参数 - 把问题打包成AI能理解的格式
- ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
- .addUserMessage(prompt) //添加用户消息: 你说的话
- .model(AiConfig.LLM_NAME) //指定用哪个AI大模型来处理
- .build();//打包完成 - 准备发送
-
- //第4步: 发送请求并获取回复 - 把信寄出去, 等待回信
- ChatCompletion chatCompletion = aiClient.chat() //打开聊天功能
- .completions() //开启补全模式(AI回复)
- .create(params); //发送请求并等待响应
-
- //第5步: 提取AI的回答 - 拆开回信, 取出内容
- //5.1 获取AI返回的原始信息
- String message = chatCompletion.choices().get(0).message().content().get();
- System.out.println(message);
- //5.2清理消息格式
- // message = message.replace("```tool_code", "");
- // message = message.replace("```", "");
- // message = message.replace("```json", "");
-
- System.out.println(message);
- //5.3解析JSON
- JSONObject jsonObject = JSONObject.parseObject(message);
-
- //获取工具的名称
- String toolName = jsonObject.getString("toolName");
- System.out.println(toolName);
- String toolParams = jsonObject.getString("params");
- System.out.println(toolParams);
-
- //第6步: 执行工具调用
- //6.1 从工具注册表中找到对应的方法
- Method toolMethod = tools.get(toolName);
-
- //6.2创建工具实例并且执行方法
- Object result = toolMethod.invoke(new AgentTools(), toolParams);
-
- //第7步: 显示结果
- System.out.println(result);
-
- }
-
- }
复制代码
aiagent.zip
(12.37 KB, 下载次数: 0, 售价: 50 金豆)
|