找回密码
 立即注册

2,工具调用

[复制链接]
admin 发表于 4 天前 | 显示全部楼层 |阅读模式
1,定义工具注解类:

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

aiagent.zip (12.37 KB, 下载次数: 0, 售价: 50 金豆)

QQ|网站地图|Archiver|小黑屋|金黑网络 ( 粤ICP备2021124338号 )

网站建设,微信公众号小程序制作,商城系统开发,高端系统定制,app软件开发,智能物联网开发,直播带货系统等

Powered by Www.Jinhei.Cn

Copyright © 2013-2024 深圳市金黑网络技术有限公司 版权所有

快速回复 返回顶部 返回列表