กลไกในการป้องกันไม่ให้ Copilot ทำผิดพลาดซ้ำสองครั้ง — ออกแบบให้มี “ความทรงจำในการสนทนา” ด้วย RAG + MCP
🔗 สารบัญซีรีส์: บทความนี้เป็น ฉบับการใช้งาน (1) ของซีรีส์ บันทึกการปฏิบัติงานของผู้ช่วย AI - บันทึกการปฏิบัติสำหรับการเพิ่มรหัส Copilot / Claude ในฐานะคู่หูของคุณ
สิ่งที่คุณสามารถเรียนรู้ได้จากบทความนี้
- อุบัติเหตุไม่หยุดแม้หลังจากเขียน 15
instructions.mdใน GitHub Copilot และขีดจำกัดแล้ว - สถาปัตยกรรมที่ช่วยให้ Copilot มี “ที่จัดเก็บข้อมูลภายนอก (RAG)” โดยใช้ MCP (Model Context Protocol)
- การใช้งานการตั้งค่า เซิร์ฟเวอร์ MCP ที่สร้างขึ้นเอง ด้วย ChromaDB + Ollama (
nomic-embed-text) + FastMCP - มากกว่าแค่การค้นหา 6 การตัดสินใจออกแบบเพื่อป้องกันอุบัติเหตุไม่ให้เกิดขึ้นอีก
- การเพิ่มความใหม่ / ลำดับความสำคัญสูง / การส่งออกอัตโนมัติ session_context / บันทึกกิจกรรม / เกณฑ์แบบไดนามิก / ล็อคอะตอม
- ผลกระทบของการปฏิบัติงาน — เรื่องราวที่ความล้มเหลวแบบเดิมๆ หยุดลงและข้อจำกัดยังคงอยู่
กลุ่มเป้าหมาย
- ผู้ที่ใช้ GitHub Copilot แล้วรู้สึกว่าตัวเองทำจุดเดิมๆ ซ้ำแล้วซ้ำอีก
- ผู้ที่ต้องการให้ผู้ช่วย AI มี ความจำระยะยาว
- ผู้ที่ต้องการสร้าง MCP (Model Context Protocol) เป็น เซิร์ฟเวอร์เครื่องมือที่ใช้งานได้จริง
- ผู้ที่เห็นด้วยกับแนวคิด “พัฒนา AI”
สภาพแวดล้อมการทำงาน| รายการ | เวอร์ชัน/การกำหนดค่า |
|---|---|
| ระบบปฏิบัติการ | Windows 11 (PowerShell 5.1 / 7) |
| หลาม | 3.13 (venv) |
| เวกเตอร์ DB | ChromaDB (โหมดถาวร) |
| โมเดลการฝัง | โอลมะ nomic-embed-text (768 มิติ) |
| กรอบงาน MCP | mcp Python SDK FastMCP |
| ลูกค้า | VS Code GitHub Copilot Chat (เรียกใช้ stdio ผ่านการตั้งค่า MCP) |
1. บทนำ — 24 คำที่ฉันพูดไปตอนพูดว่า “ได้โปรด” เรื่องราวของค่ำคืนที่ PATCH อยู่เหนือการควบคุม
คืนหนึ่ง ฉันกำลังเขียนสคริปต์ร่วมกับ Copilot เพื่ออัปเดตบทความ 25 บทความพร้อมกันโดยใช้ API ของ Qiita นี่เป็นขั้นตอนที่ระมัดระวังโดยเราจะส่งข้อความทดสอบเพียงข้อความเดียวในระยะที่ 1 ซึ่งทำได้สำเร็จ รอประมาณ 5 นาที แล้วจึงส่งข้อความที่เหลืออีก 24 ข้อความในระยะที่ 2
ระยะที่ 1 ประสบความสำเร็จและฉันพูดว่า “เอาล่ะ แล้วไงล่ะ?
“ได้โปรด”
ความตั้งใจของฉันคือ “โปรดเตรียมตัวสำหรับระยะที่ 2 ฉันจะออกคำสั่งการดำเนินการอีกครั้งใน 5 นาที”
Copilot ตีความว่า: “คำสั่งให้ เรียกใช้เฟส 2 ทันที”
ไอเทม 24 ชิ้นกระโดดพร้อมกัน อัตราจำกัดอยู่ที่ 429 หน้าต่างเลื่อนของ Qiita เริ่มต้นขึ้น และขยายเวลาวางจำหน่ายจนถึงวันถัดไป
โกรธแล้วบันทึกไว้และเพิ่มจรรยาบรรณ 1 ข้อไปที่ .instructions.md
“กรุณา” ไม่ใช่คำสั่งการกระทำ ก่อนดำเนินการ อย่าลืมถาม “คุณแน่ใจหรือไม่ว่าต้องการดำเนินการ X?”
ในเดือนหน้า บรรทัดฐานยังคงเพิ่มขึ้นอย่างต่อเนื่องตามเหตุการณ์ที่คล้ายคลึงกันในแต่ละครั้ง ฉันสังเกตเห็นสิ่งนี้เมื่อฉันอายุเกิน 15 ปี
**แม้หลังจากเขียนบรรทัดฐานแล้ว Copilot ก็ทำผิดพลาดแบบเดิมอีกครั้ง **พูดให้ถูกก็คือ เซสชันใหม่จะไม่จดจำอุบัติเหตุในอดีต แม้ว่าคุณจะอ่าน .instructions.md ทุกครั้ง คุณจะ ตัดสินผิดแบบเดิม เมื่อคุณพบคำที่คล้ายกันในบริบท
นี่ไม่ใช่ความผิดของ Copilot แต่เป็นลักษณะของ LLM เอง เมื่อบทสนทนาเปลี่ยนไป บริบทก็เปลี่ยนไป และแม้ว่าจะมีกฎเกณฑ์ ความทรงจำที่สดใส ของ “24 PATCH runaway ในคืนนั้น” ก็เริ่มต้นจากศูนย์
ฉันอยากให้โคไพลอตจดจำคืนนั้น ไม่ใช่คำสั่ง แต่ เป็นความทรงจำ
บทความนี้เกี่ยวกับวิธีการสร้างระบบนั้น
2. ทำไม instructions.md ถึงยังไม่เพียงพอ
Copilot มีกลไกที่ให้คุณเขียนกฎที่อ่านทุกครั้งโดยใช้ .github/copilot-instructions.md หรือ .instructions.md ของ VSCode workspace สะดวกแบบนี้ผมก็ใช้แล้ว
อย่างไรก็ตาม มีข้อจำกัดอยู่
ข้อจำกัด 1: “รายการกฎ” ไม่สามารถเอาชนะบริบทได้
- อย่าตีความคำว่า "กรุณา" เป็นคำสั่งให้ปฏิบัติ
- ตรวจสอบก่อนดำเนินการทุกครั้ง
- เชื่อถือการตอบสนองของ API ผ่านการเดา LLM
- ปฏิบัติตามข้อจำกัดด้านเวลา เช่น รอ 5 นาที
- อย่าทำผิดซ้ำอีก
...(ยังมีอีก 10 รายการให้ติดตาม)
แม้ว่าคุณจะอ่านรายการลักษณะนี้เป็นครั้งแรกทุกครั้ง Copilot ก็ทำผิดพลาดทันทีที่พบกับคำที่คล้ายกันในการสนทนา เหตุการณ์ “ได้โปรด” ได้รับการทำซ้ำในบริบทที่แตกต่างออกไป *แม้หลังจาก ได้มีการเขียนหลักคำสอนแล้วก็ตาม
ข้อจำกัด 2: กฎขาด “ประวัติศาสตร์” และ “ความรู้สึก”
กฎเกณฑ์ก็คือข้อเท็จจริง แต่ไม่มีเรื่องราวว่าทำไมกฎจึงมีอยู่จริง สำหรับ Copilot มันเป็นเพียง “อย่าลงรายการ” และเราไม่ร่วม ความเจ็บปวด ของการละเมิดกฎฉันต้องแจ้งให้ Copilot ทราบถึงสถานการณ์เฉพาะของ 24 PATCH ที่ไม่สามารถควบคุมได้ → Qiita ขยายเวลาการเผยแพร่จนถึงวันถัดไป → งานของฉันหยุดไปหนึ่งวัน'' ความโกรธของฉันในตอนนั้น ฉันขอโทษ และความตั้งใจของฉันที่จะ อย่าทำผิดซ้ำอีก” - ในแต่ละบริบท เหล่านี้ถูกส่งไปยัง Copilot
ข้อจำกัด 3: เนื่องจากจำนวนกฎยังคงเพิ่มขึ้นอย่างต่อเนื่อง จะกลายเป็นเสียงรบกวน
มันทำงานจนถึงอันที่ 10 หากตัวเลขเกิน 15 สถานะจะ โหลดแล้วแต่ใช้งานไม่ได้ Copilot ไม่สามารถพิจารณาทุกสิ่งที่สำคัญได้ในคราวเดียว และในท้ายที่สุด กฎก็ถูก “อ่านซ้ำ” ในบริบทของขณะนั้น ทำให้เกิดอุบัติเหตุ
เมื่อมาถึงจุดนี้เราจึงตัดสินใจเปลี่ยนทิศทาง
หยุดเพิ่มกฎเพิ่มเติม เปลี่ยนเป็นระบบที่ให้คุณค้นหาและแยกเฉพาะกฎที่คุณต้องการในตอนนี้
นี่คือวิธีที่เรามาถึง RAG + MCP
3. วิธีแก้ปัญหา — สร้าง RAG “ที่จัดเก็บข้อมูลภายนอก” สำหรับ Copilot
เมื่อรวบรวมสิ่งต่าง ๆ เข้าด้วยกัน สิ่งที่ฉันต้องการคือ:
| สิ่งที่คุณต้องการ | ทำไม |
|---|---|
| สถานที่สะสมประวัติความล้มเหลว | ทิ้งความเป็นมา ความเจ็บปวด และบริบทของกฎ |
| กลไกที่สามารถเรียกได้แบบไดนามิกระหว่างการสนทนา | รับเฉพาะสิ่งที่คุณต้องการในขณะนี้ |
| กลไกเพื่อให้แน่ใจว่าสิ่งสำคัญไม่ลืม | บทเรียนเก่าไม่ฝังอยู่ในบันทึกใหม่ |
| นักบินสามารถใช้วิจารณญาณของตนเองได้ | ผู้ใช้ไม่จำเป็นต้องผ่านด้วยตนเองในแต่ละครั้ง |
สิ่งนี้มีผลโดยตรงกับสถาปัตยกรรม RAG (Retrieval-Augmented Generation)
[บทเรียนจากอดีต บทสรุป และการตระหนักรู้]
↓ สร้างเวกเตอร์และบันทึก
[ChromaDB (คงอยู่)]
↑ ค้นหาตามบริบทการสนทนา
[Copilot] ← ใส่หน่วยความจำที่เกี่ยวข้องลงใน prompt → ตัดสินใจอย่างเหมาะสม
อย่างไรก็ตาม เพื่อที่จะ เรียกสิ่งนี้อย่างเป็นธรรมชาติจาก Copilot เราจำเป็นต้องมีกลไกเพิ่มเติมนี่คือจุดที่ MCP (Model Context Protocol) เข้ามามีบทบาท
4. MCP เป็นสะพาน
MCP เป็นโปรโตคอลแบบเปิดที่พัฒนาโดย Anthropic และเป็นมาตรฐานสำหรับการเชื่อมต่อไคลเอนต์ LLM และเซิร์ฟเวอร์เครื่องมือ/ทรัพยากรภายนอก GitHub Copilot Chat ยังรองรับ MCP และด้วยการลงทะเบียนเซิร์ฟเวอร์ Copilot จึงสามารถ เรียกใช้เครื่องมือได้โดยอัตโนมัติ
[แชทนักบิน]
↓ โปรโตคอล MCP (stdio)
[เซิร์ฟเวอร์ MCP สมองของฉัน]
├─ search_memory(query, ...) ← เรียกโดย Copilot ตามต้องการ
└─ add_note(ข้อความ, ประเภท, ...) ← บันทึกข้อสรุปที่ได้รับระหว่างการสนทนาทันที
↓
[การฝัง ChromaDB + Ollama]
สองจุด:
- Copilot ค้นหาโดยอัตโนมัติ — แม้ว่าผู้ใช้จะไม่พูดว่า “ตรวจสอบบันทึกที่ผ่านมา” ทุกครั้ง Copilot จะตัดสินจากบริบทว่า “สิ่งนี้ดูเหมือนจะเป็นบันทึกที่เกี่ยวข้อง” และเรียก
search_memory - การบันทึกสามารถทำได้ทันที — ทันทีที่การสนทนาสิ้นสุดลงหรือผู้ใช้ชี้ให้เห็นบางสิ่ง Copilot จะโทรไปที่
add_noteและเพิ่มลงใน RAG → คุณสามารถอ้างอิงเองได้ในเซสชั่นถัดไป
“ลูปการเรียนรู้แบบเรียกซ้ำด้วยตนเอง” นี้เป็นสิ่งที่ instructions.md ไม่สามารถสร้างขึ้นได้
5. หัวใจของการนำไปปฏิบัติ
my-rag-brain แยกส่วนสำคัญของ src/mcp/server.py ออกจากที่เก็บ
5.1 คำจำกัดความของเซิร์ฟเวอร์
mcp.server.fastmcp.FastMCP อนุญาตให้คุณเผยแพร่ฟังก์ชัน Python เป็นเครื่องมือ MCP โดยเพียงแค่เพิ่มมัณฑนากรลงไป```หลาม
จาก mcp.server.fastmcp นำเข้า FastMCP
mcp = FastMCP(“สมองของฉัน”)
@mcp.tool() def search_memory (แบบสอบถาม: str, ประเภท: str = "", โดเมน: str = "", ด้านบน: int = 5) -> str: """ค้นหาปฏิสัมพันธ์ บทเรียน ความรู้ และแนวคิดในอดีตในภาษาธรรมชาติ
เมื่อพิจารณาแล้วว่าบันทึกในอดีตที่เกี่ยวข้องมีความจำเป็นในระหว่างการทำงาน จะสามารถเรียกบันทึกเหล่านั้นได้โดยอัตโนมัติ
สร้างแบบสอบถามด้วยตนเองจากบริบทปัจจุบัน อย่าให้ผู้ใช้ระบุ
"""
# ... แบบสอบถาม ChromaDB ...
@mcp.tool() def add_note (ข้อความ: str, ประเภท: str = “note”, ลำดับความสำคัญ: str = "") -> str: """บันทึกการตระหนักรู้ ข้อตกลง บทเรียนที่ได้รับ และข้อสรุประหว่างการสนทนาใน RAG ณ จุดเกิดเหตุ
เมื่อใดที่จะบันทึก:
- เมื่อถึงข้อสรุปหลังจากการหารือกับผู้ใช้ → type="conclusion"
- เมื่อผู้ใช้ชี้หรือแก้ไข → type="lesson", Priority="high"
- เมื่อมีการสร้างความรู้ทางเทคนิคใหม่ → type="knowledge"
"""
# ... ChromaDB เขียน ...
ถ้า name == “main”: mcp.run(ขนส่ง=“stdio”)
ประเด็นสำคัญคือ **วิธีเขียน docstring** นี่ไม่ใช่แค่ความคิดเห็นเท่านั้น มันเป็นพื้นฐานที่ Copilot ตัดสินใจว่าเมื่อใดจะเรียกใช้เครื่องมือนี้
> “เมื่อผู้ใช้ชี้หรือแก้ไข → type="lesson", Priority="high""โดย **ชี้แจงเงื่อนไขการโทร** ด้วยวิธีนี้ Copilot จะสามารถระบุได้จากบทสนทนาว่า ``นี่คือช่วงเวลาที่ควรบันทึก''
### 5.2 การตั้งค่าด้าน VS Code
ลงทะเบียนเซิร์ฟเวอร์ในไฟล์การตั้งค่า VS Code MCP (`.vscode/mcp.json` หรือ settings.json)
```.json
{
"mcpเซิร์ฟเวอร์": {
"สมองของฉัน": {
"type": "stdio",
"command": "C:\\Users\\y_104\\git\\my-rag-brain\\venv\\Scripts\\python.exe",
"args": ["C:\\Users\\y_104\\git\\my-rag-brain\\src\\mcp\\server.py"],
"env": {
"การเข้ารหัส PYTHONIO": "utf-8"
}
}
}
}
เมื่อคุณเปิด Copilot Chat ระบบจะเริ่มทำงานโดยอัตโนมัติ และ search_memory และ add_note จะปรากฏในรายการเครื่องมือ
5.3 ChromaDB + โอลามา
สำหรับการฝัง ให้ใช้ nomic-embed-text ของ Ollama (768 มิติ แข็งแกร่งในหลายภาษา รวมถึงภาษาญี่ปุ่น)
นำเข้า chromadb
จาก chromadb.utils.embedding_functions นำเข้า OllamaEmbeddingFunction
embedding_fn = OllamaEmbeddingFunction(
url = "http://localhost:11434/api/embeddings",
model_name = "nomic-embed-text",
)ลูกค้า = chromadb.PersistentClient (เส้นทาง = "chroma_db")
คอลเลกชัน = client.get_or_create_collection (
ชื่อ = "dev",
embedding_function=embedding_fn,
)
การดำเนินงานในท้องถิ่นเต็มรูปแบบ บันทึกจะไม่ถูกส่งไปภายนอก
6. Design Judgment — 6 วิธีป้องกันอุบัติเหตุไม่ให้เกิดขึ้นอีก
นี่คือจุดสำคัญของบทความนี้ เพียงค้นหาก็ไม่หยุดอุบัติเหตุ การออกแบบหกแบบที่เราสังเกตเห็นในการใช้งานจริงมีประสิทธิภาพ
6.1 Recency Boost — อย่าปล่อยให้บทเรียนล่าสุดสูญหาย
การค้นหาเวกเตอร์จะใส่ “บันทึกที่ใกล้กับข้อความค้นหา” ไว้ที่ด้านบนสุด แต่บางครั้งบทเรียนสำคัญใหม่ๆ อาจปะปนกับบันทึกเก่าที่ไม่เกี่ยวข้องกัน
มาตรการตอบโต้: ขณะนี้ประเภท lesson / conclusion เป็นการได้มาแบบผสมของ “ผลลัพธ์ที่คล้ายคลึงกัน 5 อันดับแรก + การบังคับฉีดผลลัพธ์ 3 รายการล่าสุด”
RECENCY_TYPES = {"บทเรียน", "บทสรุป"}
ความซ้ำซ้อน_พิเศษ = 3
# ความเกี่ยวข้อง: การค้นหาเวกเตอร์ปกติ
สำหรับคอลในคอลเลกชัน:
res = col.query(query_texts=[query], n_results=top, โดยที่=where_clause)
# ... เพิ่มใน all_results ...# ความใหม่: บทเรียน/ข้อสรุปบังคับให้เสร็จสิ้น N รายการล่าสุดตามลำดับวันที่จากมากไปน้อย
ถ้า Effective_type ใน RECENCY_TYPES:
สำหรับคอลในคอลเลกชัน:
rec = col.get(where={"source_type": {"$eq":efficient_type}},
รวม=["เอกสาร", "ข้อมูลเมตา"])
items = sorted(rec_items, key=lambda x: x[1].get("date", ""), Reverse=True)
สำหรับเอกสาร เมตาในรายการ[:RECENCY_EXTRA]:
# บังคับให้เพิ่มใน all_results หากยังไม่ได้กล่าวถึง (แม้จะอยู่นอกข้อจำกัดด้านบนก็ตาม)
...
ผลลัพธ์ที่ได้รับความนิยมจะถูกแท็กด้วย [RECENT] ดังนั้น Copilot จึงรับรู้ว่านี่เป็นเรื่องใหม่ตามลำดับเวลาและให้ความสำคัญกับมัน บทเรียนของเหตุการณ์ “ได้โปรด” ก็คือมันจะไม่หายไปแม้ว่าวันที่ที่เขียนไว้จะเก่าไปแล้วก็ตาม
6.2 ลำดับความสำคัญสูง — จัดลำดับความสำคัญของบทเรียนที่สำคัญ
หากคุณระบุ priority="high" สำหรับ add_note เรกคอร์ดนั้นจะถูก จัดเรียงไว้ที่ด้านบนเสมอ ในผลลัพธ์การค้นหา
all_results.sort(
key=lambda x: (0 ถ้า x[2].get("priority") == "high" อย่างอื่น 1, x[0])
)
กฎของร้านค้าที่คุณต้องการปฏิบัติตามอย่างยิ่ง เช่น “ขอคำยืนยันก่อนดำเนินการเสมอ” ที่นี่ บทเรียนที่ได้รับจากอุบัติเหตุร้ายแรง เช่น เหตุการณ์ “ได้โปรด” ถือเป็น ลำดับความสำคัญสูงทั้งหมด### 6.3 session_context.md ส่งออกอัตโนมัติ — เชื่อมโยงไปยังเซสชันถัดไป
ทันทีหลังจากบันทึกประเภท บทเรียน / บทสรุป / ความรู้ / โปรไฟล์ ด้วย add_note, export_context.py จะถูกเรียกใช้โดยอัตโนมัติและสร้าง session_context.md ซึ่งรวบรวมการบันทึกล่าสุด
def _refresh_session_context() -> ไม่มี:
"""เริ่ม send_context.py แบบอะซิงโครนัสหลังจาก add_note สำเร็จ
อัปเดต session_context.md ทันที """
ถ้าไม่ใช่ _refresh_lock.acquire(blocking=False):
return # ข้ามหากวิ่งอยู่แล้ว (มาตรการตอบโต้สภาพการแข่งขัน)ลอง:
proc = กระบวนการย่อย Popen (
[str(_PYTHON), str(_EXPORT_SCRIPT)],
cwd=str(รูท), env=env,
stdout=กระบวนการย่อย.DEVNULL, stderr=กระบวนการย่อย.DEVNULL,
)
def _copy_after_done():
ลอง:
proc.wait (หมดเวลา = 30)
src = ROOT / "context_output" / "session_context.md"
ถ้า src.exists():
shutil.copy2(str(src), str(_MEMORIES_SESSION / "session_context.md"))
ในที่สุด:
_refresh_lock.ปล่อย()
threading.Thread(target=_copy_after_done, daemon=True).start()
ข้อยกเว้น ข้อยกเว้น:
_refresh_lock.ปล่อย()
session_context.md ที่สร้างขึ้นจะถูกคัดลอกโดยตรงไปยัง โฟลเดอร์ GitHub Copilot Memory Tool
C:\Users\...\globalStorage\github.copilot-chat\memory-tool\memories\session\session_context.md
````ด้วยวิธีนี้ บทเรียนและข้อสรุปล่าสุดจะถูกโหลดโดยอัตโนมัติ **ในครั้งถัดไปที่คุณเริ่ม Copilot Chat** **“หน่วยความจำที่ครอบคลุมเซสชัน” ได้รับการตระหนักรู้แล้ว**
### 6.4 บันทึกกิจกรรม — เพื่อปรับปรุงคุณภาพการค้นหาอย่างต่อเนื่อง
เพิ่มการเรียกเครื่องมือทั้งหมดไปที่ `logs/activity.jsonl`
```หลาม
def _log_activity (เครื่องมือ: str, **kwargs) -> ไม่มี:
ลอง:
รายการ = {"ts": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "เครื่องมือ": เครื่องมือ, **kwargs}
ด้วย _ACTIVITY_LOG.open("a", encoding="utf-8") เป็น f:
f.write(json.dumps(รายการ, Sure_ascii=False) + "\n")
ข้อยกเว้น ข้อยกเว้น:
ผ่าน
สิ่งที่ต้องบันทึก:
search_memory: แบบสอบถาม พิมพ์ จำนวนการเข้าชม คะแนนระยะทางขั้นต่ำต่อประเภทadd_note: ประเภท, ลำดับความสำคัญ, ตัวอย่างข้อความ, solved_query (จะอธิบายในภายหลัง)
ด้วยวิธีนี้ คุณสามารถตรวจสอบได้ในภายหลังว่า Copilot ใช้แบบสอบถามประเภทใดในการค้นหา RAG คุณสามารถค้นหารูปแบบการสืบค้นที่ส่งผลให้การค้นหาไร้ผล และดำเนินการ PDCA เพื่อปรับปรุงวิธีการเขียนบทเรียน
6.5 เกณฑ์แบบไดนามิก (solved_query) - บันทึก “การค้นหานี้ได้รับการแก้ไขแล้ว”
solved_query: str เป็นอาร์กิวเมนต์สำหรับ add_note
เมื่อ Copilot โทรไปที่ add_note “ทันทีหลังจากแก้ไขปัญหาของผู้ใช้” มันจะบันทึก คำค้นหาที่นำไปสู่ปัญหา ด้วย```หลาม
add_note(
text=“อย่าตีความว่า “กรุณา” เป็นคำสั่งในการดำเนินการ อย่าลืมยืนยัน (บทเรียนหนี 24 PATCH)”,
ประเภท = “บทเรียน”,
ลำดับความสำคัญ = “สูง”,
Solved_query=“กรุณายืนยันการดำเนินการ”,
)
เมื่อรวบรวมข้อมูลนี้แล้ว จะสามารถดำเนินการวิเคราะห์หลังชันสูตรของการแมป ``การสืบค้นใดจะนำไปสู่บทเรียนใด'' ซึ่งสามารถใช้เป็นพื้นฐานสำหรับการปรับเกณฑ์และการปรับโครงสร้างการสืบค้น
### 6.6 Atomic Lock — หลบหนีจากสภาพการแข่งขัน
`_refresh_session_context` เป็นกระบวนการที่หนักหน่วง (export_context.py เริ่มกระบวนการย่อยและเขียนมันออกมา) ดังนั้นจึงมีความเสี่ยงที่จะเกิดการแข่งขันหากมีการร้องขอหลายรายการเริ่มต้นในเวลาเดียวกัน
ในตอนแรก ฉันใช้ `is_set()` / `set()` เพื่อยกเว้น แต่สุดท้ายฉันก็เขียนมันในรูปแบบ **TOCTOU (Time-Of-Check to Time-Of-Use)** ซึ่งทำให้ฉันมีกรณีที่กระบวนการทั้งสองเริ่มต้นพร้อมกัน
วิธีแก้ปัญหา: เปลี่ยนเป็น **atomic Try-Lock** ใน `acquire(blocking=False)` ของ `threading.Lock`
```หลาม
_refresh_lock = เธรดล็อค()
def _refresh_session_context() -> ไม่มี:
# พยายามรับอะตอม หากล็อคไว้แล้วให้คืนทันที
ถ้าไม่ใช่ _refresh_lock.acquire(blocking=False):
กลับมา
ลอง:
# ... การประมวลผลหนัก ...
ข้อยกเว้น ข้อยกเว้น:
_refresh_lock.ปล่อย()
แม้ว่าจะเรียบง่าย แต่ การควบคุมพิเศษที่แม่นยำ ก็เป็นข้อกำหนดที่จำเป็นสำหรับเซิร์ฟเวอร์ MCP เพื่อให้สามารถทนต่อการดำเนินการด้านการผลิตได้
---## 7. เป็นยังไงบ้างตอนที่ได้ลอง?
นี่เป็นการประเมินแบบอัตนัย แต่มีบางสิ่งที่เปลี่ยนแปลงไปอย่างเห็นได้ชัด
7.1 อุบัติเหตุลักษณะเดียวกันนี้ไม่เคยเกิดขึ้นอีกเลยหลังจากเหตุการณ์ “ได้โปรด”
ด้วยการผสมผสานระหว่างบทเรียนของ priority="high" + บูสต์ [RECENT] Copilot จะเรียก search_memory และดึงข้อมูลเคสที่ผ่านมาทันทีที่ “โปรด” ปรากฏในการสนทนา
[ฉัน] ได้โปรด
[Copilot] (search_memory("กรุณาเรียกใช้การยืนยัน") โทร)
→ รับ "บทเรียน: อย่าตีความว่า "ได้โปรด" เป็นคำสั่งให้ปฏิบัติ แต่ให้ขอคำยืนยันเสมอ"
[Copilot] ยืนยันว่า "คุณแน่ใจหรือไม่ว่าต้องการรัน X ตอนนี้"
ฉันเห็นการยิงนี้หลายครั้งในบันทึกกิจกรรม ต่างจากตอนที่ฉันเขียน instructions.md ตอนนี้กฎจะมีผล ในเวลาที่เหมาะสม ขึ้นอยู่กับบริบท
7.2 บทสรุปของการอภิปรายจะถ่ายทอดสดใน “เซสชันถัดไป”
หลังจากหารือเกี่ยวกับการตัดสินใจในการออกแบบและกฎการปฏิบัติงานแล้ว มีอีกหลายกรณีที่ Copilot โทรหา add_note(type="conclusion") และบันทึกโดยธรรมชาติ
ตัวอย่างเช่น ทันทีหลังจากการสนทนาสรุปว่า ```PROJECT_STATUS.md` จะไม่ได้รับการอัปเดตทุกครั้ง แต่จะอัปเดตเฉพาะเมื่อมีการเผยแพร่เท่านั้น” Copilot จะบันทึกทันที
บันทึกจะได้รับการสืบทอดโดยอัตโนมัติในเซสชันถัดไปผ่านทาง session_context.md ผู้ใช้ไม่จำเป็นต้องจำอีกต่อไปว่า “กฎการปฏิบัติงานที่เราพูดคุยกันเมื่อสัปดาห์ที่แล้วมีอะไรบ้าง” ทุกครั้ง
7.3 ความพยายามในการเขียนบทเรียนหายไป
เมื่อฉันเพิ่มบรรทัดฐานให้กับ instructions.md ด้วยตนเอง ทุกครั้งที่มีเหตุการณ์เกิดขึ้น ฉันจะ:
- แยกแยะสิ่งที่เกิดขึ้น
- วิเคราะห์ว่าทำไมมันถึงเกิดขึ้น
- สร้างข้อความที่จะเลื่อนระดับเป็นกฎ
- แก้ไข
.instructions.md - เตือน Copilot ให้ “ปกป้องมันในครั้งต่อไป”
ฉันต้องทำทั้งหมดตอนนี้ Copilot จัดการทุกอย่างตั้งแต่คำแนะนำของผู้ใช้ไปจนถึง add_note(type="lesson", priority="high") เพิ่งได้คุยกัน ก็กลายเป็นโครงสร้างที่สะสมบทเรียนเอาไว้
8. ข้อควรทราบ/ข้อจำกัด
จากนี้ฉันจะเขียนจุดอ่อนโดยสุจริตของฉันด้วย
8.1 ขึ้นอยู่กับคุณภาพการฝัง
nomic-embed-text เก่งภาษาญี่ปุ่น แต่ความแม่นยำในการค้นหาอาจลดลงเมื่อใช้คำค้นหาสั้น ๆ เช่น “Please” การค้นหาด้วยข้อความค้นหาแบบยาวในบริบทจะเพิ่มอัตราการเข้าชม แต่คุณไม่สามารถควบคุมได้ว่า Copilot จะสร้างข้อความค้นหาประเภทใด
8.2 Recency Boost จะส่งผลย้อนกลับหากมีโน้ตเก่ามากเกินไป
เมื่อ lesson สะสมเกิน 100 กรณี มีกรณีที่ 3 กรณีล่าสุดมีประสิทธิภาพมากกว่า “บทเรียนเก่าจริง”** ขณะนี้ เรากำลังดำเนินการด้วยการส่งเสริมลำดับความสำคัญด้วยตนเองและย้ายลำดับความสำคัญแบบเก่าไปที่ knowledge ในระยะยาว เราอาจจำเป็นต้องมี ระบบที่ช่วยให้บทเรียนมี “ระยะเวลาให้บริการ”
8.3 การใช้ทรัพยากรของ LLM ภายในองค์กร (Ollama)
เนื่องจากถือว่า Ollama ทำงานอยู่ในเครื่อง หน่วยความจำและ CPU จะถูกถอดออกไป มันไม่ก่อให้เกิดอันตรายใดๆ อย่างแท้จริงต่อสภาพแวดล้อมการพัฒนาของฉัน แต่อาจเป็นปัญหากับเครื่องที่มีข้อจำกัดด้านทรัพยากร การใช้การฝัง OpenAI API แทนนั้นง่ายกว่า แต่มาพร้อมกับข้อดีข้อเสียของการย้ายข้อมูลออก
8.4 ความยากลำบากในการแบ่งปัน “เพื่อนที่คุณเลี้ยงดู” กับผู้อื่น
ระบบนี้ใช้งานได้กับ RAG ของฉัน (ประวัติการสนทนา บทเรียนที่ได้รับ นิสัย) ดังนั้นนักพัฒนารายอื่นจึงไม่สามารถใช้มันและพูดว่า “ฉันจะให้คุณยืมสักหน่อย” หากคุณทำให้เป็น RAG ทั่วไปสำหรับทีม ความเป็นตัวตนจะจางหายไป ความสมดุลระหว่างการเพิ่มประสิทธิภาพส่วนบุคคลและโครงสร้างพื้นฐานทั่วไป ถือเป็นความท้าทายในอนาคต
9. เกี่ยวกับการออกแบบระบบเพื่อ “บำรุง” AI
สุดท้ายนี้มีบางอย่างที่ฉันอยากจะบอกว่ามันเกินกว่าทฤษฎีทางเทคนิคนิดหน่อยตอนที่ฉันเขียนบรรทัดฐาน 15 ข้อสำหรับ instructions.md ฉันคิดว่าฉันกำลัง ให้ความรู้แก่ Copilot ให้คำแนะนำและทำให้พวกเขาปฏิบัติตาม ฉันจะดุคุณถ้าคุณไม่ปฏิบัติตาม มันเป็น ความสัมพันธ์ที่โดดเด่น
ตั้งแต่เปลี่ยนมาใช้ RAG + MCP คุณภาพของความสัมพันธ์ก็เปลี่ยนไป Copilot โทรไปที่ search_memory และตรวจสอบความล้มเหลวของตัวเองในอดีตก่อนที่จะเคลื่อนย้าย บันทึกบทสรุปของการสนทนาด้วยตัวเองด้วย add_note นักบินมีประวัติของตัวเองและมีการอ้างอิงถึงตัวมันเอง
นี่เป็นเหมือน การทำงานร่วมกัน มากกว่า การศึกษา ฉันไม่ได้เป็นคนเขียนโค้ดอีกต่อไป แต่เป็นคนที่ตอบสนองต่อการสนทนา Copilot ไม่ใช่ผู้ที่ได้รับคำสั่งอีกต่อไป แต่เป็นผู้สั่งสมประสบการณ์ของตัวเอง
การใช้ผู้ช่วย AI ต่อไปอาจหมายถึง การเติบโตไปพร้อมกับพันธมิตร แทนที่จะ ใช้เครื่องมือ
อย่างน้อยฉันก็รู้สึกแบบนั้นทุกวันที่ได้ร่วมงานกับ Copilot และ Claude Code
สรุป
.instructions.mdnorm ใช้งานไม่ได้หากมีมากกว่า 15 ชิ้น. จำเป็นต้องมีกลไกในการ “ดึง” กฎที่เหมาะสมขึ้นอยู่กับบริบท- RAG + MCP ช่วยให้ Copilot มี หน่วยความจำภายนอก ทำให้สามารถค้นหาและบันทึกบทเรียนที่ผ่านมาระหว่างการสนทนาได้โดยอัตโนมัติ
- เพียงแค่สามารถค้นหาไม่เพียงพอ การออกแบบทั้ง 6 แบบมีประสิทธิภาพในการป้องกันอุบัติเหตุไม่ให้เกิดขึ้นอีก: การเพิ่มความใหม่ / ลำดับความสำคัญ / การส่งออกอัตโนมัติ session_context / บันทึกกิจกรรม / ขีดจำกัดแบบไดนามิก / การล็อคแบบอะตอมมิก
- หลังจากนำไปใช้งาน หลังจากเหตุการณ์ “ได้โปรด” อุบัติเหตุที่คล้ายกันก็ไม่เกิดขึ้นอีก ความพยายามในการเขียนบทเรียนก็หายไปเช่นกัน
- มีข้อจำกัด. การฝังคุณภาพ “ในการให้บริการ” ของบทเรียน ทรัพยากรในท้องถิ่น และอุปสรรคในการปรับเปลี่ยนในแบบของคุณ
- คุณภาพของความสัมพันธ์เปลี่ยนจาก ด้านการศึกษา เป็นการทำงานร่วมกัน ฉันรู้สึกว่านี่เป็นผลกำไรที่ยิ่งใหญ่ที่สุดของฉันบทความที่เกี่ยวข้อง:
- [ฉันใช้ GitHub Copilot เป็นเวลา 1 เดือนและ Claude Code เป็นเวลา 2 วัน — พันธมิตรด้านการเขียนโค้ดและตัวแทนเป็นคนละเรื่องกัน] (/blog/copilot-vs-claude-code) — การเชื่อมต่อของระบบ MCP นี้กับเรื่องราวที่ฉันทำก่อนที่จะย้ายไปยัง Claude Code
เราจะเก็บสะสมบทเรียนที่ได้รับมาต่อไป พรุ่งนี้จะต้องมีความล้มเหลวแบบตลกๆ เกิดขึ้นด้วย