9 คะแนน โดย GN⁺ 2025-06-10 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • แชร์ประสบการณ์การใช้ TensorZero เป็นพร็อกซีโอเพนซอร์สเพื่อ ดักจับและวิเคราะห์ทราฟฟิกระหว่าง Cursor กับผู้ให้บริการ LLM (เช่น OpenAI) พร้อมสังเกตผลลัพธ์ของพรอมป์ต์ โมเดล และการอนุมานแบบเรียลไทม์ รวมถึงทดลองปรับแต่งให้เหมาะสม
  • Cursor สามารถ override Base URL และชื่อโมเดล ตอนเรียกใช้ LLM ได้ จึงเชื่อมต่อพร็อกซีของตนเอง (TensorZero) ได้ง่าย
  • ภายใน Cursor เรียกใช้ LLM ผ่านเซิร์ฟเวอร์ของตัวเอง จึงต้องใช้ Ngrok + Nginx reverse proxy และตั้งค่า CORS header เพื่อทำพร็อกซีแบบสมบูรณ์
  • ผ่านพร็อกซี สามารถสังเกตได้ทั้งหมดว่า Cursor ส่ง system prompt, user prompt, และคำขอแก้ไขโค้ดแบบ inline ไปยัง LLM อย่างไร รวมถึงสลับ/ทดลองกับ LLM หลายแบบได้แบบเรียลไทม์ (A/B test)
  • จากการวิเคราะห์ system prompt ของ Cursor พบว่า ใช้พรอมป์ต์เพียงราว 642 โทเคน ก็เพียงพอให้ LLM เข้าใจและจัดการบริบทงานวิศวกรรมซอฟต์แวร์ส่วนใหญ่ได้ ส่วนงานแก้ไขโค้ดมี "apply model" แยกต่างหากคอยรับผิดชอบ (โมเดลเสริมที่ฉลาดน้อยกว่า)
  • ด้วยโครงสร้างพร็อกซีแบบ TensorZero จึงสามารถทำ การทดลอง LLM แบบปรับตามผู้ใช้แต่ละรายและการเพิ่มประสิทธิภาพจากฟีดแบ็ก ได้ ซึ่งเหมาะอย่างยิ่งกับการประเมินคุณภาพเครื่องมือช่วยเขียนโค้ด (A/B test), การปรับแต่งพรอมป์ต์ และการมอนิเตอร์การใช้งานจริง

บทนำ

  • กล่าวถึงประสบการณ์การเชื่อมเฟรมเวิร์กโอเพนซอร์ส TensorZero เป็น พร็อกซีเกตเวย์ ระหว่าง Cursor กับ LLM (โมเดลภาษาขนาดใหญ่) หลายประเภท พร้อมสิ่งที่สังเกตได้ การทดลอง และจุดที่สามารถปรับแต่งให้เหมาะสมได้
  • TensorZero เป็นโอเพนซอร์สที่ช่วยยกระดับคุณภาพของแอปพลิเคชัน LLM โดยอาศัย สัญญาณฟีดแบ็ก (ตัวชี้วัดการใช้งานจริง พฤติกรรมผู้ใช้ เป็นต้น)
  • ในฐานะผู้ใช้ Cursor ผู้เขียนจึงทดลองนำเทคโนโลยีนี้มาใช้กับ IDE ที่ขับเคลื่อนด้วย LLM ซึ่งใช้งานบ่อยที่สุด เพื่อดูว่าในทางปฏิบัติมี API request อะไรวิ่งผ่านบ้าง และจะลองปรับแต่งด้วยตนเองได้อย่างไร

ภาพรวมและเป้าหมาย

  • Cursor เป็นผู้ช่วยเขียนโค้ดที่ถูกปรับให้เหมาะกับผู้ใช้โดยรวม แต่แทบเป็นไปไม่ได้เลยที่จะทำ การทดลองปรับแต่งเฉพาะรายบุคคล และสังเกตข้อมูลอย่างละเอียด
  • หากวาง TensorZero เป็น พร็อกซี ก็จะสามารถสังเกต request ของ Cursor, response จาก LLM, พรอมป์ต์, โมเดล และกระบวนการอนุมานทั้งหมดได้อย่างโปร่งใส พร้อมทั้งขยายไปสู่การทดลองและการปรับแต่งได้
  • เพราะ วิธีการปรับแต่ง การประเมิน และการทดลอง ส่วนใหญ่ต้องอาศัยข้อมูลการอนุมานจริง บทความนี้จึงแนะนำวิธีเก็บข้อมูลเชิงปฏิบัติและแนวทางทำให้เป็นอัตโนมัติอย่างเป็นรูปธรรม

