分类: 未分类

  • LLM群星闪耀时 – AI应用开发踩坑记录

    其一:Tool Call格式输出不对

    LLM并不总是能输出正确的JSON格式,有的时候会写错格式,而且错得很离谱(比如在双引号外面打一个甚至两个转义符,破坏格式),导致Tool Call参数没办法被正常反序列化,产生报错(例如Gson的JsonSyntaxException),没原地catch掉还会一层一层往回抛,导致逻辑意外中断。
    解决办法貌似也只有观察LLM输出的错误格式,有没有错得相似的地方,给修正回去再反序列化。更多时候,模型连格式都写不对大不了换一个算了。以及,基于对LLM“概率推测”原理的考量,还是需要解析LLM输出的参数的时候,及时捕获错误,防止程序出现意料之外的行为。

    其二:输出正文不按照要求格式输出

    我发现这个问题的场景是 长上下文 加 单智能体多任务职能,我要求一个智能体从网上抓取数据,然后要求它按照固定格式分条目输出格式化的内容,后面代码再解析处理。结果LLM基本没输出过正确的格式。因为长上下文会分散LLM的注意力,不同模型的注意力也不一致。

    所以我尝试分智能体解决的这个问题。一个智能体负责抓取并总结(貌似这也更加符合LLM的本能……哈哈),第二个智能体才根据前一个智能体获得的干净内容,整理成格式化内容输出,给程序处理。貌似效果挺不错,大幅缩短了上下文,使第二个智能体的注意力得以集中在格式化的任务,任务完成率也高了很多

    其三:UUID照着抄都抄不对

    好吧这里就还挺无语的,之前一直都知道,LLM的行为不稳定,但没意识到抄UUID也未必总是能抄对。
    比如,我输入一些数据,数据用UUID编了号,要求LLM用编号在输出中引用到这些数据。
    因为UUID确实比较长,所以相较于数字,本来也就更容易抄错。UUID的tokens长度也比数字长很多,假设LLM在这一块输出正确tokens的概率是99%,那么一个UUID被写对的概率只有90%,而输数字的正确概率就是99%。毕竟LLM训练的时候,一定见过1. 2. 3. 4. 5.,但是一定没见过随机生成出来的UUID。所以,让LLM引用东西的时候,最好临时重新编号一下,做一个数字到UUID的映射,让AI通过数字引用数据,正确率更高,也更省tokens

    自己开发过程遇到的比较反直觉的暂时只有这么多,之后再遇到再补充补充。

  • 末屿宇宙 – 通过 Spigot 插件在 Minecraft 聊天框显示低清图片

    以方块字符作为像素点显示图片

    优点:可以不离开 Minecraft 界面,通过缩略图,大概判断群聊中图片的内容,从而提升游戏内外沟通效率。
    缺点:分辨率真的很低(

    https://github.com/Ylkawa/MoyuUniverse/blob/1e673e440c11d1e3a39ad6bb5402a0cb86a98a84/Minecraft-Connect/src/main/java/com/nekoyu/Universe/MinecraftConnect/MinecraftConnectSpigot.java#L150

    ComponentBuilder bc = new ComponentBuilder();
    
    BufferedImage bi = ImageIO.read(imgF.url);
    int maxSize = 40;
    double scale = Math.min(
            (double) maxSize / bi.getWidth(),
            (double) maxSize / bi.getHeight()
    );
    int targetWidth  = (int) (bi.getWidth()  * scale);
    int targetHeight = (int) (bi.getHeight() * scale);
    Image scaled = bi.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
    BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = resized.createGraphics();
    g.drawImage(scaled, 0, 0, null);
    g.dispose();
    StringBuilder sb = new StringBuilder();
    for (int y = 0; y < resized.getHeight(); y++) {
        for (int x = 0; x < resized.getWidth(); x++) {
            int rgb = resized.getRGB(x, y);
            int r = (rgb >> 16) & 0xFF;
            int gr = (rgb >> 8) & 0xFF;
            int b = rgb & 0xFF;
            sb.append(colorHex(r, gr, b)).append("█");
        }
        sb.append("\n");
    }
    BaseComponent[] hover = TextComponent.fromLegacyText(sb.toString());
    TextComponent tc = new TextComponent(ChatColor.UNDERLINE + "[图片]");
    tc.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(hover)));
    bc.append(tc);

    流程简而言之:
    降分辨率 -> 逐像素转换为带颜色标记的方块字符 -> 作为 HoverEvent.Action.SHOW_TEXT 添加到消息

    具体实现使用方法:将鼠标指针悬浮到聊天框中的 [图片] 上,就能显示内容了

  • 末屿宇宙 – 服务端互联核心

    开源地址:https://github.com/Ylkawa/MoyuUniverse/

    这个项目的目标是以模块化的形式实现个人部署的不同服务之间的自定义互联。现在已经实现了 Onebot协议 的消息通道,和 Minecraft 服务端之间的简单数据交换。

    本项目开发使用如下依赖库:
    Gson、SnakeYaml、Java-WebSocket、SLF4J、Log4J、Guava


    2025/8/22:
    目前有效功能有,DeepSeek聊天,群名称信息显示,服务端间聊天打通, 网络监视(检测ICMP丢包率)