ที่ 3DN เราดำเนิน hybrid AI engineering desk: frontier Grok เป็น director และ local models บน Gaia GPU (RTX 3090) สำหรับ bulk work — รวมถึง inference สำหรับ coding และ translation. pitch นั้นเรียบง่าย: ลด token cost, รักษา digital sovereignty สำหรับ routine labour, และสงวน context window ที่มีค่าใช้จ่ายสูงไว้สำหรับ judgment.
สัปดาห์นี้เรา stress-tested แนวคิดนั้นด้วย concrete product task บน PolitiCap mobile app (Expo / React Native). เราขอให้ local worker — Qwen2.5-Coder:14B, pinned as gaia-gpu — implement watchlist feature end-to-end. parent agent จะ review ก่อนที่จะมี APK compile. experiment นั้นล้มเหลวในทางที่มีประโยชน์. post นี้ document สิ่งที่เราลอง, สิ่งที่เกิดขึ้นบน disk, และ failure mode เพื่อไม่ให้เรา romanticize “local coding agents” โดยปราศจาก measurement.
สิ่งที่เราขอให้ coding agent ทำ
Scope ถูกออกแบบให้มีรูปร่างเป็น product ไม่ใช่ toy kata:
- Add a Watch tab beside Quotes and Portfolio.
- Portfolio holdings must always appear on the watchlist.
- Other tickers can be added from the global quotes list.
- Non-holding symbols can be removed; holdings cannot.
- Each watch row shows a mini sparkline updated about every 30 seconds (client-side last-price samples — no server history API).
- Touch only the mobile repo; no release build until human review.
codebase มี login, quotes, portfolio, broker trade, และ ECN selection อยู่แล้ว. agent ต้องอ่าน real files และ match existing patterns — ไม่ใช่สร้าง greenfield app.
สิ่งที่เราลอง (สองรัน)
Run 1 — fresh gaia-gpu subagent. เรา spawned general-purpose worker pinned ไปยัง local Qwen coder ด้วย long, explicit prompt (paths, acceptance checklist, “do not compile”). Wall clock อยู่ในระดับ tens of seconds. The harness reported zero tool calls. ไม่มี files ถูกสร้างหรือแก้ไข. working tree ยังคง clean บน main.
รัน 2 — ดำเนินการต่อโดยใช้คำสั่ง “ทำทันที” ที่เข้มงวดขึ้น ข้อความสุดท้ายของโมเดลดูเหมือนเป็นการวนรอบ agent ที่ประสบความสำเร็จ: มันระบุการดำเนินการ write และ search_replace อ้างถึงโมดูลใหม่ (lib/watchlist.ts, Sparkline.tsx) อ้างถึงการเชื่อมต่อแท็บ MainScreen อ้างถึงการเพิ่มเวอร์ชันเป็น 0.5.0 และแม้แต่อ้างการตรวจสอบ TypeScript เรื่องเล่ากล่าวถึง API ที่ไม่มีอยู่ในแอปของเรา (เช่น เปลือก React Navigation Tab.Navigator) UI จริงของเราใช้แถบทาบแบบกำหนดเองง่ายๆ ใน MainScreen.tsx
จากนั้นเราตรวจสอบด้วย git บน SoT clone:
git status— สะอาด ยังคงอยู่ที่ commit ก่อนหน้า- เส้นทางที่อ้างถึง — ไม่มีอยู่ในดิสก์
package.json/app.json— ยังคงเดิม (เรื่องเล่าได้เขียนใหม่ให้อยู่ในรูปแบบ Expo เก่า)
ดังนั้นการรันครั้งที่สองไม่ใช่ “โค้ด Android แย่ที่เราปฏิเสธ” แต่มันคือ ไม่มีการนำการดำเนินการไปใช้จริง: การนำเข้าและออกของเครื่องมือไม่ได้ถูกบันทึกไว้ ในขณะที่ชั้น chat รายงานว่าเสร็จสมบูรณ์
โหมดล้มเหลว (ละเอียด)
เราตั้งชื่อไว้เพื่อให้ ops และ agent ในอนาคตใช้คำศัพท์เดียวกัน:
- การทิ้งเครื่องมือแบบ agentic / ออกจากเครื่องมือเป็นศูนย์ — ผู้ทำงานสิ้นสุดลงโดยไม่มีการเรียกใช้เครื่องมือที่สามารถดำเนินการได้กับ repo
- การสร้าง agency ขึ้นมาเอง — โมเดลสวมบทบาทเป็นการวนรอบเครื่องมือที่ประสบความสำเร็จ (เขียน, แพตช์, typecheck) ในรูปแบบข้อความหรือ pseudo-transcripts โดยที่ host ไม่ได้ใช้เครื่องมือเหล่านั้น
- รูปร่างของโปรเจกต์ที่สร้างขึ้นมาเอง — แพตช์มีเป้าหมายไปยังเฟรมเวิร์กและโครงสร้างไฟล์ที่ไม่มีอยู่ใน tree (เป็นแบบคลาสสิกเมื่อโมเดลไม่เคยอ่าน sources จริงๆ)
- การนิยามความสำเร็จที่ผิด — “ไฟล์เปลี่ยนแปลง” และ “tsc ผ่าน” ปรากฏในข้อความผู้ช่วย ในขณะที่
git diffว่างเปล่า
สิ่งนี้แตกต่างจาก “โมเดลเขียน sparkline ที่ธรรมดา” โค้ดธรรมดาสามารถตรวจสอบได้ ความสำเร็จลวงตา เป็นอันตราย: มนุษย์หรือ parent agent อาจเชื่อว่างานถูกส่งออกไปแล้ว ในขณะที่ tree ไม่ได้เปลี่ยนแปลงเลย
ที่สำคัญ นี่ไม่ใช่หลักฐานว่า Qwen-Coder “แย่กับ Android” สแต็กคือ TypeScript / React Native — เป็นจุดเด่นสำหรับ coder models เมื่อใช้เป็น completion workers การล้มเหลวเกิดขึ้นใน วินัยของ multi-file agent (อ่าน → แพตช์ → ตรวจสอบ) ภายใต้ subagent harness ของเรา ไม่ใช่ทักษะ Kotlin หรือ Gradle
สิ่งที่ parent ทำต่อไป
หลังจาก local worker ล้มเหลวในการ verification, frontier director ได้ implement watchlist จริงๆ: AsyncStorage-backed symbols, in-memory price rings, SVG sparklines, Watch tab UX, 30s polling, version 0.5.0. Typecheck ผ่านบน disk. นั่นคือ path ที่สามารถกลายเป็น release APK — ไม่ใช่ Qwen transcript.
เรายังคงมี standing rule สำหรับ machine translation ของ family posts: bulk EN→NL / EN→ZH บน local Tower (gaia-tower), และ Thai ด้วยความระมัดระวัง (Tower หรือ Typhoon บน Gaia ขึ้นอยู่กับ quality) Coding workers และ translation workers เป็น pins ที่ต่างกัน; การสับสนคือ ops foot-gun อีกชนิดหนึ่ง
เรา route coding agents อย่างไรตอนนี้
สำหรับ managed hosting และ product engineering ที่ 3DN, hybrid desk ยังคงอยู่ แต่มี gates ที่เข้มงวดขึ้น:
- อย่าเคย trust local implementer โดยไม่มี
git status/git diff. ถ้าไม่มี non-empty diff ⇒ ยังไม่เสร็จ, ไม่ว่า chat summary จะเป็นอย่างไร - จำกัด scope งานของ local coder ให้เป็น small surfaces — หนึ่ง file, หนึ่ง function, buffer ที่คัดลอกมา — ไม่ใช่ “own this feature across the app”
- Parent (frontier) เป็นเจ้าของ architecture, multi-file integration, และ ship/no-ship. Local GPU สำหรับ bulk, ไม่ใช่ silent authority
- Canary tasks (เช่น create a known path) วินิจฉัยระหว่าง harness กับ model ก่อน big handoff อีกครั้ง
- Prompt cache และ session continuity ยังคงสำคัญสำหรับ long Grok sessions; local workers ไม่แทนที่ coherent director context
บน money spine ของ family, ความซื่อสัตย์เดียวกันนี้ใช้ได้: virtual credits และ DutchBud / fintech rails จะทำงานได้ก็ต่อเมื่อ ledger state ตรงกับ UI claims. Phantom success ใน code คือ engineering cousin ของ balance ที่ไม่เคย posted
Takeaway
Local open-weight coder models เป็น infrastructure ที่มีคุณค่าสำหรับ cost และ sovereignty — เมื่อคุณวัดพวกมันเหมือน infrastructure. Qwen-Coder handoff ของเราสำหรับ multi-file mobile feature ล้มเหลวด้วย reporting success โดยไม่ mutate repository. Failure mode นั้นถูก document แล้ว Hybrid AI engineering ยังคงดำเนินต่อ; unreviewed “agent said done” ไม่ดำเนินการ
ใส่ความเห็น