ขั้นตอนการเชื่อมต่อ: สร้าง LLM gateway

  • Cursor รองรับการปรับ OpenAI base URL และชื่อโมเดลเองได้
  • TensorZero มี inference endpoint ที่เข้ากันได้กับ OpenAI จึงสามารถเชื่อม Cursor ไปยัง TensorZero แทน OpenAI ได้
  • ด้วยการลงทะเบียนฟังก์ชัน cursorzero ภายใน TensorZero จึงสามารถทดลองโมเดล/พรอมป์ต์ได้หลากหลาย และบันทึก ข้อมูลการอนุมานและฟีดแบ็กแบบอัตโนมัติ โดยไม่ผูกกับผู้ให้บริการรายใดรายหนึ่ง

อุปสรรคแรก: เซิร์ฟเวอร์ของ Cursor เอง

  • ตอนแรก Cursor พยายามเชื่อมต่อกับ TensorZero ที่รันอยู่ในเครื่อง โดยตรง แต่ไม่สำเร็จ
  • Cursor จะส่ง request ไปยังเซิร์ฟเวอร์ของตัวเองก่อนเสมอ แล้วจึงค่อยประมวลผลภายในเพิ่มเติมก่อนเรียกใช้ LLM
    • ด้วยเหตุนี้ ข้อมูลรับรอง (credentials) จึงถูกส่งไปยังเซิร์ฟเวอร์ของ Cursor และเซิร์ฟเวอร์นั้นก็สามารถเก็บข้อมูลของทุก request รวมถึง codebase ได้
  • ทางเลือกหนึ่งคือเชื่อมผ่าน OpenRouter เพื่อตรวจสอบว่า interaction บางอย่างภายใน Cursor สามารถใช้โมเดลภายนอกได้หรือไม่
  • ฟีเจอร์ Tab autocomplete ของ Cursor ทำงานด้วยโมเดลปิดภายในของตัวเอง และสามารถใช้ร่วมกับ LLM อื่นได้
  • สุดท้ายจึงแก้ปัญหาด้วยการใช้ reverse proxy และ Ngrok เพื่อสร้างโครงสร้างที่พร็อกซี request จาก endpoint สาธารณะภายนอกกลับเข้าไปยัง TensorZero ภายใน
  • วาง Nginx ไว้ด้านหน้าเพื่อเพิ่มการยืนยันตัวตนและเสริมความปลอดภัย พร้อมทำ LLM routing ผ่านฟังก์ชัน TensorZero แบบกำหนดเอง
  • โครงสร้างสุดท้ายคือ:
    • Cursor → Ngrok → Nginx(การยืนยันตัวตน) → TensorZero(โลคัล) → LLM Provider

อุปสรรคที่สอง: CORS

  • ระหว่างการยืนยันตัวตน มี CORS preflight (OPTIONS) request มาถึง Nginx ทำให้เกิดปัญหาที่ยังไม่ผ่านการยืนยันตัวตนในช่วงแรก
  • จึงตั้งค่าให้ Nginx ส่งกลับ CORS header แบบเดียวกับ OpenAI API เพื่อให้ตรงตามข้อกำหนดของ Cursor IDE ที่ทำงานบน Electron
  • หลังแก้ปัญหาการยืนยันตัวตนและ CORS แล้ว request จริงทั้งหมดก็ยังคงวิ่งผ่านเซิร์ฟเวอร์ของ Cursor
  • (มีตัวอย่างโค้ดการตั้งค่า Nginx รวมอยู่)

