V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
bbbblue
V2EX  ›  程序员

用了半个多月 roocode+GLM4.5/ds 3.1/qwen3-coder 谈谈感受

  •  
  •   bbbblue · 3 小时 51 分钟前 · 138 次点击

    很早之前用 sonnet 3+cline 发现钱包爆炸,一天得好几刀。 后来换成了 gemini 2.0 flash 虽然偶尔有问题,但基本能 cover ,便宜了很多 接着就一直白嫖 gemini 2.5 pro

    但是 8 月中左右各种截断和报错,基本没法用了 之前国产这仨就在 chat 里偶尔用用,就想着万一不给白嫖了还是得付费,先试试着这仨便宜的来写代码,看看效果。 GLM 4.5/ds 3.1 用的智谱/deepseek 官网 qwen3-coder 用的魔搭的每日免费 魔搭也有 GLM4.5 和 ds3.1 但是似乎速度没有 qwen3-coder 快?

    主要是 remix/nextjs+ts 的几个网站,再加 ts 写一些脚本。 使用的场景主要是辅助,不是那种完全所有默认 approve 让 AI 刷刷刷写,基本就是某些页面/组件,把需求告诉 AI ,手动 approve ,然后看 AI 生成的 diff ,一边改一边 approve 。

    示例的任务说明:

    帮我实现一个 xxxx
    具体需求
    字段可以增加 已经有的字段可以删除
    
    
    页面放到`src/app/[locale]/(tools)/tools/`对应的工具名的文件夹下
    i18 翻译放在`messages/tools`新建一个工具名的文件夹,新建 en.json, ja.json, zh.json 表示英语 日文 中文的翻译文件
    组件放到`src/components/tools`下对应的工具名的文件夹中
    server actions 放到`src/actions/tools`下对应的工具名的文件夹中
    
    你可以参考:
    `src/app/[locale]/(tools)/tools/xxx`
    `src/components/tools/xxx`
    `messages/tools/xxx`
    `src/actions/xxx`
    这个 xxx 的实现
    

    先说结论,这仨都能满足需求,虽然 roocode 比 cc 之类的省 token ,那些来回读取 1-2M 的任务都能 cover 住。

    然后说说每个的缺点:

    ds 3.1

    用的 reasoner (虽然现在这俩都是 3.1 ),主要就一个问题,慢,太慢了。

    用 ds 写的时候我各种摸鱼,有时候一个问题光思考就分钟级,diff 生成的时候是一行行出来的,痛啊...

    工具调用偶尔会出错,但是基本下一轮能恢复

    网上之前比较火的遇到极的问题,运气好没遇到过

    glm 4.5

    速度挺快的,大部分时候质量也挺好。

    但是非常的轴。。。工具调用失败挺多的。。而且一旦失败了就怎么也恢复不了,反复失败。

    有个例子:

    **Assistant:**
    
    <edit_file>
    <path>src/components/tools/test-data-generator/test-data-generator-tool.tsx</path>
    <new_content>
    import { Button } from "@/components/ui/button";
    import { Input } from "@/components/ui/input";
    import { Label } from "@/components/ui/label";
    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
    import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
    import { Textarea } from "@/components/ui/textarea";
    import { CopyButton } from "@/components/ui/copy-button";
    import { useToast } from "@/components/ui/use-toast";
    import { Trash2, Plus, Download } from "lucide-react";
    </new_content>
    <old_content>
    import { Button } from "@/components/ui/button";
    import { Input } from "@/components/ui/input";
    import { Label } from "@/components/ui/label";
    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
    import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
    import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
    import { Textarea } from "@/components/ui/textarea";
    import { CopyButton } from "@/components/ui/copy-button";
    import { useToast } from "@/components/ui/use-toast";
    import { Trash2, Plus, Download } from "lucide-react";
    </old_content>
    </edit_file>
    
    ---
    
    **User:**
    
    [ERROR] You did not use a tool in your previous response! Please retry with a tool use.
    
    # Reminder: Instructions for Tool Use
    
    Tool uses are formatted using XML-style tags. The tool name itself becomes the XML tag name. Each parameter is enclosed within its own set of tags. Here's the structure:
    
    <actual_tool_name>
    <parameter1_name>value1</parameter1_name>
    <parameter2_name>value2</parameter2_name>
    ...
    </actual_tool_name>
    
    For example, to use the attempt_completion tool:
    
    <attempt_completion>
    <result>
    I have completed the task...
    </result>
    </attempt_completion>
    
    Always use the actual tool name as the XML tag name for proper parsing and execution.
    
    # Next Steps
    
    If you have completed the user's task, use the attempt_completion tool. 
    If you require additional information from the user, use the ask_followup_question tool. 
    Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task. 
    (This is an automated message, so do not respond to it conversationally.)
    <environment_details>
    # VSCode Visible Files
    package.json
    
    # VSCode Open Tabs
    
    
    # Current Time
    Current time in ISO 8601 UTC format: 2025-08-29T18:07:29.609Z
    User time zone: Asia/Hong_Kong, UTC+8:00
    
    # Current Cost
    $0.21
    
    # Current Mode
    <slug>code</slug>
    <name>💻 Code</name>
    <model>glm-4.5</model>
    ====
    
    REMINDERS
    
    Below is your current list of reminders for this task. Keep them updated as you progress.
    
    | # | Content | Status |
    |---|---------|--------|
    | 1 | 创建测试数据生成器的目录结构 | Completed |
    | 2 | 实现测试数据生成器的主页面组件 | Completed |
    | 3 | 实现测试数据生成器的核心功能组件,包括: | In Progress |
    | 4 | 创建多语言翻译文件(英文、日文、中文) | Pending |
    | 5 | 更新工具导航数据,添加新工具 | Pending |
    | 6 | 测试功能并确保一切正常工作 | Pending |
    
    
    IMPORTANT: When task status changes, remember to call the `update_todo_list` tool to update your progress.
    
    </environment_details>
    
    ---
    
    **Assistant:**
    
    <edit_file>
    <path>src/components/tools/test-data-generator/test-data-generator-tool.tsx</path>
    <new_content>
    import { Button } from "@/components/ui/button";
    import { Input } from "@/components/ui/input";
    import { Label } from "@/components/ui/label";
    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
    import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
    import { Textarea } from "@/components/ui/textarea";
    import { CopyButton } from "@/components/ui/copy-button";
    import { useToast } from "@/components/ui/use-toast";
    import { Trash2, Plus, Download } from "lucide-react";
    </new_content>
    <old_content>
    import { Button } from "@/components/ui/button";
    import { Input } from "@/components/ui/input";
    import { Label } from "@/components/ui/label";
    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
    import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
    import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
    import { Textarea } from "@/components/ui/textarea";
    import { CopyButton } from "@/components/ui/copy-button";
    import { useToast } from "@/components/ui/use-toast";
    import { Trash2, Plus, Download } from "lucide-react";
    </old_content>
    </edit_file>
    
    ---
    

    roocode 压根就没edit_file这个 tool... ...

    无限循环了,试了几次中断,继续。和他说不要改了他还是会这么回。

    然后这么多来几次,GLM 4.5 送的 2Mtoken 直接爆炸,然后发现他送的 2M 居然是所有模型 2M+GLM 4.5 2M 共用的,用完 GLM 4.5 的 2M ,那个所有模型的也没了 🤣🤣🤣🤣

    qwen3 coder

    速度也挺快的,总体感觉都不错。

    就是偶尔写的 ts 有一股 java 的味道,面向对象优先了,他写的代码:

    /**
     * Sync manager for CloudWatch logs to MySQL database
     */
    export class SyncManager {
      private cloudWatchClient: CloudWatchLogClient;
      private mysqlClient: MySQLClient;
      private syncConfig: SyncConfig;
    
      constructor(
        cloudWatchClient: CloudWatchLogClient,
        mysqlClient: MySQLClient,
        syncConfig: SyncConfig
      ) {
        this.cloudWatchClient = cloudWatchClient;
        this.mysqlClient = mysqlClient;
        this.syncConfig = syncConfig;
      }
    
      /**
       * Calculate the time window for syncing logs
       * @returns Object containing startTime and endTime in milliseconds
       */
      public calculateTimeWindow(): { startTime: number; endTime: number } {
        const endTime = Date.now();
        const startTime = endTime - this.syncConfig.intervalHours * 60 * 60 * 1000;
        return { startTime, endTime };
      }
    ...
    export class Logger {
      private static readonly LEVELS = {
        ERROR: 0,
        WARN: 1,
        INFO: 2,
        DEBUG: 3,
      };
    
      private static level = Logger.LEVELS.INFO;
    
      public static setLevel(level: keyof typeof Logger.LEVELS) {
        Logger.level = Logger.LEVELS[level];
      }
    
      public static error(message: string, error?: Error) {
        if (Logger.level >= Logger.LEVELS.ERROR) {
          const timestamp = new Date().toISOString();
          console.error(
            `[ERROR] ${timestamp} - ${message}`,
            error ? error.stack : ""
          );
        }
      }
    
    

    🤣🤣🤣🤣🤣🤣

    kk2syc
        1
    kk2syc  
       3 小时 32 分钟前
    所以说浪费这个时间干嘛……类似 i18n 翻译的 json 文件可以直接写好 zh.json 之后让 ai 去处理其他的,至于类似前端框架这些,有这个时间调教 ai ,ctrl+cv 改改都干完喝咖啡了……
    bbbblue
        2
    bbbblue  
    OP
       3 小时 22 分钟前
    @kk2syc 不是呀 页面+功能+翻译都是 ai 完成 一行代码都没写 就改改 diff
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   915 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 21:50 · PVG 05:50 · LAX 14:50 · JFK 17:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.