ป้อนประวัติการสนทนาของ Copilot Chat และ Claude Code ลงใน ChromaDB และค้นหา "ตัวตนในอดีต" ของคุณ
🔗 สารบัญซีรีส์: บทความนี้เป็น ฉบับการใช้งาน (2) ของซีรีส์ บันทึกการปฏิบัติงานของผู้ช่วย AI - บันทึกการปฏิบัติสำหรับการเพิ่มรหัส Copilot / Claude ในฐานะคู่หูของคุณ
สิ่งที่คุณสามารถเรียนรู้ได้จากบทความนี้
- ตำแหน่งและโครงสร้าง ของบันทึกการสนทนา (JSONL) ที่ถูกบันทึกโดยอัตโนมัติโดย VSCode Copilot Chat และ Claude Code
- ความแตกต่างในรูปแบบ JSONL แต่ละรูปแบบและ การออกแบบให้รองรับด้วยอินเทอร์เฟซทั่วไป
- วิธีค้นหา “อดีตที่ผ่านมา” ในภาษาธรรมชาติโดยการใช้เวกเตอร์ด้วย ChromaDB + Ollama
- ขั้นตอนในการส่งโดยอัตโนมัติเมื่อสิ้นสุดเซสชันโดยใช้ Stop hook ของ Claude Code
- เอฟเฟกต์และประเด็นที่ควรทราบหลังจากสะสมเซสชันหลายสิบครั้ง
กลุ่มเป้าหมาย
- ผู้ที่ต้องการ ใช้การสนทนากับผู้ช่วย AI เป็นความทรงจำถาวร
- ผู้ที่อาศัยบันทึกการค้นหาทุกครั้งเพื่อถามว่า “ตอนนั้นแก้ปัญหายังไง”
- ผู้ที่ต้องการเพิ่ม ฟังก์ชันนำเข้าบันทึกการสนทนา ให้กับ RAG ของตนเอง
- ผู้ที่ใช้ VSCode Copilot Chat / Claude Code หรือทั้งสองอย่าง
สภาพแวดล้อมการทำงาน
| รายการ | เวอร์ชั่น |
|---|---|
| ระบบปฏิบัติการ | วินโดวส์ 11 |
| หลาม | 3.13 (venv) |
| ChromaDB | โหมดถาวร (PersistentClient) |
| การฝัง | โอลมะ nomic-embed-text (768 มิติ) |
| VSCode Copilot Chat | บันทึกการถอดเสียง JSONL อัตโนมัติไปที่ workspaceStorage |
| รหัสคลอด | บันทึกเซสชัน JSONL โดยอัตโนมัติไปที่ ~/.claude/projects/ |
1. บทนำ — “อ
ะไรคือวิธีแก้ไขปัญหานั้น”ช่วงเวลาเช่นนี้กลายเป็นเรื่องปกติมากขึ้นเมื่อคุณทำงานร่วมกับผู้ช่วย AI ทุกวัน
วิธีแก้ปัญหาการเข้ารหัสอักขระของ PowerShell ที่ Copilot สอนฉันตอนนั้นคืออะไร
สัปดาห์ที่แล้ว ฉันได้พูดคุยกับ Claude Code และตัดสินใจเกี่ยวกับ “การออกแบบบายพาสการรับรองความถูกต้องโดยใช้โปรไฟล์ dev” ข้อสรุปคืออะไร
ฉันรู้สึกเหมือนฉันกำลังจะก้าวเข้าสู่กับดักที่ฉันเหยียบเมื่อเดือนที่แล้วอีกครั้ง…
ควรบันทึกการสนทนาไว้ที่ใดที่หนึ่งเป็นไฟล์ JSONL แต่ชื่อไฟล์คือ UUID และเนื้อหาเป็น JSON หลายแสนบรรทัด เป็นการยากที่จะค้นหาโดยใช้ grep และความปรารถนาเดิมคือ “ดึงวิธีแก้ปัญหาในอดีตโดยใช้ภาษาธรรมชาติ”
วันหนึ่งฉันก็ตระหนักได้
**บันทึกการสนทนาเป็น “เนื้อหาที่ดีที่สุดของ RAG” ที่สร้างขึ้นทุกวันไม่ใช่หรือ? **
บล็อกทางเทคนิค เอกสารการออกแบบ คำตอบ Stack Overflow มี “ความรู้ของผู้อื่น” มากมาย แต่วิธีแก้ปัญหาเดียวที่คุณจะพบในบริบทของคุณเอง ด้วยคำพูดของคุณเอง และสำหรับปัญหาของคุณเองนั้นอยู่ในบันทึกการสนทนาของคุณเอง หากคุณใส่สิ่งนี้ลงใน RAG คุณสามารถสร้างเครื่องมือค้นหาที่ช่วยให้คุณสามารถค้นหา “ตัวตนในอดีต” ของคุณได้อย่างแท้จริง
บทความนี้จะอธิบายวิธีการสร้างกลไกนี้สำหรับทั้ง Copilot Chat และ Claude Code
2. การถอดเสียงสองประเภท
ขั้นแรก จัดระเบียบว่าแต่ละไฟล์จะบันทึกที่ไหนและในรูปแบบใด
2.1 VSCode Copilot Chat
บันทึกไปที่:
C:\Users\<ผู้ใช้>\AppData\Roaming\Code\User\workspaceStorage\<workspace-hash>\GitHub.copilot-chat\transcripts\<uuid>.jsonl
มีไดเร็กทอรีที่แฮชสำหรับแต่ละพื้นที่ทำงาน (โฟลเดอร์ที่เปิดใน VSCode) และโฟลเดอร์ transcripts/ ถูกขุดในไดเร็กทอรีนั้น และ JSONL ที่มีชื่อ UUID จะถูกซ้อนกัน
โครงสร้าง JSONL (ประยุกต์):
{"type":"user.message","data":{"content":"How to write Virtual Threads in Java 21?"},"timestamp":"..."}
{"type":"assistant.message","data":{"content":"`Thread.ofVirtual().start(() -> { ... })`..."},"timestamp":"..."}
{"type":"assistant.turn_end","data":{...}}
1 แถว = 1 กิจกรรม ข้อความผู้ใช้/ผู้ช่วยสามารถระบุได้ด้วยฟิลด์ type และ data.content มีข้อความเป็นสตริง เรียบง่าย.
2.2 รหัสคลอดด์
บันทึกไปที่:
C:\Users\<ผู้ใช้>\.claude\projects\<project-slug>\<session-id>.jsonl
มีโฟลเดอร์สำหรับแต่ละโปรเจ็กต์ (กระสุนที่แปลงจากเส้นทางแบบเต็มของที่เก็บ) และในโฟลเดอร์นั้นจะมี JSONL พร้อมชื่อ ID เซสชัน
โครงสร้าง JSONL (ประยุกต์):
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"…"}]}}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"…"},{"type":"thinking","thinking":"…"},{"type":"tool_use","name":"Read","input":{...}}]}}
{"type":"queue-operation","operation":"enqueue",...}
{"type":"attachment",...}
{"type":"file-history-snapshot",...}
อันนี้ซับซ้อนนิดหน่อย:
typeฟิลด์คือ"user"/"assistant"แต่ เนื้อหาซ้อนอยู่ในอาร์เรย์ของmessage.content- แต่ละองค์ประกอบของอาร์เรย์เป็น บล็อกเนื้อหา และ
typeแบ่งออกเป็น"text"/"thinking"/"tool_use"เป็นต้น - ข้อความของผู้ใช้มี แท็กอัตโนมัติ เช่น
<system-reminder><ide_opened_file> - เหตุการณ์ Meta เช่น
queue-operationattachmentfile-history-snapshotก็อยู่ใน JSONL เดียวกันเช่นกัน
กล่าวโดยสรุป Copilot Chat เป็นรูปแบบง่ายๆ โดยที่ “1 ข้อความ = 1 ข้อความ” และ Claude Code เป็นรูปแบบที่มีโครงสร้างโดยที่ “อาร์เรย์บล็อกเนื้อหา + เหตุการณ์เมตาผสมกัน” แม้จะเรียกว่า “ประวัติการสนทนา” เดียวกัน แต่รูปแบบก็แตกต่างกัน
3. ความท้าทายและการออกแบบทั่วไป
ฉันต้องการจัดการทั้งสองอย่างในอินเทอร์เฟซเดียว ดังนั้นฉันจึงจัดระเบียบมันแบบนี้
ขั้นตอนการประมวลผลทั่วไป
[ไฟล์ JSONL]
↓ การแยกวิเคราะห์ (ขึ้นอยู่กับรูปแบบ)
[คู่ข้อความผู้ใช้ / ผู้ช่วย (= รอบ)]
↓ การแบ่งส่วน (ทั่วไป)
[id/ข้อความ/ข้อมูลเมตาที่ตั้งค่าไว้สำหรับ ChromaDB]
↓ upsert (ทั่วไป)
[คอลเลกชัน ChromaDB]
การออกแบบเป็นเช่นนั้นเฉพาะส่วนที่ขึ้นอยู่กับรูปแบบ (การแยกวิเคราะห์) เท่านั้นที่จะถูกนำไปใช้แยกกัน และทุกอย่างหลังจากการแยกชิ้นส่วนจะได้รับมาตรฐานอย่างสมบูรณ์ โดยเฉพาะ:
ingest_conversation.py— Parser สำหรับ Copilot Chat + เรียกกระบวนการป้อนข้อมูลทั่วไปingest_claude_code.py— Parser สำหรับ Claude Code + เรียกกระบวนการอินพุตทั่วไปแบบเดียวกันsrc/db/store.py’singest_chunks()— ChromaDB ที่เติมตรรกะที่เรียกโดยทั้งคู่
กฎการแบ่งส่วน
หน่วยการสนทนาตามธรรมชาติคือคู่ “ผู้ใช้ 1 ตา + ผู้ช่วย 1 คำตอบ” สิ่งนี้เรียกว่า turns
ขีดจำกัดสูงสุดของการฝังในครั้งเดียวจะอยู่ที่ MAX_CHUNK_CHARS = 1200 เป็นโซนปลอดภัยสำหรับ nomic-embed-text และเราตัดสินใจรวม 3 รอบเป็น 1 ชิ้น
TURNS_PER_CHUNK = 3
MAX_CHUNK_CHARS = 1200
def turns_to_chunks(turns: list[dict], session_id: str, date_str: str) -> list[dict]:
chunks = []
for i in range(0, len(turns), TURNS_PER_CHUNK):
group = turns[i:i + TURNS_PER_CHUNK]
lines = []
for t in group:
lines.append(f"[user] {t['user']}")
lines.append(f"[AI] {t['assistant']}")
lines.append("")
text = "\n".join(lines)
if len(text) > MAX_CHUNK_CHARS:
text = text[:MAX_CHUNK_CHARS]
chunk_index = i // TURNS_PER_CHUNK
chunks.append({
"id": f"{session_id}::chunk_{chunk_index}",
"text": text,
"metadata": {
"source_type": "conversation",
"source_file": session_id,
"title": f"Conversation session {date_str} (part {chunk_index + 1})",
"date": date_str,
"tags": "conversation,copilot", # or "conversation,claude-code"
"chunk_index": chunk_index,
},
})
return chunks
มีเพียง tags ของข้อมูลเมตาเท่านั้นที่ถูกแยกความแตกต่างด้วย “copilot” หรือ “claude-code” และที่เหลือก็เหมือนกันโดยสิ้นเชิง ตอนนี้ เมื่อคุณ rag search การสนทนากับ Copilot และ Claude Code จะปรากฏในผลการค้นหาโดยไม่คำนึงถึง
4. รวม Copilot Chat
ตัวแยกวิเคราะห์นี้เป็นแกนหลักของ Copilot Chat (ingest_conversation.py)
def parse_conversation(jsonl_path: Path) -> list[dict]:
"""Extract user/AI message pairs from JSONL"""
turns = []
user_msg = None
with open(jsonl_path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
record = json.loads(line)
except json.JSONDecodeError:
continue
rtype = record.get("type", "")
timestamp = record.get("timestamp", "")
if rtype == "user.message":
content = record["data"].get("content", "").strip()
if content:
user_msg = {"content": content, "timestamp": timestamp}
elif rtype == "assistant.message":
content = record["data"].get("content", "").strip()
if content and user_msg:
turns.append({
"user": user_msg["content"],
"assistant": content,
"timestamp": user_msg["timestamp"],
})
user_msg = None
return turns
เพียงเลือกโฟลว์ user.message → Assistant.message ตามลำดับและโหลดลงใน turns type ความเรียบง่ายของ parser สามารถใส่ได้ 30 บรรทัด ฉันชื่นชมความซื่อสัตย์ในส่วนของ Copilot Chat
ตรวจจับการถอดเสียงล่าสุดโดยอัตโนมัติได้อย่างง่ายดาย:
TRANSCRIPT_BASE = Path(r"C:\Users\<user>\AppData\Roaming\Code\User\workspaceStorage")
def find_latest_transcript() -> Path:
"""Auto-detect latest transcripts across all workspaces"""
candidates = []
if TRANSCRIPT_BASE.exists():
for jsonl in TRANSCRIPT_BASE.rglob("*.jsonl"):
if "transcripts" in jsonl.parts:
candidates.append(jsonl)
if not candidates:
raise FileNotFoundError(...)
return max(candidates, key=lambda p: p.stat().st_mtime)
ค้นหาพื้นที่ทำงานทั้งหมดซ้ำด้วย rglob และส่งคืน JSONL ล่าสุดด้วย mtime ฉันเผยแพร่สิ่งนี้ให้กับผู้ใช้ผ่านคำสั่ง rag conv
# Insert the latest conversation with one command
rag conv
# Input by specifying a specific past session
rag conv "C:\path\to\specific.jsonl"
5. ผสมผสานรหัส Claude — ต่อสู้กับเสียงรบกวน
นี่คือสิ่งที่น่าสนใจเล็กน้อย Claude Code ผสมกับเหตุการณ์เมตามากมายนอกเหนือจากการสนทนา ดังนั้นจึงจำเป็นต้องมีตัวกรอง
5.1 สิ่งของที่ต้องนำออก/ทิ้ง
type | บางสิ่งบางอย่าง | นำเข้า |
|---|---|---|
user | ข้อความผู้ใช้ | ✅ อย่างไรก็ตาม เฉพาะบล็อกข้อความเท่านั้นที่ถูกแยกออกจากอาร์เรย์ content |
assistant | การตอบสนองของ AI | ✅ ในทำนองเดียวกัน ให้แยกเฉพาะบล็อกข้อความ |
queue-operation | การดำเนินการคิว (เหตุการณ์การประมวลผลภายใน) | ❌ |
attachment | ข้อมูลไฟล์แนบ | ❌ |
file-history-snapshot | ประวัติไฟล์ | ❌ |
ai-title | การกำหนดชื่อเซสชัน | ❌ |
last-prompt | เมตาดาต้าพร้อมท์สุดท้าย | ❌ |
5.2 กำลังประมวลผลอาร์เรย์บล็อกเนื้อหา
User/AI ทั้งข้อความ message.content เป็นอาร์เรย์และมีประเภทบล็อกผสม
def _extract_text_blocks(content) -> str:
"""Concatenate and return only text block from message.content"""
if isinstance(content, str):
return content.strip()
if not isinstance(content, list):
return ""
parts = []
for block in content:
if not isinstance(block, dict):
continue
if block.get("type") == "text":
txt = block.get("text", "")
if isinstance(txt, str) and txt.strip():
parts.append(txt.strip())
return "\n\n".join(parts)
บล็อกอื่นที่ไม่ใช่ text (thinking / tool_use / tool_result) จะถูกข้ามไป thinking เป็นการคิดภายในของ AI ดังนั้นจึงเป็นการดีกว่าที่จะไม่รวมไว้ในโฟลว์ของการสนทนา เนื่องจากเสียงรบกวนในการค้นหาจะลดลง และ tool_use เป็น JSON ที่มีโครงสร้าง ดังนั้นจึงไม่เหมาะสำหรับการค้นหาข้อความ
5.3 การลบแท็กที่แทรกอัตโนมัติ
ข้อความของผู้ใช้ผสมกับแท็กที่ Claude Code แทรกโดยอัตโนมัติ
<system-reminder>The TodoWrite tool hasn't been used recently...</system-reminder>
<ide_opened_file>The user opened the file ...</ide_opened_file>
<command-message>...</command-message>
หากคุณป้อน RAG โดยมีจำนวนที่เหลือ เมื่อคุณค้นหา “สิ่งที่พูดในการสนทนานั้น” เนื้อหาแท็ก (เสียงรบกวนทั่วไป) จะถูกโจมตี งั้นฉันจะเอามันออก
NOISE_TAG_RE = re.compile(
r"<(system-reminder|ide_opened_file|ide_selection|command-message|command-name|command-args|local-command-stdout)>.*?</\1>",
re.DOTALL,
)
def _strip_noise(text: str) -> str:
if not text:
return ""
cleaned = NOISE_TAG_RE.sub("", text)
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned) # Clean up empty lines
return cleaned.strip()
DOTALL ตัดข้ามตัวแบ่งบรรทัดพร้อมกัน เพียงทำเช่นนี้ ฉันก็พบว่ามีความแม่นยำในการค้นหาเพิ่มขึ้น 30%
5.4 ตัวพาร์เซอร์
เมื่อรวมสิ่งเหล่านี้เข้าด้วยกัน parser สำหรับ Claude Code จะมีลักษณะดังนี้:
def parse_conversation(jsonl_path: Path) -> list[dict]:
turns: list[dict] = []
pending_user: dict | None = None
with open(jsonl_path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
record = json.loads(line)
except json.JSONDecodeError:
continue
rtype = record.get("type")
msg = record.get("message", {}) or {}
if rtype == "user":
content = msg.get("content") if isinstance(msg, dict) else None
text = _strip_noise(_extract_text_blocks(content))
if text:
pending_user = {"content": text, "timestamp": record.get("timestamp", "")}
elif rtype == "assistant":
content = msg.get("content") if isinstance(msg, dict) else None
text = _extract_text_blocks(content) # AI response does not require denoising
if text and pending_user:
turns.append({
"user": pending_user["content"],
"assistant": text,
"timestamp": pending_user["timestamp"],
})
pending_user = None
return turns
มันเป็นตรรกะ “การซ้อนคู่” แบบเดียวกับสำหรับ Copilot แต่ประเด็นสำคัญคือ การแยกบล็อกและการกำจัดสัญญาณรบกวนจะถูกประกบกันในขั้นตอนก่อนหน้า
6. รหัส Claude จะถูกป้อนโดยอัตโนมัติด้วย Stop hook
สำหรับ Copilot Chat นั้น rag conv จะถูกดำเนินการด้วยตนเอง แต่ Claude Code มีกลไกที่เรียกว่า Stop hook คำสั่งใดๆ ก็สามารถดำเนินการได้ทันทีที่เซสชันสิ้นสุดลง ซึ่งจะทำให้คุณสามารถ ทำให้เป็นอัตโนมัติ ได้อย่างเต็มที่
เขียนสิ่งนี้ลงใน `~/.claude/settings.json
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"C:\\Users\\<user>\\git\\my-rag-brain\\scripts\\claude_code_stop_hook.ps1\""
}
]
}
]
}
}
สคริปต์ PowerShell ที่เรียกว่ามีลักษณะเช่นนี้
# read JSON from stdin, extract transcript_path and start ingest
$stdin = [Console]::In.ReadToEnd()
$payload = $stdin | ConvertFrom-Json
$transcript = $payload.transcript_path
if (-not (Test-Path $transcript)) { return }
# Start in background (don't block Stop hook for long time)
$env:PYTHONIOENCODING = 'utf-8'
Start-Process -FilePath "<venv>\python.exe" `
-ArgumentList @("<my-rag-brain>\src\pipeline\ingest_claude_code.py", $transcript) `
-WindowStyle Hidden `
-RedirectStandardOutput $stdoutLog `
-RedirectStandardError $stderrLog
สองจุด:
- อ่าน
transcript_pathจาก stdin — Claude Code ส่งให้เราใน JSON - การเริ่มต้นพื้นหลังด้วย
Start-Process— เพื่อหลีกเลี่ยงการบล็อก Stop hook เป็นเวลานาน
ตอนนี้ เมื่อคุณปิด Claude Code เซสชันจะถูกแทรกลงใน ChromaDB โดยอัตโนมัติ ไม่มีอะไรที่ต้องทำด้วยตนเอง
7. มีอะไรเปลี่ยนแปลงบ้าง? ความรู้สึกปลอดภัยที่ช่วยให้คุณสามารถค้นหา “ตัวตนในอดีต” ของคุณ
หลังจากผ่านไปหลายสิบครั้ง เหตุการณ์เช่นนี้ก็เริ่มเกิดขึ้น
7.1 “คุณแก้ปัญหานั้นได้อย่างไร” ปัญหาหายไป
เมื่อฉันพบข้อผิดพลาดในการเข้ารหัสอักขระใน PowerShell:
ค้นหาเศษผ้า "อักขระที่อ่านไม่ออกของ PowerShell UTF-8"
จากนั้นโซลูชัน 5 อันดับแรกที่สร้างขึ้นในอดีตเมื่อพูดถึงปัญหาเดียวกันกับ Copilot และ Claude Code จะถูกส่งคืน คุณสามารถจำได้ทันทีว่า “โอ้ ฉันใส่ PYTHONIOENCODING=utf-8 ไว้ในตัวแปรสภาพแวดล้อม”
7.2 ข
้อสรุปของการโต้แย้งถูกทำให้ถาวรในเซสชันที่มีการหารือเกี่ยวกับการตัดสินใจในการออกแบบและนโยบายการดำเนินงาน การเลี้ยวทั้ง 3 ครั้งก่อนและหลังการสรุปจะถูกบันทึกเป็นชิ้นเดียว หลังจากนั้น หากคุณค้นหาว่า ปัจจัยในการตัดสินใจที่อยู่เบื้องหลังการตัดสินใจออกแบบนั้นคืออะไร'' ลำดับการสนทนาทั้งหมดจะปรากฏขึ้น **บริบทของ ทำไมเราถึงทำ” ที่ไม่สามารถเขียนลงในเอกสารการออกแบบได้** มักถูกทิ้งไว้ข้างหลัง
7.3 คุณจะมีโอกาสทำผิดพลาดน้อยลง
กับดักที่ “ตัวตนในอดีต” ของฉันก้าวเข้าไปนั้นถูกซ่อนไว้อย่างลึกลับใกล้กับตัวตนปัจจุบันของฉัน เมื่อคุณค้นหาบันทึกที่ผ่านมาด้วย rag search "<関連キーワード>" ก่อนที่จะเริ่มงานใหม่ คุณมักจะได้รับการเตือนถึง บันทึกที่ถูกลืม
โดยเฉพาะอย่างยิ่งหลังจากติดตั้งการแทรกตะขอหยุดอัตโนมัติของ Claude Code ความทรงจำของฉันก็สะสมโดยที่ฉันไม่รู้ตัว ดังนั้นประสบการณ์การค้นหาของฉันจึงดีขึ้นเรื่อยๆ
8. ข้อควรทราบ/ข้อจำกัด
8.1 ความเสี่ยงจากการปะปนข้อมูลที่เป็นความลับ
การสนทนาอาจรวมถึง ข้อความที่ตัดตอนมาจากโค้ด, คีย์ API, URL และข้อมูลส่วนบุคคล ไม่มีปัญหาตราบใดที่ปิดไปยัง ChromaDB ในเครื่อง แต่จำเป็นอย่างยิ่งที่คุณจะต้องไม่ส่งไดเรกทอรี ChromaDB ไปยังพื้นที่เก็บข้อมูลสาธารณะโดยใช้ Git ฉันมี chroma_db/ ใน .gitignore
8.2 กฎการกำจัดเสียงรบกวนต้องมีการบำรุงรักษา
แท็กการแทรกอัตโนมัติของ Claude Code อาจเพิ่มขึ้นในอนาคต รายการแท็กที่ถูกลบโดย NOISE_TAG_RE ครั้งนี้มาจากช่วงที่ฉันสังเกตเห็น มีค่าใช้จ่ายในการดำเนินการ เพิ่มแท็กใหม่ตามที่ปรากฏ
8.3 การฝังการสนทนาแบบเก่าอาจสูญเสียความแม่นยำหากไม่สร้างใหม่
เมื่อคุณอัปเดตโมเดลการฝังของ Ollama การฝังของก้อนเก่าและการฝังของก้อนใหม่จะอยู่ใน ช่องว่างที่แตกต่างกันเล็กน้อย จำเป็นต้องฝังใหม่ทั้งหมด เพื่อความเข้ากันได้อย่างสมบูรณ์ ซึ่งทำได้โดยใช้ rag bulk เพื่อส่งรายการทั้งหมดอีกครั้ง
8.4 ความแม่นยำในการค้นหาอาจลดลงหากคุณ “ใส่ทุกอย่างลงไป”
ข้อผิดพลาดที่ไม่คาดคิดคือการรวม เซสชันเริ่มต้นที่มีเสียงดังรบกวน และ เซสชันที่จบลงด้วยข้อผิดพลาด จะลดความแม่นยำในการค้นหา source_file ด้วยการกรองด้วยข้อมูลเมตาหรือโดยการแบ่ง source_type ออกเป็นส่วนเล็กๆ คุณสามารถจำกัดการค้นหาของคุณให้แคบลงได้
9. สรุป
- VSCode Copilot Chat บันทึกประวัติการสนทนาไปที่
workspaceStorage/.../transcripts/*.jsonlโดยอัตโนมัติ และ Claude Code บันทึกประวัติการสนทนาไปที่~/.claude/projects/<slug>/<session-id>.jsonlโดยอัตโนมัติ - JSONL ทั้งสองมีโครงสร้างที่แตกต่างกัน (Copilot นั้นเรียบง่าย Claude Code มีบล็อกอาร์เรย์ + เหตุการณ์เมตาผสมกัน) แต่สามารถดูดซับได้โดยใช้พาร์เซอร์แยกกัน + การกำหนดมาตรฐานและต่อมา
- การกำจัดเสียงรบกวน (การลบแท็ก เช่น
<system-reminder>) ส่งผลให้ความแม่นยำในการค้นหาแตกต่างกัน 30% - ด้าน Claude Code สามารถทำงานอัตโนมัติได้อย่างสมบูรณ์ด้วย Stop hook + การเริ่มต้นพื้นหลัง
- หลังจากสะสมเซสชันได้หลายสิบเซสชัน คุณจะสามารถค้นหา “ตัวตนในอดีต” ในภาษาธรรมชาติได้ ฉันจำวิธีแก้ปัญหานั้น การตัดสิน และกับดักนั้นได้ทันที
- การจัดการข้อมูลที่เป็นความลับ การบำรุงรักษากฎการกำจัดสัญญาณรบกวน การสร้างใหม่เมื่ออัปเดตโมเดลการฝัง — แม้ว่าจะมีค่าใช้จ่ายในการดำเนินการ แต่ผลตอบแทนที่ได้รับก็มีจำนวนมากอย่างท่วมท้นบทความที่เกี่ยวข้อง:
- กลไกในการป้องกันไม่ให้ Copilot ทำผิดพลาดซ้ำสองครั้ง — ออกแบบให้มี “ความทรงจำในการสนทนา” ด้วย RAG + MCP — การใช้งานเซิร์ฟเวอร์ MCP สำหรับ Copilot เพื่อค้นหาอัตโนมัติแบบเรียลไทม์ที่ป้อนประวัติการสนทนาในบทความนี้
- ฉันใช้ GitHub Copilot เป็นเวลาหนึ่งเดือน และใช้ Claude Code เป็นเวลาสองวัน พาร์ทเนอร์และเจ้าหน้าที่เขียนโค้ดเป็นสองสิ่งที่แตกต่างกัน — ความแตกต่างในบุคลิกของ Copilot และ Claude Code
แม้ว่า AI จะลืมฉันก็จะบันทึกมันไว้ จากนั้นเมื่อจำเป็นให้ “เตือน” จากด้านนี้ นี่คือทัศนคติพื้นฐานของฉันเมื่อทำงานกับ AI