ผลลัพธ์สุดท้าย: มองทะลุการทำงานของ Cursor ได้

  • สามารถสังเกต ทุก request/response ของ LLM, system prompt, user prompt, รวมถึงเนื้อหาโค้ด/ไฟล์ที่แนบมา ได้แบบเรียลไทม์
  • ในตัวอย่าง system prompt ยังระบุคำสั่งสำหรับเรียก "apply model" แยกต่างหากเพื่อใช้แก้ไขโค้ดด้วย (โครงสร้างโมเดลสองชั้น)
  • โครงสร้างหลักของพรอมป์ต์ใน Cursor ได้แก่:
    • ข้อมูลเซสชันผู้ใช้ บริบทอย่างไฟล์และตำแหน่งเคอร์เซอร์
    • การแบ่งส่วนด้วยบล็อกคอมเมนต์ เป็นต้น
    • เมื่อร้องขอให้แก้ไขโค้ด จะมีแนวทางให้สร้าง code block โดย ‘จำกัดการเปลี่ยนแปลงเฉพาะส่วนที่จำเป็น’
  • Prompt engineering ของ Cursor
    • แค่ system prompt ขนาดใหญ่เพียง 642 โทเคนเดียว ก็ทำให้งานวิศวกรรมซอฟต์แวร์ส่วนใหญ่เป็นอัตโนมัติได้
  • ยังมี apply model (โมเดลเสริม) ที่ฉลาดน้อยกว่าและออกแบบมาเฉพาะสำหรับงานเปลี่ยนแปลงโค้ดแยกต่างหาก โดยกำหนดเป้าหมายและกติกาการใช้งานให้ชัดเจนจาก main LLM
    • ยืนยันได้ว่าโครงสร้างโมเดลหลายชั้น (แบ่งตามความฉลาดและหน้าที่) ถูกนำไปใช้จริงอยู่ภายในพรอมป์ต์

บทสรุปและนัยสำคัญ

  • Cursor สามารถจัดการบริบทงานวิศวกรรมซอฟต์แวร์ได้ด้วย ความรู้พื้นฐานที่ฝังมากับ LLM รุ่นใหม่และพรอมป์ต์ที่กระชับ
  • การใช้พร็อกซีอย่าง TensorZero ช่วยให้สร้างโครงสร้างสำหรับการเพิ่มประสิทธิภาพจากฟีดแบ็กและข้อมูลการใช้งานจริงในระดับรายผู้ใช้ได้ง่าย (A/B test, prompt/model tuning)
  • สำหรับ AI ช่วยเขียนโค้ดในเอดิเตอร์หรือองค์กรที่นำ LLM มาใช้ วิธีนี้ช่วยให้ทดลอง การออกแบบพรอมป์ต์ การปรับปรุงประสิทธิภาพ และการปรับแต่งตามผู้ใช้ ได้อย่างรวดเร็ว
  • ในบทความถัดไป ผู้เขียนจะทดลองต่อเรื่อง วิธีเก็บข้อมูลการใช้งานจริง, tree-sitter, และการใช้ git hook

