找回密码
 立即注册

5,飞机大战实战

[复制链接]
admin 发表于 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. import java.util.List;
  11. /**
  12. * 调用模型对话
  13. */
  14. public class AiChat {
  15.     private static final String TEMPLATE = """
  16.             你是一位能力强大的 AI 助手,擅长通过逻辑推理与调用工具来解决问题。
  17.             
  18.             你可以使用的工具如下:
  19.             {tools}
  20.             
  21.             **重要:你必须严格按照以下 JSON 格式返回工具调用请求:**
  22.             ```json
  23.             {
  24.               "toolName": "工具名称",
  25.               "params": "{参数 JSON 字符串}"
  26.             }
  27.             ```
  28.             
  29.             注意:
  30.             1. 只能返回上述 JSON 格式,不要添加任何解释文字
  31.             2. params 字段必须是字符串格式的 JSON
  32.             3. 不要使用代码块标记
  33.             
  34.             对话历史:
  35.             {memory}
  36.             
  37.             当前用户的问题是:
  38.             {input}
  39.             """;
  40.     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  41.         // 第0步:准备工作 - 注册可用的工具
  42.         // 创建一个工具注册表(就像一个工具箱),记录每个工具的名称和对应的方法
  43.         // key: 工具名称(AI调用时使用)
  44.         // value: 实际执行的Java方法(反射调用)
  45.         // 通俗理解:建立一张"工具对照表"
  46.         // 当AI说"我要用putFile工具"时,程序就知道要调用AgentTools类的putFile方法
  47.         HashMap<String, Method> tools = new HashMap<>();
  48.         tools.put("putFile", AgentTools.class.getMethod("putFile", String.class));
  49.         tools.put("getFile", AgentTools.class.getMethod("getFile", String.class));
  50.         tools.put("batchPutFile", AgentTools.class.getMethod("batchPutFile", String.class));
  51.         // 第 0.5 步:创建记忆管理器 - 加载长期记忆
  52.         MemoryManager memoryManager = new MemoryManager();
  53.         System.out.println(memoryManager.getMemoryStats());
  54.         //第1步:创建AI客户端 - 建立与AI服务的连接通道
  55.         OpenAIClient aiClient = OpenAIOkHttpClient.builder()
  56.                 .apiKey(AiConfig.API_KEY)      // 设置身份证(API密钥)
  57.                 .baseUrl(AiConfig.BASE_URL)    // 设置对方地址(服务地址)
  58.                 .build();                       // 建造完成,电话接通
  59.         //第 2 步:准备要问的问题 - 编写聊天内容
  60.         // 2.1 用户的实际问题(原始输入)
  61. //         String promptString = "批量创建 3 个文件到 D:\\ 中,分别是 a.txt 内容为 Hello A, b.txt 内容为 Hello B, c.txt 内容为 Hello C";
  62. //        String promptString = "读取 D:\\a.txt 文件的内容";  // 这个问题 AI 会直接回答,不需要调用工具
  63. //        String promptString = "我之前都让你干了哪些事情";  // 这个问题 AI 会直接回答,不需要调用工具
  64.         String promptString = "请帮我写一个完整的飞机大战 Java 游戏,包含以下功能:\n" +
  65.                 "1. 玩家飞机可以用方向键或 WASD 移动\n" +
  66.                 "2. 空格键发射子弹\n" +
  67.                 "3. 敌机会从屏幕上方随机出现并向下移动\n" +
  68.                 "4. 子弹击中敌机会产生爆炸效果并加分\n" +
  69.                 "5. 敌机撞到玩家则游戏结束\n" +
  70.                 "6. 显示分数和等级\n" +
  71.                 "7. 飞机形状,敌机下落速度均匀,不要出现一快慢\n" +
  72.                 "\n" +
  73.                 "请将所有代码保存到一个文件中。";
  74.         // 2.1.5 记录用户消息到记忆中
  75.         memoryManager.addUserMessage(promptString);
  76.         // 2.2 替换模板中的工具占位符
  77.         // ToolUtil.getToolDescription(AgentTools.class) 会返回 AgentTools 类中所有工具的说明
  78.         // 就像把“工具箱清单”填写到工作流程说明书中
  79.         // 告诉 AI:你能用的工具有“写文件”、“读文件”等等...
  80.         String prompt = TEMPLATE.replace("{tools}", ToolUtil.getToolDescription(AgentTools.class));
  81.         // 2.2.5 获取最近的记忆并替换到模板中
  82.         // 这样 AI 就能记住之前的对话内容
  83.         String memoryContext = buildMemoryContext(memoryManager.getRecentMemories(10));
  84.         prompt = prompt.replace("{memory}", memoryContext);
  85.         // 2.3 替换模板中的用户问题占位符
  86.         // 把用户的具体问题填进去
  87.         // 就像告诉AI:"这是你要完成的具体任务"
  88.         prompt = prompt.replace("{input}", promptString);
  89.         //第3步:构建请求参数 - 把问题打包成AI能理解的格式
  90.         ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
  91.                 .addUserMessage(prompt)           // 添加用户消息:你说的话
  92.                 .model(AiConfig.LLM_NAME)         // 指定用哪个AI大脑来处理
  93.                 .build();                          // 打包完成,准备发送
  94.         //第4步:发送请求并获取回复 - 把信寄出去,等待回信
  95.         ChatCompletion chatCompletion = aiClient.chat()      // 打开聊天功能
  96.                 .completions()   // 开启补全模式(AI回复)
  97.                 .create(params); // 发送请求并等待响应
  98.         // 第5步:提取AI的回答 - 拆开回信,取出内容
  99.         // 5.1 获取AI返回的原始消息
  100.         String message = chatCompletion.choices().get(0).message().content().get();
  101.         // 5.2 清理消息格式 - 移除 markdown 代码块标记和多余文字
  102.         // AI 可能把工具调用放在代码块中,我们需要提取出纯 JSON
  103.         // 例如:将 ```tool_code {...} ``` 转换成 {...}
  104.         message = message.replace("```tool_code", "");
  105.         message = message.replace("```json", "");
  106.         message = message.replace("```", "");
  107.         // 尝试提取第一个 { 到最后一个 } 之间的内容(处理 AI 添加解释文字的情况)
  108.         int firstBrace = message.indexOf('{');
  109.         int lastBrace = message.lastIndexOf('}');
  110.         if (firstBrace != -1 && lastBrace != -1 && lastBrace > firstBrace) {
  111.             message = message.substring(firstBrace, lastBrace + 1);
  112.         }
  113.         // 5.3 解析 JSON - 理解 AI 想要调用哪个工具
  114.         // 将清理后的字符串解析成 JSON 对象,提取工具名称和参数
  115.         // 就像读懂 AI 写的"工具使用申请单"
  116.         JSONObject jsonObject = null;
  117.         try {
  118.             jsonObject = JSONObject.parseObject(message);
  119.             // 检查是否是有效的工具调用格式(必须包含 toolName 和 params)
  120.             String toolName = jsonObject.getString("toolName");
  121.             String toolParams = jsonObject.getString("params");
  122.             if (toolName == null || toolParams == null) {
  123.                 // 格式不对,说明不是工具调用
  124.                 jsonObject = null;
  125.             }
  126.         } catch (Exception e) {
  127.             // 解析失败,说明 AI 返回的不是 JSON,而是直接回答
  128.             System.out.println("\n[AI 直接回复]\n" + message);
  129.             // 记录 AI 的回复到记忆中(没有工具调用)
  130.             memoryManager.addAssistantMessage(message, null, null);
  131.             memoryManager.saveMemories();
  132.             System.out.println(memoryManager.getMemoryStats());
  133.             return; // 直接结束,不执行工具调用
  134.         }
  135.         // 能到这里说明是有效的工具调用
  136.         String toolName = jsonObject.getString("toolName");
  137.         String toolParams = jsonObject.getString("params");
  138.         // 第 6 步:执行工具调用 - 根据 AI 的指令实际操作
  139.         // 6.1 从工具注册表中找到对应的方法
  140.         // 就像根据工具名称从工具箱里取出对应的工具
  141.         Method toolMethod = tools.get(toolName);
  142.         // 6.2 创建工具实例并执行方法
  143.         // 通过反射调用工具方法,就像启动机器开始干活
  144.         // new AgentTools():创建工具对象(准备干活)
  145.         // toolMethod.invoke():执行具体方法(开始干活)
  146.         // toolParams:传入参数(告诉工具要怎么做)
  147.         Object result = toolMethod.invoke(new AgentTools(), toolParams);
  148.         // 第 7 步:显示结果 - 把工具执行的结果打印出来
  149.         System.out.println(result);
  150.         // 第 8 步:保存记忆 - 将本次对话记录保存到长期记忆中
  151.         // 重要:记录自然语言总结,而不是工具调用 JSON
  152.         String assistantSummary = buildAssistantSummary(toolName, result.toString());
  153.         memoryManager.addAssistantMessage(assistantSummary, toolName, result.toString());
  154.         memoryManager.saveMemories();
  155.         System.out.println(memoryManager.getMemoryStats());
  156.     }
  157.     /**
  158.      * 构建 AI 回复的自然语言总结
  159.      * @param toolName 工具名称
  160.      * @param toolResult 工具执行结果
  161.      * @return 自然语言总结
  162.      */
  163.     private static String buildAssistantSummary(String toolName, String toolResult) {
  164.         if ("putFile".equals(toolName)) {
  165.             return "使用写文件工具创建了文件";
  166.         } else if ("getFile".equals(toolName)) {
  167.             return "使用读文件工具读取了文件内容";
  168.         } else if ("batchPutFile".equals(toolName)) {
  169.             // 从结果中提取文件信息
  170.             StringBuilder summary = new StringBuilder("批量创建了以下文件:");
  171.             String[] lines = toolResult.split("\\n");
  172.             for (String line : lines) {
  173.                 if (line.contains("成功写入")) {
  174.                     // 提取文件名
  175.                     int start = line.indexOf("D:");
  176.                     if (start != -1) {
  177.                         String filePath = line.substring(start).trim();
  178.                         summary.append(filePath).append("、");
  179.                     }
  180.                 }
  181.             }
  182.             // 移除最后一个顿号
  183.             if (summary.length() > 0 && summary.charAt(summary.length() - 1) == '、') {
  184.                 summary.setLength(summary.length() - 1);
  185.             }
  186.             return summary.toString();
  187.         }
  188.         return "调用了工具:" + toolName;
  189.     }
  190.     /**
  191.      * 构建记忆上下文字符串
  192.      * @param memories 记忆列表
  193.      * @return 格式化的记忆文本
  194.      */
  195.     private static String buildMemoryContext(List<MemoryManager.MemoryEntry> memories) {
  196.         if (memories.isEmpty()) {
  197.             return "(暂无历史对话)";
  198.         }
  199.         StringBuilder context = new StringBuilder();
  200.         for (MemoryManager.MemoryEntry entry : memories) {
  201.             String roleText = "user".equals(entry.getRole()) ? "用户" : "AI";
  202.             context.append(String.format("[%s] %s: %s\n",
  203.                     entry.getTimestamp(), roleText, entry.getContent()));
  204.             // 如果有工具调用信息,也加上
  205.             if (entry.getToolName() != null) {
  206.                 context.append(String.format("  → 使用工具:%s\n", entry.getToolName()));
  207.             }
  208.             if (entry.getToolResult() != null) {
  209.                 context.append(String.format("  → 工具结果:%s\n", entry.getToolResult()));
  210.             }
  211.         }
  212.         return context.toString();
  213.     }
  214. }
复制代码
aiagent.zip (22.01 KB, 下载次数: 0, 售价: 50 金豆)

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

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

Powered by Www.Jinhei.Cn

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

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