{"title":"Semantic Search (Embeddings)","slug":"semantic-search","category":"concepts","summary":"การค้นหา memory เชิงแนวคิดโดยใช้ vector embedding — ค้นหาตามความหมาย ไม่ใช่แค่ keyword","audience":["human","llm"],"tags":["concept","semantic","embeddings","vector-search"],"difficulty":"advanced","updated":"2026-06-27","word_count":427,"read_minutes":2,"lang":"th","translated":true,"requested_lang":"th","content_markdown":"\n# Semantic Search (Embeddings)\n\nSynapse รองรับ semantic search โดยใช้ vector embedding ต่างจาก FTS5 (keyword matching) ตรงที่ semantic search หา memory ตาม **ความหมาย** — แม้ไม่มี keyword ตรงกัน\n\n## วิธีการทำงาน\n\n```\n1. Memory stored → embedding generated → vector stored\n2. Search query → embedding generated → vector compared\n3. Cosine similarity → top N results returned\n```\n\n### embedding คืออะไร?\n\nembedding เป็นการแทน text ด้วย numerical vector text ที่มีความหมายคล้ายกันจะมี vector คล้ายกัน Synapse สร้าง vector (เช่น 1536 มิติ) สำหรับเนื้อหา memory แต่ละรายการ\n\n### Cosine similarity\n\nเพื่อหา memory ที่คล้ายเชิง semantic Synapse คำนวณ cosine similarity ระหว่าง query vector และ memory vector แต่ละตัว similarity สูง = เกี่ยวข้องมากกว่า\n\n## เมื่อใดควรใช้ Semantic Search\n\n### ใช้ semantic search เมื่อ:\n\n- คุณต้องการ \"memory เกี่ยวกับ X\" โดย X ถูกอธิบายต่างจากที่เก็บ\n- FTS5 ไม่ส่งกลับผลลัพธ์ (ไม่มี keyword ตรง)\n- คุณต้องการการจัดกลุ่มเชิงแนวคิด (เช่น memory \"deployment\" ทั้งหมด แม้บางอันพูดถึง \"release\")\n- Query เป็นคำถาม: \"เราจัดการ authentication อย่างไร?\"\n\n### ใช้ FTS5 เมื่อ:\n\n- คุณรู้ keyword ที่แน่นอน\n- คุณต้องการ logic boolean (AND, OR, NOT)\n- คุณต้องการ response ในระดับ sub-millisecond\n- คุณต้องการ phrase matching\n\n## Endpoint\n\n### GET /memory/semantic-search\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/semantic-search?q=container+orchestration\"\n```\n\nResponse:\n\n```json\n{\n  \"results\": [\n    {\n      \"id\": \"mem_001\",\n      \"category\": \"project\",\n      \"key\": \"project_synapse_deployment\",\n      \"content\": \"Synapse deployed using Docker Swarm on vps1...\",\n      \"tags\": [\"docker\", \"swarm\", \"deployment\"],\n      \"similarity\": 0.89\n    },\n    {\n      \"id\": \"mem_042\",\n      \"category\": \"fact\",\n      \"key\": \"kubernetes_cluster\",\n      \"content\": \"We use Kubernetes for production orchestration...\",\n      \"tags\": [\"kubernetes\", \"orchestration\"],\n      \"similarity\": 0.84\n    }\n  ]\n}\n```\n\n## ตัวอย่าง\n\n### หา memory เกี่ยวกับ deployment\n\n```bash\n# FTS5 might miss some — semantic catches all\ncurl .../memory/semantic-search?q=deployment+process\n```\n\nส่งกลับ memory เกี่ยวกับ \"deployment\", \"release\", \"publishing\", \"rolling out\" ฯลฯ\n\n### หารูปแบบ authentication\n\n```bash\ncurl .../memory/semantic-search?q=how+do+users+log+in\n```\n\nส่งกลับ memory เกี่ยวกับ login, auth, JWT, session management, OAuth ฯลฯ\n\n### หา memory ที่คล้ายกัน\n\n```bash\n# Find memories similar to a specific one\ncurl .../memory/related/mem_001\n```\n\nใช้ semantic similarity (ผ่าน tag ที่ใช้ร่วมกันและ embedding vector)\n\n## การสร้าง Embedding\n\n### เมื่อใดจะสร้าง embedding?\n\n- **เมื่อเก็บ memory** — หาก embeddings service ถูกกำหนดค่า, embedding ถูกสร้างแบบ synchronous\n- **Batch generation** — `POST /memory/embed-batch` สร้าง embedding สำหรับ memory ที่ยังไม่มี\n- **Async update** — เมื่อเนื้อหาถูกอัปเดต, embedding ถูกสร้างใหม่\n\n### Embedding provider\n\nSynapse รองรับ embedding provider ที่กำหนดค่าได้:\n\n- **OpenAI** (`text-embedding-3-small`, `text-embedding-3-large`)\n- **Local model** (ผ่าน Ollama หรือคล้ายกัน)\n- **Custom** (implement embeddings interface)\n\nกำหนดค่าผ่าน environment variable:\n\n```bash\nEMBEDDINGS_PROVIDER=openai\nEMBEDDINGS_API_KEY=sk-...\nEMBEDDINGS_MODEL=text-embedding-3-small\n```\n\n### การสร้างแบบ Batch\n\nสำหรับ mind ที่มี memory หลายรายการที่ยังไม่มี embedding:\n\n```bash\n# Generate embeddings for up to 100 memories\ncurl -X POST https://synapse.schaefer.zone/memory/embed-batch \\\n  -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"limit\": 100}'\n\n# Check progress\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     https://synapse.schaefer.zone/memory/embed-batch-status\n```\n\n## ประสิทธิภาพ\n\n| การดำเนินการ | Latency |\n|-----------|---------|\n| สร้าง embedding (OpenAI) | 100-200ms |\n| Semantic search (1k memory) | 50-100ms |\n| Semantic search (10k memory) | 200-500ms |\n| การสร้างแบบ batch (100 memory) | 10-20s |\n\n> [!NOTE]\n> Semantic search ช้ากว่า FTS5 เนื่องจากการคำนวณ vector ใช้ FTS5 สำหรับ keyword ที่รู้ ใช้ semantic สำหรับ query เชิงแนวคิด\n\n## ข้อจำกัด\n\n### ต้นทุน embedding\n\nหากใช้ OpenAI การสร้าง embedding มีค่าใช้จ่าย (~$0.02 ต่อ 1M token สำหรับ text-embedding-3-small) สำหรับ 10,000 memory เฉลี่ย 100 token ต่อรายการ ประมาณ $0.02 — น้อยมาก\n\n### Cold start\n\nmemory ที่เก็บก่อนกำหนดค่า embedding จะไม่มี embedding รัน `POST /memory/embed-batch` เพื่อ backfill\n\n### การพึ่งพา provider\n\nหาก embedding provider ล่ม semantic search จะล้มเหลวอย่างนุ่มนวล (ส่งกลับผลลัพธ์ว่างหรือ error) FTS5 ยังทำงานได้\n\n## เมื่อ Embedding ไม่พร้อมใช้งาน\n\nหาก embeddings service ไม่ถูกกำหนดค่า:\n\n- `GET /memory/semantic-search` ส่งกลับ 503 Service Unavailable\n- `POST /memory` ยังทำงานได้ (เพียงแค่ไม่สร้าง embedding)\n- FTS5 search ยังทำงานได้\n\n## แนวทางปฏิบัติที่ดีที่สุด\n\n> [!TIP]\n> - **ใช้ semantic สำหรับ query เชิงแนวคิด** — \"เราจัดการ X อย่างไร?\"\n> - **ใช้ FTS5 สำหรับคำเฉพาะ** — \"docker swarm\"\n> - **Backfill embedding เป็นคาบ** — `POST /memory/embed-batch`\n> - **ตรวจสอบสุขภาพ provider** — semantic search พึ่งพามัน\n> - **รวมกับ tag** — semantic + tag filter จำกัดผลลัพธ์\n\n## ขั้นตอนถัดไป\n\n- [FTS5 Search](/docs/concepts/fts5-search)\n- [Memory API](/docs/api/memory)\n- [Architecture](/docs/concepts/architecture)\n","content_html":"<h1>Semantic Search (Embeddings)</h1>\n<p>Synapse รองรับ semantic search โดยใช้ vector embedding ต่างจาก FTS5 (keyword matching) ตรงที่ semantic search หา memory ตาม <strong>ความหมาย</strong> — แม้ไม่มี keyword ตรงกัน</p>\n<h2>วิธีการทำงาน</h2>\n<pre><code class=\"hljs language-plaintext\">1. Memory stored → embedding generated → vector stored\n2. Search query → embedding generated → vector compared\n3. Cosine similarity → top N results returned</code></pre><h3>embedding คืออะไร?</h3>\n<p>embedding เป็นการแทน text ด้วย numerical vector text ที่มีความหมายคล้ายกันจะมี vector คล้ายกัน Synapse สร้าง vector (เช่น 1536 มิติ) สำหรับเนื้อหา memory แต่ละรายการ</p>\n<h3>Cosine similarity</h3>\n<p>เพื่อหา memory ที่คล้ายเชิง semantic Synapse คำนวณ cosine similarity ระหว่าง query vector และ memory vector แต่ละตัว similarity สูง = เกี่ยวข้องมากกว่า</p>\n<h2>เมื่อใดควรใช้ Semantic Search</h2>\n<h3>ใช้ semantic search เมื่อ:</h3>\n<ul>\n<li>คุณต้องการ &quot;memory เกี่ยวกับ X&quot; โดย X ถูกอธิบายต่างจากที่เก็บ</li>\n<li>FTS5 ไม่ส่งกลับผลลัพธ์ (ไม่มี keyword ตรง)</li>\n<li>คุณต้องการการจัดกลุ่มเชิงแนวคิด (เช่น memory &quot;deployment&quot; ทั้งหมด แม้บางอันพูดถึง &quot;release&quot;)</li>\n<li>Query เป็นคำถาม: &quot;เราจัดการ authentication อย่างไร?&quot;</li>\n</ul>\n<h3>ใช้ FTS5 เมื่อ:</h3>\n<ul>\n<li>คุณรู้ keyword ที่แน่นอน</li>\n<li>คุณต้องการ logic boolean (AND, OR, NOT)</li>\n<li>คุณต้องการ response ในระดับ sub-millisecond</li>\n<li>คุณต้องการ phrase matching</li>\n</ul>\n<h2>Endpoint</h2>\n<h3>GET /memory/semantic-search</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/semantic-search?q=container+orchestration&quot;</span></code></pre><p>Response:</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span>\n  <span class=\"hljs-attr\">&quot;results&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span>\n    <span class=\"hljs-punctuation\">{</span>\n      <span class=\"hljs-attr\">&quot;id&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;mem_001&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project_synapse_deployment&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;Synapse deployed using Docker Swarm on vps1...&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;docker&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;swarm&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;deployment&quot;</span><span class=\"hljs-punctuation\">]</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;similarity&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-number\">0.89</span>\n    <span class=\"hljs-punctuation\">}</span><span class=\"hljs-punctuation\">,</span>\n    <span class=\"hljs-punctuation\">{</span>\n      <span class=\"hljs-attr\">&quot;id&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;mem_042&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;fact&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;kubernetes_cluster&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;We use Kubernetes for production orchestration...&quot;</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;kubernetes&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;orchestration&quot;</span><span class=\"hljs-punctuation\">]</span><span class=\"hljs-punctuation\">,</span>\n      <span class=\"hljs-attr\">&quot;similarity&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-number\">0.84</span>\n    <span class=\"hljs-punctuation\">}</span>\n  <span class=\"hljs-punctuation\">]</span>\n<span class=\"hljs-punctuation\">}</span></code></pre><h2>ตัวอย่าง</h2>\n<h3>หา memory เกี่ยวกับ deployment</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># FTS5 might miss some — semantic catches all</span>\ncurl .../memory/semantic-search?q=deployment+process</code></pre><p>ส่งกลับ memory เกี่ยวกับ &quot;deployment&quot;, &quot;release&quot;, &quot;publishing&quot;, &quot;rolling out&quot; ฯลฯ</p>\n<h3>หารูปแบบ authentication</h3>\n<pre><code class=\"hljs language-bash\">curl .../memory/semantic-search?q=how+<span class=\"hljs-keyword\">do</span>+<span class=\"hljs-built_in\">users</span>+<span class=\"hljs-built_in\">log</span>+<span class=\"hljs-keyword\">in</span></code></pre><p>ส่งกลับ memory เกี่ยวกับ login, auth, JWT, session management, OAuth ฯลฯ</p>\n<h3>หา memory ที่คล้ายกัน</h3>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Find memories similar to a specific one</span>\ncurl .../memory/related/mem_001</code></pre><p>ใช้ semantic similarity (ผ่าน tag ที่ใช้ร่วมกันและ embedding vector)</p>\n<h2>การสร้าง Embedding</h2>\n<h3>เมื่อใดจะสร้าง embedding?</h3>\n<ul>\n<li><strong>เมื่อเก็บ memory</strong> — หาก embeddings service ถูกกำหนดค่า, embedding ถูกสร้างแบบ synchronous</li>\n<li><strong>Batch generation</strong> — <code>POST /memory/embed-batch</code> สร้าง embedding สำหรับ memory ที่ยังไม่มี</li>\n<li><strong>Async update</strong> — เมื่อเนื้อหาถูกอัปเดต, embedding ถูกสร้างใหม่</li>\n</ul>\n<h3>Embedding provider</h3>\n<p>Synapse รองรับ embedding provider ที่กำหนดค่าได้:</p>\n<ul>\n<li><strong>OpenAI</strong> (<code>text-embedding-3-small</code>, <code>text-embedding-3-large</code>)</li>\n<li><strong>Local model</strong> (ผ่าน Ollama หรือคล้ายกัน)</li>\n<li><strong>Custom</strong> (implement embeddings interface)</li>\n</ul>\n<p>กำหนดค่าผ่าน environment variable:</p>\n<pre><code class=\"hljs language-bash\">EMBEDDINGS_PROVIDER=openai\nEMBEDDINGS_API_KEY=sk-...\nEMBEDDINGS_MODEL=text-embedding-3-small</code></pre><h3>การสร้างแบบ Batch</h3>\n<p>สำหรับ mind ที่มี memory หลายรายการที่ยังไม่มี embedding:</p>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Generate embeddings for up to 100 memories</span>\ncurl -X POST https://synapse.schaefer.zone/memory/embed-batch \\\n  -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n  -H <span class=\"hljs-string\">&quot;Content-Type: application/json&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;limit&quot;: 100}&#x27;</span>\n\n<span class=\"hljs-comment\"># Check progress</span>\ncurl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     https://synapse.schaefer.zone/memory/embed-batch-status</code></pre><h2>ประสิทธิภาพ</h2>\n<table>\n<thead>\n<tr>\n<th>การดำเนินการ</th>\n<th>Latency</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>สร้าง embedding (OpenAI)</td>\n<td>100-200ms</td>\n</tr>\n<tr>\n<td>Semantic search (1k memory)</td>\n<td>50-100ms</td>\n</tr>\n<tr>\n<td>Semantic search (10k memory)</td>\n<td>200-500ms</td>\n</tr>\n<tr>\n<td>การสร้างแบบ batch (100 memory)</td>\n<td>10-20s</td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-note\">Semantic search ช้ากว่า FTS5 เนื่องจากการคำนวณ vector ใช้ FTS5 สำหรับ keyword ที่รู้ ใช้ semantic สำหรับ query เชิงแนวคิด</div><h2>ข้อจำกัด</h2>\n<h3>ต้นทุน embedding</h3>\n<p>หากใช้ OpenAI การสร้าง embedding มีค่าใช้จ่าย (~$0.02 ต่อ 1M token สำหรับ text-embedding-3-small) สำหรับ 10,000 memory เฉลี่ย 100 token ต่อรายการ ประมาณ $0.02 — น้อยมาก</p>\n<h3>Cold start</h3>\n<p>memory ที่เก็บก่อนกำหนดค่า embedding จะไม่มี embedding รัน <code>POST /memory/embed-batch</code> เพื่อ backfill</p>\n<h3>การพึ่งพา provider</h3>\n<p>หาก embedding provider ล่ม semantic search จะล้มเหลวอย่างนุ่มนวล (ส่งกลับผลลัพธ์ว่างหรือ error) FTS5 ยังทำงานได้</p>\n<h2>เมื่อ Embedding ไม่พร้อมใช้งาน</h2>\n<p>หาก embeddings service ไม่ถูกกำหนดค่า:</p>\n<ul>\n<li><code>GET /memory/semantic-search</code> ส่งกลับ 503 Service Unavailable</li>\n<li><code>POST /memory</code> ยังทำงานได้ (เพียงแค่ไม่สร้าง embedding)</li>\n<li>FTS5 search ยังทำงานได้</li>\n</ul>\n<h2>แนวทางปฏิบัติที่ดีที่สุด</h2>\n<div class=\"callout callout-ok\"></div><h2>ขั้นตอนถัดไป</h2>\n<ul>\n<li><a href=\"/docs/concepts/fts5-search\">FTS5 Search</a></li>\n<li><a href=\"/docs/api/memory\">Memory API</a></li>\n<li><a href=\"/docs/concepts/architecture\">Architecture</a></li>\n</ul>\n","urls":{"html":"/docs/concepts/semantic-search","text":"/docs/concepts/semantic-search?format=text","json":"/docs/concepts/semantic-search?format=json","llm":"/docs/concepts/semantic-search?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}