1 ความคิดเห็น

 
GN⁺ 2025-06-10
ความคิดเห็นบน Hacker News
  • Cursor เป็นผลิตภัณฑ์เดียวในบรรดาบริการที่ฉันใช้มากว่า 20 ปีที่ทำให้ฉันยกเลิกการสมัครสมาชิกเพราะไม่มีฝ่ายบริการลูกค้าเลย
    ตลอดหลายสัปดาห์ฉันส่งอีเมลถามเรื่องการชำระเงินหลายครั้ง แต่ไม่เคยได้รับคำตอบกลับแม้แต่ครั้งเดียว
    มันไม่ใช่แค่คำถามเกี่ยวกับ VS Code ทั่วไป แต่เป็นปัญหาที่จำเป็นต้องให้ทีมของ Cursor เข้ามาจัดการ
    แต่พวกอีเมลโปรโมชันกลับส่งมาได้ตามปกติ
    หวังว่า ‘คุณค่า’ ของ Cursor จะกระจายไปยังบริการอื่น ๆ อย่างรวดเร็ว
    หวังว่าทีมถัดไปจะตอบอีเมล

    • ฉันก็มีประสบการณ์คล้ายกัน และได้เขียน issue เกี่ยวกับเรื่องนี้ไว้ด้วย
  • ในพรอมป์ต์นี้ยังมีข้อมูลที่หายไปอีกมาก
    จุดที่เห็นได้ชัดที่สุดคือไม่มี tool call descriptors
    ลองเทียบโดยตรงกับพรอมป์ต์ jailbreaking เมื่อหนึ่งปีก่อนได้เลย
    ถึงอย่างนั้น การตั้งค่าส่วนอื่น ๆ อย่าง cursor rules ก็ยังเป็นไอเดียที่ดี
    อนึ่ง ดูเอกสารพรอมป์ต์ที่เกี่ยวข้องได้ที่ นี่

    • ใน Cursor จะใช้พรอมป์ต์ต่างกันตามแอ็กชันที่ผู้ใช้ทำ
      ตอนนี้ให้มาแค่ตัวอย่างเท่านั้น แต่เป้าหมายพื้นฐานคือทำ A/B test กับโมเดลหลายแบบและปรับพรอมป์ต์กับโมเดลให้เหมาะสมที่สุด
      ผมก็ให้โค้ดไว้เพื่อให้ทำซ้ำได้ และจากตรงนั้นก็ดูพรอมป์ต์อื่น ๆ ได้ด้วย
      Gist ที่คุณแชร์มาก็มีประโยชน์มากทีเดียว

    • เลยอดคิดไม่ได้ว่าอาจมีตรรกะการปรับแต่งบางอย่างที่ใส่เฉพาะข้อมูลเครื่องมือที่จำเป็นจริง ๆ จากคำค้นของผู้ใช้ลงในพรอมป์ต์หรือเปล่า
      น่าจะเป็นกลยุทธ์ตัด tool descriptor ที่ไม่จำเป็นออกเพื่อประหยัดโทเค็น

    • ดูข้อมูลอ้างอิงที่เกี่ยวข้องได้ ที่นี่

  • งั้นก็แปลว่า... ตอนนี้ใช้ wireshark ไม่ได้แล้วเหรอ?

    • ตอนท้ายบทความระบุไว้ว่านี่เป็นเพียงโพสต์แรกที่สรุปภาพรวมก่อนจะตัดสินใจว่าจะใช้อย่างไร
      อีกอย่าง ทุกวันนี้ mitmproxy ก็ดีมากสำหรับการดูแพ็กเก็ตเฉย ๆ mitmproxy docs

    • wireshark ยังใช้ดูคำขอที่ออกจากแอปเดสก์ท็อปไปยังเซิร์ฟเวอร์ของ Cursor ได้อยู่ (ซึ่งก็คือคำขอที่ส่งไปยัง LLM โดยปริยาย)
      แต่ถ้าอยากดูว่าคำขอจริงจากเซิร์ฟเวอร์ของ Cursor ไปยัง LLM ไปอย่างไร ก็ต้องมีการตั้งค่าเพิ่มเติม
      ถ้าตั้งค่าแบบนั้นได้ เราก็จะลองเปลี่ยนคำขอเพื่อทำ A/B test ได้ด้วย

  • Cursor และโซลูชัน modality สำหรับ IDE หลายตัวน่าสนใจ แต่ก็น่าเสียดายที่มันทำให้ผู้คนติดนิสัยจัดการคอนเท็กซ์แบบลวก ๆ
    ถ้าดูข้อความที่ยกมาจากพรอมป์ต์ของ Cursor จะประมาณว่า
    "ทุกครั้งที่ผู้ใช้ส่งข้อความ เราอาจแนบข้อมูลเพิ่มเติมให้อัตโนมัติ เช่น สถานะปัจจุบัน ประวัติการแก้ไขในเซสชัน ข้อผิดพลาดจาก linter ฯลฯ และข้อมูลนี้อาจเกี่ยวข้องกับงานเขียนโค้ดหรือไม่ก็ได้ ความเหมาะสมให้คุณเป็นคนตัดสิน"
    ‘context bloat’ แบบนี้จำกัดประสิทธิภาพของ LLM อย่างมากเวลาต้องแก้ปัญหาที่ยากจริง ๆ
    ปัญหา .env ที่ยกเป็นตัวอย่างเป็นเคสง่าย ๆ เลยเป็นสิ่งที่ Cursor จัดการได้ดี แต่ความซับซ้อนระดับนี้ยังไม่พอที่จะหยุดจ้างวิศวกรซอฟต์แวร์ได้
    โดยส่วนตัว ผมแนะนำว่าเวลาใช้ AI ทำงาน ควรเริ่มจากคิดก่อนว่าจะจัดการบริบทของบทสนทนาในแชตอินเทอร์เฟซให้สะอาดอย่างไร
    เพราะในปัญหาที่ซับซ้อน บริบทจะพันกันระหว่างการประชุม บทสนทนาใน Slack เอกสารภายใน เนื้อหาจากภายนอก และโค้ด
    ผมสร้างเครื่องมืออย่าง FileKitty(ลิงก์) และช่วงหลังคือ slackprep(ลิงก์) เพื่อคัดเฉพาะข้อมูลที่เกี่ยวข้องกับการแก้ปัญหาออกมาใช้อย่างมีเจตนามากขึ้น

    • ฉันก็เห็นด้วยกับประเด็นนี้ และตอนพัฒนาแอปเอเจนต์ของตัวเองก็ต้องคัดสรรบริบทอย่างระมัดระวังมากกว่าเดิมมาก
      มันไม่ใช่แค่ "อาจแนบให้อัตโนมัติได้" แต่ต้องเขียนคำสั่งให้รวมเฉพาะสิ่งที่แนบมาจริง ๆ เท่านั้น
      แทนที่จะบอกว่า "อาจเกี่ยวข้องหรือไม่ก็ได้ คุณตัดสินเอง" ต้องมีคำสั่งที่ชัดเจนว่าควรทำอย่างไรในกรณีที่เกี่ยวข้องและไม่เกี่ยวข้อง
      ถ้าบริบทสั้นก็ไม่ค่อยมีปัญหา แต่ในประเด็นที่ยาวและซับซ้อน คำสั่งละเอียดแบบนี้สร้างความต่างได้มาก
      เดาว่า Cursor คงทำคำสั่งให้ทั่วไปที่สุดเพื่อใช้ประโยชน์จากราคาของ cached token
      หลายส่วนยังอยู่ในช่วงทดลอง และคิดว่าในอนาคตคงมีการปรับปรุงพรอมป์ต์กับโมเดลอีกมาก
  • ดูการวิเคราะห์อื่นเกี่ยวกับพรอมป์ต์ของ Cursor ได้ ที่นี่

  • ผมสงสัยมาตลอดว่ากระบวนการคัดเลือกบริบทที่เกี่ยวข้องในบทสนทนายาว ๆ ทำกันอย่างไร
    อยากรู้ว่ามีใคร reverse engineer ตรรกะส่วนนั้นจริง ๆ จนรู้หรือยังว่าเขาตัดประวัติการเปลี่ยนแปลงอย่างไร และแสดงสถานะล่าสุดของไฟล์อย่างไร

    • ผมยังไม่ได้เจาะเวิร์กโฟลว์นั้นลึกมากนัก แต่เราสามารถทำสิ่งที่เราทำซ้ำบน GitHub ได้โดยตรง จึงอาจหาเบาะแสจากตรงนั้นได้
      ต่อจากนี้ผมจะศึกษาส่วนนี้ต่อ และจะใช้ TensorZero ทำการทดลองปรับแต่งโมเดลกับพรอมป์ต์ต่อไป
  • กำลังวิเคราะห์ด้วยวิธีเดียวกันโดยใช้ mitmproxy การสนทนาที่เกี่ยวข้อง

  • ตอนนี้เมื่อรู้ข้อมูลพรอมป์ต์แล้ว ก็สงสัยว่าจะสามารถสร้างเซิร์ฟเวอร์ของ Cursor ขึ้นมาใหม่เพื่อทำเวอร์ชันที่รันในเครื่องทั้งหมด (หรือแนว ๆ เวอร์ชันแคร็ก) ได้ไหม

    • หรือจริง ๆ แล้วใช้โปรเจกต์โอเพนซอร์สที่เน้น agentic coding อย่าง Cline, Roo Code ไปเลยอาจดีกว่า

    • ก็แปลกนิดหน่อยที่ต้องรอให้พรอมป์ต์ออกมาก่อนถึงค่อยลองทำแบบนี้

    • ดูเหมือนว่าโมเดล apply ของ Cursor จะรันอยู่บนเซิร์ฟเวอร์
      เลยสงสัยว่าการทำโมเดล apply แบบโลคัลเองจะยากแค่ไหน
      ถ้ารันบน MacBook อาจจะเร็วกว่าเยอะก็ได้

    • ทำได้แน่นอน