Files

1 line
82 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "autolove111/fitters", "files": {"health-app/study/aid_learning_agent/assets/README/README_TH.md": {"1d1a93717421d10f6294c917a377ace11cb3c248": {"t": 1785595182.7709954, "n": 41588, "h": "5783901a5b4e35da", "c": "<div align=\"center\">\n\n<img src=\"../../assets/logo.png\" alt=\"AidLearning\" width=\"140\" style=\"border-radius: 15px;\">\n\n# AidLearning: ผู้ช่วยติวส่วนบุคคลแบบ Agent-Native\n\n<a href=\"https://trendshift.io/repositories/17099\" target=\"_blank\"><img src=\"https://trendshift.io/api/badge/repositories/17099\" alt=\"HKUDS%2FAidLearning | Trendshift\" style=\"width: 250px; height: 55px;\" width=\"250\" height=\"55\"/></a>\n\n[![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/downloads/)\n[![Next.js 16](https://img.shields.io/badge/Next.js-16-000000?style=flat-square&logo=next.js&logoColor=white)](https://nextjs.org/)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue?style=flat-square)](../../LICENSE)\n[![GitHub release](https://img.shields.io/github/v/release/HKUDS/AidLearning?style=flat-square&color=brightgreen)](https://github.com/HKUDS/AidLearning/releases)\n[![arXiv](https://img.shields.io/badge/arXiv-2604.26962-b31b1b?style=flat-square&logo=arxiv&logoColor=white)](https://arxiv.org/abs/2604.26962)\n\n[![Discord](https://img.shields.io/badge/Discord-Community-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/eRsjPgMU4t)\n[![Feishu](https://img.shields.io/badge/Feishu-Group-00D4AA?style=flat-square&logo=feishu&logoColor=white)](../../Communication.md)\n[![WeChat](https://img.shields.io/badge/WeChat-Group-07C160?style=flat-square&logo=wechat&logoColor=white)](https://github.com/HKUDS/AidLearning/issues/78)\n\n[คุณสมบัติเด่น](#-คุณสมบัติเด่น) · [เริ่มต้นใช้งาน](#-เริ่มต้นใช้งาน) · [สำรวจความสามารถ](#-สำรวจ-aidlearning) · [TutorBot](#-tutorbot--ติวเตอร์-ai-แบบถาวรและอัตโนมัติ) · [CLI](#%EF%B8%8F-aidlearning-cli--อินเทอร์เฟซแบบ-agent-native) · [ชุมชน](#-ชุมชนและระบบนิเวศ)\n\n[🇺🇸 English](../../README.md) · [🇨🇳 中文](README_CN.md) · [🇯🇵 日本語](README_JA.md) · [🇪🇸 Español](README_ES.md) · [🇫🇷 Français](README_FR.md) · [🇸🇦 العربية](README_AR.md) · [🇷🇺 Русский](README_RU.md) · [🇮🇳 हिन्दी](README_HI.md) · [🇵🇹 Português](README_PT.md) · [🇹🇭 ภาษาไทย](README_TH.md) · 🇵🇱 [Polski](README_PL.md)\n\n</div>\n\n---\n\n> 🤝 **ยินดีรับทุกรูปแบบการมีส่วนร่วม!** ดู [คู่มือการมีส่วนร่วม](../../CONTRIBUTING.md) สำหรับกลยุทธ์สาขา มาตรฐานโค้ด และจุดเริ่มต้น\n\n### 📦 ประวัติการเผยแพร่\n\n> **[2026.5.10]** [v1.3.10](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.10) — แก้ CORS สำหรับ Docker ระยะไกล, `DISABLE_SSL_VERIFY` ใน SDK providers, citation ใน code block และแยก Matrix E2EE เป็น add-on\n\n> **[2026.5.9]** [v1.3.9](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.9) — TutorBot รองรับ Zulip และ NVIDIA NIM, routing ของ thinking-model ปลอดภัยขึ้น, `aidlearning start`, tooltip ใน sidebar, และ session-store parity\n\n> **[2026.5.8]** [v1.3.8](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.8) — deployment แบบ multi-user ที่เปิดได้ตามต้องการ พร้อม workspace แยกผู้ใช้, admin grants, auth routes, และ scoped runtime access\n\n> **[2026.5.4]** [v1.3.7](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.7) — แก้ไข thinking-model/provider, แสดงประวัติ Knowledge index, และ Co-Writer clear/template editing ปลอดภัยขึ้น\n\n> **[2026.5.3]** [v1.3.6](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.6) — เลือกโมเดลจากคาตาล็อกสำหรับแชตและ TutorBot, RAG re-indexing ปลอดภัยขึ้น, แก้ token-limit ของ OpenAI Responses, และตรวจสอบ Skills editor\n\n> **[2026.5.2]** [v1.3.5](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.5) — ตั้งค่าการเปิดใช้งานในเครื่องราบรื่นขึ้น, RAG queries ปลอดภัยขึ้น, local embedding auth ชัดเจนขึ้น, และปรับแต่ง dark-mode ของ Settings\n\n> **[2026.5.1]** [v1.3.4](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.4) — Chat persistence บนหน้าหนังสือและ rebuild flows, อ้างอิงจากแชตไปหนังสือ, จัดการภาษา/การให้เหตุผลแข็งแกร่งขึ้น, เสริมความแข็งแกร่งการดึงเอกสาร RAG\n\n> **[2026.4.30]** [v1.3.3](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.3) — รองรับ embedding NVIDIA NIM และ Gemini, Space context รวมสำหรับประวัติแชต / สกิล / หน่วยความจำ, snapshot ของเซสชัน, ความทนทานของการทำดัชนี RAG ใหม่\n\n> **[2026.4.29]** [v1.3.2](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.2) — URL ปลายทาง embedding โปร่งใส, ความทนทาน re-index RAG เมื่อเวกเตอร์ที่ persist ไม่ถูกต้อง, ทำความสะอาดหน่วยความจำสำหรับเอาต์พุตโมเดล thinking, แก้รันไทม์ Deep Solve\n\n> **[2026.4.28]** [v1.3.1](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.1) — เสถียรภาพ: RAG routing ปลอดภัยขึ้นและตรวจสอบ embedding, Docker persistence, อินพุตปลอดภัยกับ IME, ความทนทาน Windows/GBK\n\n> **[2026.4.27]** [v1.3.0](https://github.com/HKUDS/AidLearning/releases/tag/v1.3.0) — ดัชนี KB แบบมีเวอร์ชันพร้อมเวิร์กโฟลว์ re-index, รีบิลด์ Knowledge workspace, embedding auto-discovery กับอะแดปเตอร์ใหม่, Space hub\n\n<details>\n<summary><b>รุ่นที่ผ่านมา (มากกว่า 2 สัปดาห์ที่แล้ว)</b></summary>\n\n> **[2026.4.25]** [v1.2.5](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.5) — แนบไฟล์ในแชตถาวรพร้อมลิ้นชักพรีวิว, pipeline ความสามารถที่รับรู้แนบไฟล์, ส่งออก Markdown ของ TutorBot\n\n> **[2026.4.25]** [v1.2.4](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.4) — แนบข้อความ / โค้ด / SVG, Setup Tour คำสั่งเดียว, ส่งออกแชต Markdown, UI จัดการ KB แบบกะทัดรัด\n\n> **[2026.4.24]** [v1.2.3](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.3) — แนบเอกสาร (PDF/DOCX/XLSX/PPTX), แสดงบล็อกการคิดของโมเดลให้เหตุผล, ตัวแก้เทมเพลต Soul, บันทึก Co-Writer ลงสมุด\n\n> **[2026.4.22]** [v1.2.2](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.2) — ระบบ Skills ที่ผู้ใช้สร้าง, ปรับประสิทธิ์อินพุตแชต, TutorBot สตาร์ทอัตโนมัติ, UI ห้องสมุดหนังสือ, โหมดเต็มจอของการแสดงผล\n\n> **[2026.4.21]** [v1.2.1](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.1) — จำกัดโทเคนต่อขั้นตอน, สร้างคำตอบใหม่ได้ทุกจุดเข้า, แก้ความเข้ากันได้ของ RAG และ Gemma\n\n> **[2026.4.20]** [v1.2.0](https://github.com/HKUDS/AidLearning/releases/tag/v1.2.0) — คอมไพเลอร์ Book Engine «หนังสือมีชีวิต», Co-Writer หลายเอกสาร, การแสดงผล HTML แบบโต้ตอบ, @-mention ธนาคารคำถามในแชต\n\n> **[2026.4.18]** [v1.1.2](https://github.com/HKUDS/AidLearning/releases/tag/v1.1.2) — แท็บ Channels แบบ schema-driven, รวม RAG เป็น pipeline เดียว, แยก chat prompts ออกเป็นไฟล์ภายนอก\n\n> **[2026.4.17]** [v1.1.1](https://github.com/HKUDS/AidLearning/releases/tag/v1.1.1) — ปุ่ม \"ตอบเลย\" ครอบคลุมทุกความสามารถ, Co-Writer scroll sync, แผงตั้งค่ารวม, ปุ่ม Stop ระหว่างสตรีม\n\n> **[2026.4.15]** [v1.1.0](https://github.com/HKUDS/AidLearning/releases/tag/v1.1.0) — ปรับปรุงการ parse LaTeX block math, ตั้งค่า LLM probe ผ่าน agents.yaml, forward extra headers ใน LLM factory, แก้ UUID ของ SaveToNotebookModal, คำแนะนำ Docker + local LLM และขยาย test suite\n\n> **[2026.4.14]** [v1.1.0-beta](https://github.com/HKUDS/AidLearning/releases/tag/v1.1.0-beta) — URL-based chat routing พร้อม bookmark ได้, ธีม Snow, WebSocket heartbeat & auto-reconnect พร้อม resume, ปรับ ChatComposer ให้เร็วขึ้น, overhaul embedding provider registry, Serper search provider, streaming idle timeout และขยาย test suite\n\n> **[2026.4.13]** [v1.0.3](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.3) — Question Notebook สำหรับทบทวนแบบทดสอบรวมศูนย์พร้อม bookmark & หมวดหมู่, รองรับ Mermaid diagram ใน Visualize, ตรวจจับ embedding model ไม่ตรง, รวม system message สำหรับ Qwen/vLLM, รองรับ LM Studio & llama.cpp และธีม Glass\n\n> **[2026.4.11]** [v1.0.2](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.2) — ปรับโครงสร้าง search consolidation ให้ง่ายขึ้นพร้อม SearXNG fallback, แก้ไข provider switch fix, ตั้ง runtime config ชัดเจนใน test runner และแก้ resource leak ฝั่ง frontend\n\n> **[2026.4.10]** [v1.0.1](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.1) — เพิ่ม Visualize capability ใหม่พร้อม Chart.js/SVG rendering pipeline, ป้องกัน quiz ซ้ำด้วย generation history, รองรับ o4-mini model และปรับปรุง server logging\n\n> **[2026.4.10]** [v1.0.0-beta.4](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.0-beta.4) — แสดงความคืบหน้า Embedding พร้อม retry เมื่อเจอ HTTP 429, จัดการ dependency ข้ามแพลตฟอร์มใน start tour และแก้ MIME validation ให้ case-insensitive\n\n> **[2026.4.8]** [v1.0.0-beta.3](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.0-beta.3) — ลบ litellm dependency ใช้ native OpenAI/Anthropic SDK providers แทน, รองรับ Math Animator บน Windows, parse JSON จาก LLM ให้ robust ขึ้น, แก้ KaTeX & navigation ใน Guided Learning และ i18n ภาษาจีนครบ\n\n> **[2026.4.7]** [v1.0.0-beta.2](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.0-beta.2) — ล้าง runtime cache สำหรับ hot settings reload, รองรับ MinerU nested output, แก้ mimic WebSocket, กำหนดขั้นต่ำ Python 3.11+ และปรับปรุง CI\n\n> **[2026.4.4]** [v1.0.0-beta.1](https://github.com/HKUDS/AidLearning/releases/tag/v1.0.0-beta.1) — เขียนสถาปัตยกรรมใหม่แบบ Agent-native (~200k บรรทัด) พร้อมโมเดลปลั๊กอิน 2 ชั้น (Tools + Capabilities), CLI & SDK entry points, TutorBot มัลติแชนแนล, Co-Writer, Guided Learning และ persistent memory\n\n> **[2026.1.23]** [v0.6.0](https://github.com/HKUDS/AidLearning/releases/tag/v0.6.0) — Session persistence, อัปโหลดเอกสารเพิ่มทีละไฟล์, import RAG pipeline ที่ยืดหยุ่น และ localization ภาษาจีนครบ\n\n> **[2026.1.18]** [v0.5.2](https://github.com/HKUDS/AidLearning/releases/tag/v0.5.2) — รองรับ Docling สำหรับ RAG-Anything, ปรับ logging system และแก้บั๊ก\n\n> **[2026.1.15]** [v0.5.0](https://github.com/HKUDS/AidLearning/releases/tag/v0.5.0) — Unified service configuration, เลือก RAG pipeline ต่อ knowledge base, ปรับ question generation ใหม่ และปรับแต่ง sidebar\n\n> **[2026.1.9]** [v0.4.0](https://github.com/HKUDS/AidLearning/releases/tag/v0.4.0) — รองรับ Multi-provider LLM & embedding, หน้า home ใหม่, แยก RAG module และ refactor environment variable\n\n> **[2026.1.5]** [v0.3.0](https://github.com/HKUDS/AidLearning/releases/tag/v0.3.0) — สถาปัตยกรรม PromptManager รวม, GitHub Actions CI/CD และ Docker image สำเร็จรูปบน GHCR\n\n> **[2026.1.2]** [v0.2.0](https://github.com/HKUDS/AidLearning/releases/tag/v0.2.0) — Docker deployment, อัปเกรด Next.js 16 & React 19, WebSocket security hardening และแก้ช่องโหว่สำคัญ\n\n</details>\n\n### 📰 ข่าวสาร\n\n> **[2026.4.19]** 🎉 ครบ 20k ดาวหลัง 111 วัน! ขอบคุณที่สนับสนุน — เราจะพัฒนาต่อเพื่อติวเตอร์เชิงบุคคลและฉลาดอย่างแท้จริง\n\n> **[2026.4.10]** 📄 งานวิจัยของเราลง arXiv แล้ว! อ่าน [พรีปรินต์](https://arxiv.org/abs/2604.26962) เพื่อทำความเข้าใจการออกแบบและแนวคิดของ AidLearning\n\n> **[2026.4.4]** นานมาแล้ว ✨ AidLearning v1.0.0 มาถึงแล้ว — วิวัฒนาการแบบ agent-native ที่เขียนสถาปัตยกรรมใหม่ตั้งแต่ต้น พร้อม TutorBot และการสลับโหมดอย่างยืดหยุ่น ภายใต้สัญญาอนุญาต Apache-2.0 บทใหม่เริ่มต้นขึ้น เรื่องราวของเรายังดำเนินต่อไป!\n\n> **[2026.2.6]** 🚀 เราไปถึง 10,000 ดาวภายในเพียง 39 วัน! ขอบคุณชุมชนที่ยอดเยี่ยมของเราสำหรับการสนับสนุน!\n\n> **[2026.1.1]** สวัสดีปีใหม่! มาร่วม [Discord](https://discord.gg/eRsjPgMU4t), [WeChat](https://github.com/HKUDS/AidLearning/issues/78) หรือ [Discussions](https://github.com/HKUDS/AidLearning/discussions) ของเรา — มาร่วมกำหนดอนาคตของ AidLearning กัน!\n\n> **[2025.12.29]** AidLearning เปิดตัวอย่างเป็นทางการ!\n\n## ✨ คุณสมบัติเด่น\n\n- **พื้นที่แชตแบบรวมศูนย์** — 6 โหมดในเธรดเดียว: Chat, Deep Solve, Quiz Generation, Deep Research, Math Animator และ Visualize ใช้บริบทร่วมกัน เริ่มจากถามง่าย ไปสู่การแก้ปัญหาแบบหลายเอเจนต์ สร้างภาพความคิด ออกแบบทดสอบ และเจาะลึกงานวิจัยโดยไม่เสียประวัติ\n- **AI Co-Writer** — พื้นที่ Markdown หลายเอกสาร AI เป็นผู้ร่วมเขียนระดับแรก: Rewrite, Expand, Shorten ดึงบริบทจาก knowledge base และเว็บ\n- **Book Engine** — เปลี่ยนวัสดุของคุณเป็น «หนังสือมีชีวิต» แบบมีโครงสร้างและโต้ตอบได้ ไปป์ไลน์หลายเอเจนต์ 13 ประเภทบล็อก (แบบทดสอบ แฟลชการ์ด ไทม์ไลน์ กราฟแนวคิด ฯลฯ)\n- **Knowledge Hub** — สร้าง knowledge base แบบ RAG-ready สมุดบันทึกสีสัน ธนาคารคำถาม และ Skills กำหนดสไตล์การสอน\n- **Persistent Memory** — AidLearning สร้างโปรไฟล์ผู้เรียนที่เติบโตอยู่ตลอดเวลา ใช้ร่วมกันข้ามทุกฟีเจอร์และทุก TutorBot ยิ่งใช้ยิ่งแม่นยำ\n- **TutorBot ส่วนตัว** — ไม่ใช่แค่ chatbot แต่เป็นติวเตอร์อัตโนมัติที่มี workspace, memory, บุคลิก และทักษะของตัวเอง ขับเคลื่อนโดย [nanobot](https://github.com/HKUDS/nanobot)\n- **Agent-Native CLI** — ทุกความสามารถ, knowledge base, session และ TutorBot ผ่านคำสั่งเดียว Rich และ JSON มอบ [`SKILL.md`](../../SKILL.md) ให้ agent\n\n---\n\n## 🚀 เริ่มต้นใช้งาน\n\n### ข้อกำหนดเบื้องต้น\n\nก่อนเริ่ม ตรวจสอบว่ามีเครื่องมือต่อไปนี้ติดตั้งแล้ว:\n\n| ข้อกำหนด | เวอร์ชัน | ตรวจสอบ | หมายเหตุ |\n|:---|:---|:---|:---|\n| [Git](https://git-scm.com/) | ใดก็ได้ | `git --version` | สำหรับ clone โปรเจกต์ |\n| [Python](https://www.python.org/downloads/) | 3.11+ | `python --version` | รัน backend |\n| [Node.js](https://nodejs.org/) | 20.9+ | `node --version` | frontend runtime สำหรับการติดตั้ง Web ในเครื่อง |\n| [npm](https://www.npmjs.com/) | มากับ Node.js | `npm --version` | ติดตั้งพร้อม Node.js |\n\nคุณยังต้องมี **API Key** จากผู้ให้บริการ LLM อย่างน้อยหนึ่งราย (เช่น [OpenAI](https://platform.openai.com/api-keys), [DeepSeek](https://platform.deepseek.com/), [Anthropic](https://console.anthropic.com/)) Setup Tour จะนำทางการกรอก\n\n### ตัวเลือก A — Setup Tour (แนะนำ)\n\n**สคริปต์ CLI แบบโต้ตอบเพียงตัวเดียว** พาคุณจาก clone สดใหม่ไปจนถึงแอปที่รันได้ — ไม่ต้อง `pip install` หรือ `npm install` หรือแก้ `data/user/settings/*.json` เอง ทุกอย่างถูกตรวจหา ติดตั้ง และตั้งค่าในขั้นแนะนำ 7 ขั้น\n\n```bash\ngit clone https://github.com/HKUDS/AidLearning.git\ncd AidLearning\n\n# สร้าง Python virtual environment (เลือกอย่างใดอย่างหนึ่ง):\nconda create -n aidlearning python=3.11 && conda activate aidlearning # Anaconda/Miniconda\npython -m venv .venv && source .venv/bin/activate # macOS/Linux\npython -m venv .venv && .venv\\Scripts\\activate # Windows\n\n# เริ่ม guided tour\npython scripts/start_tour.py\n```\n\nเมื่อตัวช่วยจบ:\n\n```bash\npython scripts/start_web.py\n```\n\n> **การเปิดใช้งานประจำวัน** — โดยทั่วไปรัน Tour แค่ครั้งเดียว หลังจากนั้นใช้ `python scripts/start_web.py` เพื่อสตาร์ท backend กับ frontend พร้อมกัน (URL ฝั่ง frontend แสดงในเทอร์มินัล) รัน `start_tour.py` อีกครั้งเฉพาะเมื่อต้องตั้งค่า provider ใหม่ เปลี่ยนพอร์ต หรือติดตั้งส่วนเสริมที่ขาด ในหน้า **Settings** ของเว็บกด **Run Tour** เพื่อเล่น walkthrough แบบเน้นจุดอีกครั้ง\n\n### ตัวเลือก B — ติดตั้งเองแบบ Local\n\nหากคุณต้องการควบคุมทุกขั้นตอนด้วยตัวเอง ให้ติดตั้งและตั้งค่าตามนี้\n\n**1. ติดตั้ง dependency**\n\n```bash\ngit clone https://github.com/HKUDS/AidLearning.git\ncd AidLearning\n\nconda create -n aidlearning python=3.11 && conda activate aidlearning\npip install -e \".[server]\"\n\n# Frontend\ncd web && npm install && cd ..\n```\n\n**2. ตั้งค่า runtime settings**\n\n```bash\npython scripts/start_tour.py\n```\n\nแก้ไขไฟล์ `data/user/settings/*.json` และกรอกค่าที่จำเป็นอย่างน้อยดังนี้:\n\n```jsonc\n// Runtime configuration now lives in data/user/settings/.\n// Model/provider credentials: model_catalog.json\n// Ports/CORS/attachments: system.json\n// Auth settings: auth.json (JWT secret stays in multi-user/_system/auth/auth_secret)\n// PocketBase and sidecars: integrations.json\n```\n\n<details>\n<summary><b>ผู้ให้บริการ LLM ที่รองรับ</b></summary>\n\n| ผู้ให้บริการ | Binding | Base URL เริ่มต้น |\n|:--|:--|:--|\n| AiHubMix | `aihubmix` | `https://aihubmix.com/v1` |\n| Anthropic | `anthropic` | `https://api.anthropic.com/v1` |\n| Azure OpenAI | `azure_openai` | — |\n| BytePlus | `byteplus` | `https://ark.ap-southeast.bytepluses.com/api/v3` |\n| BytePlus Coding Plan | `byteplus_coding_plan` | `https://ark.ap-southeast.bytepluses.com/api/coding/v3` |\n| Custom | `custom` | — |\n| Custom (Anthropic API) | `custom_anthropic` | — |\n| DashScope | `dashscope` | `https://dashscope.aliyuncs.com/compatible-mode/v1` |\n| DeepSeek | `deepseek` | `https://api.deepseek.com` |\n| Gemini | `gemini` | `https://generativelanguage.googleapis.com/v1beta/openai/` |\n| GitHub Copilot | `github_copilot` | `https://api.githubcopilot.com` |\n| Groq | `groq` | `https://api.groq.com/openai/v1` |\n| llama.cpp | `llama_cpp` | `http://localhost:8080/v1` |\n| LM Studio | `lm_studio` | `http://localhost:1234/v1` |\n| MiniMax | `minimax` | `https://api.minimaxi.com/v1` |\n| MiniMax (Anthropic) | `minimax_anthropic` | `https://api.minimaxi.com/anthropic` |\n| Mistral | `mistral` | `https://api.mistral.ai/v1` |\n| Moonshot | `moonshot` | `https://api.moonshot.cn/v1` |\n| Ollama | `ollama` | `http://localhost:11434/v1` |\n| OpenAI | `openai` | `https://api.openai.com/v1` |\n| OpenAI Codex | `openai_codex` | `https://chatgpt.com/backend-api` |\n| OpenRouter | `openrouter` | `https://openrouter.ai/api/v1` |\n| OpenVINO Model Server | `ovms` | `http://localhost:8000/v3` |\n| Qianfan | `qianfan` | `https://qianfan.baidubce.com/v2` |\n| SiliconFlow | `siliconflow` | `https://api.siliconflow.cn/v1` |\n| Step Fun | `stepfun` | `https://api.stepfun.com/v1` |\n| vLLM/Local | `vllm` | — |\n| VolcEngine | `volcengine` | `https://ark.cn-beijing.volces.com/api/v3` |\n| VolcEngine Coding Plan | `volcengine_coding_plan` | `https://ark.cn-beijing.volces.com/api/coding/v3` |\n| Xiaomi MIMO | `xiaomi_mimo` | `https://api.xiaomimimo.com/v1` |\n| Zhipu AI | `zhipu` | `https://open.bigmodel.cn/api/paas/v4` |\n\n</details>\n\n<details>\n<summary><b>ผู้ให้บริการ Embedding ที่รองรับ</b></summary>\n\n| ผู้ให้บริการ | Binding | ตัวอย่างโมเดล | Dimension เริ่มต้น |\n|:--|:--|:--|:--|\n| OpenAI | `openai` | `text-embedding-3-large` | 3072 |\n| Azure OpenAI | `azure_openai` | deployment name | — |\n| Cohere | `cohere` | `embed-v4.0` | 1024 |\n| Jina | `jina` | `jina-embeddings-v3` | 1024 |\n| Ollama | `ollama` | `nomic-embed-text` | 768 |\n| vLLM / LM Studio | `vllm` | โมเดล embedding ใดก็ได้ | — |\n| OpenAI-compatible | `custom` | — | — |\n\nผู้ให้บริการที่เข้ากันได้กับ OpenAI (DashScope, SiliconFlow ฯลฯ) ใช้ผ่าน binding `custom` หรือ `openai` ได้\n\n</details>\n\n<details>\n<summary><b>ผู้ให้บริการ Web Search ที่รองรับ</b></summary>\n\n| ผู้ให้บริการ | Env Key | หมายเหตุ |\n|:--|:--|:--|\n| Brave | `BRAVE_API_KEY` | แนะนำ, มี free tier |\n| Tavily | `TAVILY_API_KEY` | |\n| Serper | `SERPER_API_KEY` | ผลการค้นหา Google ผ่าน Serper |\n| Jina | `JINA_API_KEY` | |\n| SearXNG | — | Self-hosted, ไม่ต้องใช้ API key |\n| DuckDuckGo | — | ไม่ต้องใช้ API key |\n| Perplexity | `PERPLEXITY_API_KEY` | ต้องใช้ API key |\n\n</details>\n\n**3. เริ่มบริการ**\n\nวิธีที่เร็วที่สุด:\n\n```bash\npython scripts/start_web.py\n```\n\nคำสั่งนี้จะสตาร์ททั้ง backend และ frontend พร้อมเปิดเบราว์เซอร์ให้โดยอัตโนมัติ\n\nหรือรันแยกเทอร์มินัล:\n\n```bash\n# Backend (FastAPI)\npython -m aidlearning.api.run_server\n\n# Frontend (Next.js) — เปิดอีกเทอร์มินัลหนึ่ง\ncd web && npm run dev -- -p 3782\n```\n\n| Service | Port เริ่มต้น |\n|:---:|:---:|\n| Backend | `8001` |\n| Frontend | `3782` |\n\nเปิด [http://localhost:3782](http://localhost:3782) แล้วพร้อมใช้งาน\n\n### ตัวเลือก C — ติดตั้งด้วย Docker\n\nDocker ช่วยรวม backend และ frontend ไว้ในคอนเทนเนอร์เดียว จึงไม่จำเป็นต้องติดตั้ง Python หรือ Node.js บนเครื่องโดยตรง\n\n**1. สร้าง runtime settings** (จำเป็นสำหรับทุกตัวเลือก)\n\n```bash\ngit clone https://github.com/HKUDS/AidLearning.git\ncd AidLearning\npython scripts/start_tour.py\n```\n\nแก้ไข `data/user/settings/*.json` และกรอกค่าที่จำเป็น (เหมือน [ตัวเลือก B](#ตัวเลือก-b--ติดตั้งเองแบบ-local) ด้านบน)\n\n**2a. ดึง image ทางการ (แนะนำ)**\n\nImage ทางการเผยแพร่ที่ [GitHub Container Registry](https://github.com/HKUDS/AidLearning/pkgs/container/aidlearning) ทุกครั้งที่ release สำหรับ `linux/amd64` และ `linux/arm64`\n\n```bash\npython scripts/docker_compose.py -f docker-compose.ghcr.yml up -d\n```\n\nหากต้องการ pin เวอร์ชันเฉพาะ ให้แก้ image tag ใน `docker-compose.ghcr.yml`:\n\n```yaml\nimage: ghcr.io/hkuds/aidlearning:1.0.0 # หรือ :latest\n```\n\n**2b. Build จาก source**\n\n```bash\npython scripts/docker_compose.py up -d\n```\n\nคำสั่งนี้จะ build image จาก `Dockerfile` และเริ่มคอนเทนเนอร์\n\n**3. ตรวจสอบและจัดการ**\n\nเปิด [http://localhost:3782](http://localhost:3782) เมื่อคอนเทนเนอร์พร้อมแล้ว\n\n```bash\npython scripts/docker_compose.py logs -f # ดู log\npython scripts/docker_compose.py down # หยุดและลบคอนเทนเนอร์\n```\n\n<details>\n<summary><b>Deploy บน Cloud / เซิร์ฟเวอร์ระยะไกล</b></summary>\n\nเมื่อ deploy บนเซิร์ฟเวอร์ระยะไกล เบราว์เซอร์ต้องรู้ URL สาธารณะของ backend API เพิ่มตัวแปรอีกหนึ่งตัวใน `data/user/settings/*.json`:\n\n```json\n{\n \"next_public_api_base_external\": \"https://your-server.com:8001\"\n}\n```\n\nFrontend startup script จะใช้ค่านี้ตอน runtime — ไม่ต้อง rebuild\n\n</details>\n\n<details>\n<summary><b>การยืนยันตัวตน (สำหรับการ deploy สาธารณะ)</b></summary>\n\nการยืนยันตัวตน **ปิดใช้งานโดยค่าเริ่มต้น** — ไม่ต้องเข้าสู่ระบบบน localhost สำหรับการ deploy แบบ multi-tenant ดูส่วน [มัลติยูเซอร์](#multi-user) ด้านล่าง\n\n**ผู้ใช้คนเดียวแบบ headless (ไม่มีขั้นตอน `/register`):** กำหนดค่าล่วงหน้าผ่าน env vars:\n\n```bash\npython -c \"from aidlearning.services.auth import hash_password; print(hash_password('yourpassword'))\"\n```\n\n```jsonc\n// Runtime configuration now lives in data/user/settings/.\n// Model/provider credentials: model_catalog.json\n// Ports/CORS/attachments: system.json\n// Auth settings: auth.json (JWT secret stays in multi-user/_system/auth/auth_secret)\n// PocketBase and sidecars: integrations.json\n```\n\n</details>\n\n<details>\n<summary><b>PocketBase sidecar (ยืนยันตัวตนและจัดเก็บข้อมูลเสริม)</b></summary>\n\nPocketBase เป็น backend เบาแบบ optional ที่แทนที่การยืนยันตัวตน SQLite/JSON ในตัว\n\n> ⚠️ **PocketBase mode ใช้ได้กับผู้ใช้คนเดียวเท่านั้นในปัจจุบัน** สคีมาเริ่มต้นไม่มีฟิลด์ `role` ใน `users` และ queries ไม่ถูกกรองตาม `user_id` Multi-user: ปล่อย `integrations.pocketbase_url` ว่างไว้\n\n```bash\npython scripts/docker_compose.py up -d\nopen http://localhost:8090/_/\npip install pocketbase\npython scripts/pb_setup.py\n```\n\n```jsonc\n// Runtime configuration now lives in data/user/settings/.\n// Model/provider credentials: model_catalog.json\n// Ports/CORS/attachments: system.json\n// Auth settings: auth.json (JWT secret stays in multi-user/_system/auth/auth_secret)\n// PocketBase and sidecars: integrations.json\n```\n\n</details>\n\n<details>\n<summary><b>Development mode (hot-reload)</b></summary>\n\nเพิ่ม dev override เพื่อ mount source code และเปิด hot-reload สำหรับทั้งสองบริการ:\n\n```bash\npython scripts/docker_compose.py -f docker-compose.yml -f docker-compose.dev.yml up\n```\n\nการเปลี่ยนแปลงใน `aidlearning/`, `aidlearning_cli/`, `scripts/` และ `web/` จะมีผลทันที\n\n</details>\n\n<details>\n<summary><b>กำหนด Port เอง</b></summary>\n\nแก้ไข port เริ่มต้นใน `data/user/settings/*.json`:\n\n```json\n{\n \"backend_port\": 9001,\n \"frontend_port\": 4000\n}\n```\n\nจากนั้นรีสตาร์ท:\n\n```bash\npython scripts/docker_compose.py up -d # หรือ python scripts/docker_compose.py -f docker-compose.ghcr.yml up -d\n```\n\n</details>\n\n<details>\n<summary><b>การเก็บข้อมูลถาวร (Data persistence)</b></summary>\n\nข้อมูลผู้ใช้และ knowledge base เก็บผ่าน Docker volume ที่ map กับ directory ในเครื่อง:\n\n| Container path | Host path | เนื้อหา |\n|:---|:---|:---|\n| `/app/data/user` | `./data/user` | Settings, workspace, sessions, logs |\n| `/app/data/memory` | `./data/memory` | หน่วยความจำระยะยาวที่ใช้ร่วมกัน (`SUMMARY.md`, `PROFILE.md`) |\n| `/app/data/knowledge_bases` | `./data/knowledge_bases` | เอกสารที่อัปโหลด & vector indices |\n\nDirectory เหล่านี้จะอยู่หลังจาก `python scripts/docker_compose.py down` และถูกนำมาใช้ใหม่เมื่อ `python scripts/docker_compose.py up` ครั้งต่อไป\n\n</details>\n\n<details>\n<summary><b>Runtime settings / deployment overrides</b></summary>\n\nRuntime settings live in `data/user/settings/*.json`; `model_catalog.json` is the source of truth for model, embedding, and search provider credentials. Non-model runtime settings live in `system.json`, `auth.json`, and `integrations.json`.\n\nDocker startup is JSON-driven via `scripts/docker_compose.py`; use `data/user/settings/*.json` rather than the project-root `.env` or legacy `BACKEND_PORT` / `FRONTEND_PORT` variables.\n\n</details>\n\n### ตัวเลือก D — ใช้เฉพาะ CLI\n\nหากคุณต้องการเฉพาะ command-line interface โดยไม่ใช้เว็บ frontend:\n\n```bash\npip install -e \".[cli]\"\naidlearning chat # Interactive REPL\naidlearning run chat \"Explain Fourier transform\" # เรียกใช้ capability แบบ one-shot\naidlearning run deep_solve \"Solve x^2 = 4\" # แก้ปัญหาแบบหลายเอเจนต์\naidlearning kb create my-kb --doc textbook.pdf # สร้าง knowledge base\n```\n\n> ดูรายละเอียดเพิ่มเติมที่ [AidLearning CLI](#%EF%B8%8F-aidlearning-cli--อินเทอร์เฟซแบบ-agent-native)\n\n---\n\n## 📖 สำรวจ AidLearning\n\n<div align=\"center\">\n<img src=\"../../assets/figs/aidlearning-architecture.png\" alt=\"สถาปัตยกรรม AidLearning\" width=\"800\">\n</div>\n\n### 💬 Chat — พื้นที่ทำงานอัจฉริยะแบบรวม\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-chat.png\" alt=\"พื้นที่ Chat\" width=\"800\">\n</div>\n\nAidLearning รวม 6 โหมดหลักไว้ใน workspace เดียว โดยใช้ **ระบบจัดการบริบทร่วมกัน** ทำให้ประวัติการสนทนา knowledge base และแหล่งอ้างอิงต่อเนื่องข้ามโหมดได้ — สลับไปมาได้อิสระในหัวข้อเดียวกัน\n\n| โหมด | หน้าที่ |\n|:---|:---|\n| **Chat** | สนทนาแบบยืดหยุ่น พร้อมเปิดใช้ RAG, web search, code execution, deep reasoning, brainstorming และ paper search ได้ตามต้องการ |\n| **Deep Solve** | แก้ปัญหาแบบหลายเอเจนต์ โดยวางแผน สืบค้น แก้โจทย์ และตรวจสอบ พร้อม citation อย่างเป็นระบบ |\n| **Quiz Generation** | สร้างแบบทดสอบจาก knowledge base พร้อมตรวจสอบคุณภาพของคำถาม |\n| **Deep Research** | แยกหัวข้อออกเป็นประเด็นย่อย ส่งเอเจนต์ค้นคว้าแบบขนานจาก RAG, เว็บ และงานวิชาการ แล้วสรุปเป็นรายงานที่มีอ้างอิง |\n| **Math Animator** | เปลี่ยนแนวคิดคณิตศาสตร์ให้เป็นภาพเคลื่อนไหวและ storyboard ด้วย Manim |\n| **Visualize** | สร้าง SVG, Chart.js, Mermaid หรือหน้า HTML แบบรวมไฟล์เดียวจากคำอธิบายภาษาธรรมดา |\n\nเครื่องมือ **แยกอิสระจาก workflow** — ในทุกโหมด คุณเลือกได้ว่าจะเปิดเครื่องมือตัวไหน ใช้กี่ตัว หรือจะไม่ใช้เลย Workflow จัดการเรื่องการให้เหตุผล ส่วนเครื่องมือเป็นของคุณที่จะประกอบเข้าด้วยกัน\n\n> เริ่มจากถามคำถามง่าย ๆ ยกระดับเป็น Deep Solve เมื่อยากขึ้น แสดงภาพความคิด สร้างแบบทดสอบเพื่อตรวจสอบตัวเอง จากนั้นเปิด Deep Research เพื่อลงลึก — ทั้งหมดในเธรดเดียว\n\n### ✍️ Co-Writer — พื้นที่เขียนหลายเอกสารกับ AI\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-cowriter.png\" alt=\"Co-Writer\" width=\"800\">\n</div>\n\nสร้างและจัดการหลายเอกสาร แต่ละไฟล์ถูกเก็บถาวร — ไม่ใช่แค่ฉบับร่างครั้งเดียว: Markdown เต็มรูปแบบที่ AI เป็นผู้ร่วมเขียนระดับแรก เลือกข้อความแล้วสั่ง **Rewrite**, **Expand** หรือ **Shorten** ดึงบริบทจาก knowledge base หรือเว็บ undo/redo เต็มรูปแบบ บันทึกลง notebook ได้\n\n### 📖 Book Engine — หนังสือมีชีวิตแบบโต้ตอบ\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-book-0.png\" alt=\"ห้องสมุด\" width=\"270\"><img src=\"../../assets/figs/dt-book-1.png\" alt=\"ตัวอ่าน\" width=\"270\"><img src=\"../../assets/figs/dt-book-2.png\" alt=\"แอนิเมชัน\" width=\"270\">\n</div>\n\nระบุหัวข้อชี้ไปที่ knowledge base — ได้หนังสือที่มีโครงสร้างและโต้ตอบได้ ไม่ใช่ไฟล์ส่งออกคงที่ แต่เป็นเอกสารมีชีวิตสำหรับอ่าน ทดสอบตัวเอง และพูดคุยในบริบท\n\nเบื้องหลังเป็นไปป์ไลน์หลายเอเจนต์: เสนอโครงร่าง ดึงแหล่งอ้างอิง รวมต้นไม้บท วางแผนหน้า และคอมไพล์บล็อก คุณยังคุมได้: ตรวจโครงร่าง จัดเรียบบท แชตข้างหน้าใดก็ได้\n\n13 ประเภทบล็อก — ข้อความ callout แบบทดสอบ แฟลชการ์ด โค้ด รูป ดำดิ่งลึก แอนิเมชัน แบบโต้ตอบ ไทม์ไลน์ กราฟแนวคิด ส่วน โน้ตผู้ใช้ — แต่ละแบบมีคอมโพเนนต์โต้ตอบ ไทม์ไลน์ความคืบหน้าแบบเรียลไทม์\n\n### 📚 การจัดการความรู้ — โครงสร้างพื้นฐานการเรียนของคุณ\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-knowledge.png\" alt=\"การจัดการความรู้\" width=\"800\">\n</div>\n\nคอลเลกชันเอกสาร โน้ต และบุคลิกการสอน\n\n- **Knowledge Bases** — อัปโหลด PDF, TXT หรือ Markdown เพิ่มทีละไฟล์\n- **Notebooks** — บันทึกจาก Chat, Co-Writer, Book หรือ Deep Research จัดหมวดและสี\n- **Question Bank** — ทบทวนคำถามที่สร้างแล้ว บุ๊กมาร์กและ @ ในแชตเพื่อวิเคราะห์ผลในอดีต\n- **Skills** — สร้างบุคลิกการสอนด้วย `SKILL.md`: ชื่อ คำอธิบาย ทริกเกอร์ (ถ้ามี) และ Markdown ที่ฉีดเข้า system prompt เมื่อเปิดใช้\n\nKnowledge base ของคุณไม่ใช่แค่ที่เก็บ — มันมีส่วนร่วมอย่างแข็งขันในทุกการสนทนา ทุกเซสชันวิจัย และทุกเส้นทางการเรียนรู้\n\n### 🧠 Memory — AidLearning เรียนรู้ไปพร้อมกับคุณ\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-memory.png\" alt=\"Memory\" width=\"800\">\n</div>\n\nAidLearning มี memory แบบถาวรที่เติบโตอยู่ตลอดเวลาผ่าน 2 มิติ:\n\n- **Summary** — สรุปว่าคุณเรียนอะไรไปแล้ว สำรวจประเด็นใดบ้าง และความเข้าใจพัฒนาอย่างไร\n- **Profile** — โปรไฟล์ผู้เรียน เช่น ระดับความรู้ เป้าหมาย สไตล์การสื่อสาร และความชอบ — ปรับปรุงอัตโนมัติผ่านทุกการโต้ตอบ\n\nMemory นี้ถูกใช้ร่วมกันข้ามทุกฟีเจอร์และทุก TutorBot ยิ่งคุณใช้ AidLearning มากเท่าไร มันก็ยิ่งตอบได้เฉพาะตัวและมีประสิทธิภาพมากขึ้น\n\n---\n\n### 🦞 TutorBot — ติวเตอร์ AI แบบถาวรและอัตโนมัติ\n\n<div align=\"center\">\n<img src=\"../../assets/figs/tutorbot-architecture.png\" alt=\"สถาปัตยกรรม TutorBot\" width=\"800\">\n</div>\n\nTutorBot ไม่ใช่ chatbot ธรรมดา แต่เป็น **เอเจนต์แบบถาวร หลายอินสแตนซ์** ที่ทำงานบน [nanobot](https://github.com/HKUDS/nanobot) โดยแต่ละ TutorBot รัน agent loop เป็นของตัวเองพร้อม workspace, memory และบุคลิกแยกจากกัน คุณสามารถสร้างติวเตอร์คณิตศาสตร์แบบโสเครติส, โค้ชการเขียนที่ใจเย็น หรือผู้ช่วยวิจัยที่เข้มงวดได้พร้อมกันหลายตัว แต่ละตัวเติบโตไปพร้อมกับคุณ\n\n<div align=\"center\">\n<img src=\"../../assets/figs/tb.png\" alt=\"TutorBot\" width=\"800\">\n</div>\n\n- **Soul Templates** — กำหนดบุคลิก โทนการสอน และปรัชญาการสอนผ่านไฟล์ Soul ที่แก้ไขได้ เลือกจาก archetype ในตัว (โสเครติส, ให้กำลังใจ, เข้มงวด) หรือออกแบบเอง — soul กำหนดทุกการตอบ\n- **Independent Workspace** — แต่ละบอตมี directory ของตัวเองพร้อม memory, sessions, skills และ config แยกจากกัน — แยกตัวเต็มที่แต่ยังเข้าถึงชั้นความรู้ร่วมของ AidLearning ได้\n- **Proactive Heartbeat** — บอตไม่ใช่แค่ตอบ — มันริเริ่มเอง ระบบ Heartbeat ในตัวเปิดให้เช็กอินการเรียนซ้ำ เตือนทบทวน และจัดตารางงาน ติวเตอร์ของคุณมาหาแม้คุณไม่เริ่ม\n- **Full Tool Access** — ทุกบอตเข้าถึงเครื่องมือครบชุดของ AidLearning: RAG retrieval, code execution, web search, academic paper search, deep reasoning และ brainstorming\n- **Skill Learning** — สอนบอตความสามารถใหม่โดยเพิ่มไฟล์ skill ลงใน workspace ของมัน เมื่อความต้องการของคุณเปลี่ยน ความสามารถของติวเตอร์ก็เปลี่ยนตาม\n- **Multi-Channel Presence** — เชื่อมต่อกับ Telegram, Discord, Slack, Feishu, WeChat Work, DingTalk, Email และช่องทางอื่น ๆ ติวเตอร์ไปหาคุณไม่ว่าคุณจะอยู่ที่ไหน\n- **Team & Sub-Agents** — สร้าง sub-agent ทำงานเบื้องหลังหรือจัด multi-agent team ภายในบอตเดียวสำหรับงานซับซ้อนและใช้เวลานาน\n\n```bash\naidlearning bot create math-tutor --persona \"Socratic math teacher who uses probing questions\"\naidlearning bot create writing-coach --persona \"Patient, detail-oriented writing mentor\"\naidlearning bot list # ดูติวเตอร์ทั้งหมดที่กำลังทำงาน\n```\n\n---\n\n### ⌨️ AidLearning CLI — อินเทอร์เฟซแบบ Agent-Native\n\n<div align=\"center\">\n<img src=\"../../assets/figs/cli-architecture.png\" alt=\"สถาปัตยกรรม AidLearning CLI\" width=\"800\">\n</div>\n\nAidLearning รองรับ CLI อย่างเต็มรูปแบบ ทุก capability, knowledge base, session, memory และ TutorBot อยู่ห่างแค่คำสั่งเดียว — ไม่ต้องเปิดเบราว์เซอร์ CLI ให้บริการทั้งมนุษย์ (แสดงผลสวยงามในเทอร์มินัล) และ AI agent (ส่งออกเป็น JSON ที่มีโครงสร้าง)\n\nมอบ [`SKILL.md`](../../SKILL.md) ที่ root ของโปรเจกต์ให้ agent ที่ใช้เครื่องมือ ([nanobot](https://github.com/HKUDS/nanobot) หรือ LLM ใดก็ตามที่มี tool access) แล้วมันจะตั้งค่าและใช้งาน AidLearning ได้เอง\n\n**One-shot execution** — เรียกใช้ capability ใดก็ได้จากเทอร์มินัล:\n\n```bash\naidlearning run chat \"Explain the Fourier transform\" -t rag --kb textbook\naidlearning run deep_solve \"Prove that √2 is irrational\" -t reason\naidlearning run deep_question \"Linear algebra\" --config num_questions=5\naidlearning run deep_research \"Attention mechanisms in transformers\"\naidlearning run visualize \"Draw the architecture of a transformer\"\n```\n\n**Interactive REPL** — เซสชันแชตแบบถาวรพร้อมสลับโหมดขณะใช้งาน:\n\n```bash\naidlearning chat --capability deep_solve --kb my-kb\n# ภายใน REPL: /cap, /tool, /kb, /history, /notebook, /config เพื่อสลับขณะใช้งาน\n```\n\n**Knowledge base lifecycle** — สร้าง ค้นหา และจัดการคลัง RAG-ready ทั้งหมดจากเทอร์มินัล:\n\n```bash\naidlearning kb create my-kb --doc textbook.pdf # สร้างจากเอกสาร\naidlearning kb add my-kb --docs-dir ./papers/ # เพิ่มโฟลเดอร์เอกสาร\naidlearning kb search my-kb \"gradient descent\" # ค้นหาโดยตรง\naidlearning kb set-default my-kb # ตั้งเป็น KB เริ่มต้น\n```\n\n**Dual output mode** — แสดงผลสวยงามสำหรับมนุษย์, JSON สำหรับ pipeline:\n\n```bash\naidlearning run chat \"Summarize chapter 3\" -f rich # แสดงผลสี สวยงาม\naidlearning run chat \"Summarize chapter 3\" -f json # JSON events แบบ line-delimited\n```\n\n**Session continuity** — กลับมาทำต่อจากจุดที่ค้างไว้:\n\n```bash\naidlearning session list # แสดงรายการเซสชัน\naidlearning session open <id> # กลับมาทำต่อใน REPL\n```\n\n<details>\n<summary><b>ตารางอ้างอิงคำสั่ง CLI ทั้งหมด</b></summary>\n\n**คำสั่งหลัก**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning run <capability> <message>` | เรียกใช้ capability แบบ single turn (`chat`, `deep_solve`, `deep_question`, `deep_research`, `math_animator`, `visualize`) |\n| `aidlearning chat` | Interactive REPL พร้อมตัวเลือก `--capability`, `--tool`, `--kb`, `--language` |\n| `aidlearning serve` | เริ่ม AidLearning API server |\n\n**`aidlearning bot`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning bot list` | แสดงรายการ TutorBot ทั้งหมด |\n| `aidlearning bot create <id>` | สร้างและเริ่มบอตใหม่ (`--name`, `--persona`, `--model`) |\n| `aidlearning bot start <id>` | เริ่มบอต |\n| `aidlearning bot stop <id>` | หยุดบอต |\n\n**`aidlearning kb`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning kb list` | แสดงรายการ knowledge base ทั้งหมด |\n| `aidlearning kb info <name>` | แสดงรายละเอียด knowledge base |\n| `aidlearning kb create <name>` | สร้างจากเอกสาร (`--doc`, `--docs-dir`) |\n| `aidlearning kb add <name>` | เพิ่มเอกสารทีละไฟล์ |\n| `aidlearning kb search <name> <query>` | ค้นหา knowledge base |\n| `aidlearning kb set-default <name>` | ตั้งเป็น KB เริ่มต้น |\n| `aidlearning kb delete <name>` | ลบ knowledge base (`--force`) |\n\n**`aidlearning memory`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning memory show [file]` | ดู memory (`summary`, `profile` หรือ `all`) |\n| `aidlearning memory clear [file]` | ล้าง memory (`--force`) |\n\n**`aidlearning session`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning session list` | แสดงรายการเซสชัน (`--limit`) |\n| `aidlearning session show <id>` | ดูข้อความในเซสชัน |\n| `aidlearning session open <id>` | กลับมาทำต่อใน REPL |\n| `aidlearning session rename <id>` | เปลี่ยนชื่อเซสชัน (`--title`) |\n| `aidlearning session delete <id>` | ลบเซสชัน |\n\n**`aidlearning notebook`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning notebook list` | แสดงรายการ notebook |\n| `aidlearning notebook create <name>` | สร้าง notebook (`--description`) |\n| `aidlearning notebook show <id>` | ดูบันทึกใน notebook |\n| `aidlearning notebook add-md <id> <path>` | นำเข้า markdown เป็นบันทึก |\n| `aidlearning notebook replace-md <id> <rec> <path>` | เปลี่ยนบันทึก markdown |\n| `aidlearning notebook remove-record <id> <rec>` | ลบบันทึก |\n\n**`aidlearning book`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning book list` | แสดงรายการหนังสือทั้งหมดใน workspace |\n| `aidlearning book health <book_id>` | ตรวจ KB drift และสุขภาพของหนังสือ |\n| `aidlearning book refresh-fingerprints <book_id>` | รีเฟรช fingerprint ของ KB และล้างหน้าที่ล้าสมัย |\n\n**`aidlearning config` / `plugin` / `provider`**\n\n| คำสั่ง | คำอธิบาย |\n|:---|:---|\n| `aidlearning config show` | แสดงสรุป configuration ปัจจุบัน |\n| `aidlearning plugin list` | แสดงรายการ tools และ capabilities ที่ลงทะเบียน |\n| `aidlearning plugin info <name>` | แสดงรายละเอียด tool หรือ capability |\n| `aidlearning provider login <provider>` | ยืนยันตัวตนกับผู้ให้บริการ (OAuth กับ `openai-codex`; `github-copilot` ตรวจเซสชัน Copilot ที่มีอยู่) |\n\n</details>\n\n---\n\n<a id=\"multi-user\"></a>\n### 👥 มัลติยูเซอร์ — การ deploy ร่วมกันพร้อม workspace แยกต่อผู้ใช้\n\n<div align=\"center\">\n<img src=\"../../assets/figs/dt-multi-user.png\" alt=\"มัลติยูเซอร์\" width=\"800\">\n</div>\n\nเปิดใช้การยืนยันตัวตน และ AidLearning จะกลายเป็น deployment แบบ multi-tenant พร้อม **workspace แยกต่อผู้ใช้** และ **ทรัพยากรที่ผู้ดูแลจัดการ** ผู้ที่ลงทะเบียนคนแรกจะเป็นผู้ดูแล บัญชีถัดไปสร้างโดยผู้ดูแล (แบบ invite-only) แต่ละคนได้รับประวัติแชต/หน่วยความจำ/สมุดบันทึก/ฐานความรู้ของตนเอง\n\n**เริ่มต้นด่วน (5 ขั้นตอน):**\n\n```bash\n# 1. เปิดใช้การยืนยันตัวตนใน data/user/settings/*.json ที่ root ของโปรเจกต์\n# Set auth.json enabled=true\n# JWT secret is stored in multi-user/_system/auth/auth_secret\n\n# 2. รีสตาร์ท web stack\npython scripts/start_web.py\n\n# 3. เปิด http://localhost:3782/register และสร้างบัญชีแรก\n# การลงทะเบียนครั้งแรกเป็นครั้งเดียวที่เปิดสาธารณะ ผู้ใช้นั้น\n# จะเป็นผู้ดูแล และ /register จะถูกปิดอัตโนมัติ\n\n# 4. ในฐานะผู้ดูแล ไปที่ /admin/users → \"เพิ่มผู้ใช้\"\n\n# 5. สำหรับแต่ละผู้ใช้ คลิกไอคอนสไลเดอร์ → กำหนด LLM profiles,\n# knowledge bases, และ skills → บันทึก\n```\n\n**สิ่งที่ผู้ดูแลเห็น:**\n\n- **หน้า Settings ครบ** ที่ `/settings` — LLM/embedding/search, API keys, model catalog\n- **จัดการผู้ใช้** ที่ `/admin/users` — สร้าง เลื่อนตำแหน่ง ลดตำแหน่ง ลบบัญชี\n- **Grant editor** — เลือก model profiles, KBs, skills สำหรับผู้ใช้ที่ไม่ใช่ผู้ดูแล; grants มีแค่ **logical IDs** ไม่มี API key ข้ามขอบเขต\n- **Audit trail** — ทุกการเปลี่ยนแปลง grant บันทึกใน `multi-user/_system/audit/usage.jsonl`\n\n**สิ่งที่ผู้ใช้ทั่วไปได้รับ:**\n\n- **Workspace แยก** ใต้ `multi-user/<uid>/` — `chat_history.db`, หน่วยความจำ, สมุดบันทึก, KB ส่วนตัว\n- **สิทธิ์อ่านอย่างเดียว** สำหรับ KBs/skills ที่ผู้ดูแลกำหนด พร้อมป้าย \"กำหนดโดยผู้ดูแล\"\n- **หน้า Settings แบบจำกัด** — ธีม ภาษา และสรุป models ที่ได้รับ ไม่มี API keys\n- **LLM ที่กำหนด** — การสนทนาผ่าน model ที่ผู้ดูแลกำหนด; ไม่มี grant จะถูกปฏิเสธตั้งแต่ต้น\n\n**โครงสร้าง workspace:**\n\n```\nmulti-user/\n├── _system/\n│ ├── auth/users.json\n│ ├── auth/auth_secret\n│ ├── grants/<uid>.json\n│ └── audit/usage.jsonl\n└── <uid>/\n ├── user/\n │ ├── chat_history.db\n │ ├── settings/interface.json\n │ └── workspace/{chat,co-writer,book,...}\n ├── memory/{SUMMARY.md,PROFILE.md}\n └── knowledge_bases/...\n```\n\n**Configuration reference:**\n\nRuntime settings live in `data/user/settings/*.json`. For headless single-user bootstrap, set `username` and `password_hash` in `auth.json`; for multi-user registration, leave those blank and use the identity store.\n\n> ⚠️ **PocketBase mode (`integrations.pocketbase_url` ตั้งค่า) ใช้ได้กับผู้ใช้คนเดียวเท่านั้น** — ไม่มีฟิลด์ `role`, ไม่มีการกรองตาม `user_id` Multi-user: ปล่อย `integrations.pocketbase_url` ว่างไว้\n\n> ⚠️ **แนะนำ single process** การเลื่อนตำแหน่งผู้ดูแลคนแรกป้องกันด้วย `threading.Lock` หลาย workers: สร้างผู้ดูแลคนแรกแบบออฟไลน์\n\n## 🗺️ แผนงานในอนาคต\n\n| สถานะ | หมุดหมาย |\n|:---:|:---|\n| 🎯 | **Authentication & Login** — รองรับหน้าเข้าสู่ระบบแบบเลือกใช้สำหรับการ deploy สาธารณะและผู้ใช้หลายคน |\n| 🎯 | **Themes & Appearance** — ธีมและการปรับแต่งหน้าตา UI ที่หลากหลายขึ้น |\n| 🎯 | **Interaction Improvement** — ปรับปรุง icon และรายละเอียดการโต้ตอบ |\n| 🔜 | **Better Memories** — ยกระดับระบบจัดการ memory |\n| 🔜 | **LightRAG Integration** — รวม [LightRAG](https://github.com/HKUDS/LightRAG) เป็น knowledge base engine ขั้นสูง |\n| 🔜 | **Documentation Site** — เว็บไซต์เอกสารที่ครบถ้วนขึ้น ทั้งคู่มือ, API reference และ tutorial |\n\n> หาก AidLearning มีประโยชน์สำหรับคุณ [ฝากกดดาว](https://github.com/HKUDS/AidLearning/stargazers) — มันช่วยให้เราพัฒนาต่อไปได้!\n\n---\n\n## 🌐 ชุมชนและระบบนิเวศ\n\nAidLearning สร้างขึ้นบนโครงการโอเพนซอร์สคุณภาพหลายตัว:\n\n| โครงการ | บทบาทใน AidLearning |\n|:---|:---|\n| [**nanobot**](https://github.com/HKUDS/nanobot) | เอนจินเอเจนต์น้ำหนักเบาที่ขับเคลื่อน TutorBot |\n| [**LlamaIndex**](https://github.com/run-llama/llama_index) | แกนหลักสำหรับ RAG pipeline และการทำดัชนีเอกสาร |\n| [**ManimCat**](https://github.com/Wing900/ManimCat) | ระบบสร้างแอนิเมชันคณิตศาสตร์สำหรับ Math Animator |\n\n**จาก ecosystem ของ HKUDS:**\n\n| [⚡ LightRAG](https://github.com/HKUDS/LightRAG) | [🤖 AutoAgent](https://github.com/HKUDS/AutoAgent) | [🔬 AI-Researcher](https://github.com/HKUDS/AI-Researcher) | [🧬 nanobot](https://github.com/HKUDS/nanobot) |\n|:---:|:---:|:---:|:---:|\n| Simple & Fast RAG | Zero-Code Agent Framework | Automated Research | Ultra-Lightweight AI Agent |\n\n## 🤝 การมีส่วนร่วม\n\n<div align=\"center\">\n\nเราหวังว่า AidLearning จะเป็นของขวัญแก่ชุมชน 🎁\n\n<a href=\"https://github.com/HKUDS/AidLearning/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=HKUDS/AidLearning&max=999\" alt=\"Contributors\" />\n</a>\n\n</div>\n\nอ่าน [CONTRIBUTING.md](../../CONTRIBUTING.md) สำหรับคำแนะนำเกี่ยวกับการตั้งค่าสภาพแวดล้อมสำหรับนักพัฒนา มาตรฐานโค้ด และขั้นตอนการส่ง pull request\n\n## ⭐ ประวัติดาว\n\n<div align=\"center\">\n\n<a href=\"https://www.star-history.com/#HKUDS/AidLearning&type=timeline&legend=top-left\">\n <picture>\n <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=HKUDS/AidLearning&type=timeline&theme=dark&legend=top-left\" />\n <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=HKUDS/AidLearning&type=timeline&legend=top-left\" />\n <img alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=HKUDS/AidLearning&type=timeline&legend=top-left\" />\n </picture>\n</a>\n\n</div>\n\n<p align=\"center\">\n <a href=\"https://www.star-history.com/hkuds/aidlearning\">\n <picture>\n <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/badge?repo=HKUDS/AidLearning&theme=dark\" />\n <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/badge?repo=HKUDS/AidLearning\" />\n <img alt=\"Star History Rank\" src=\"https://api.star-history.com/badge?repo=HKUDS/AidLearning\" />\n </picture>\n </a>\n</p>\n\n<div align=\"center\">\n\n**[Data Intelligence Lab @ HKU](https://github.com/HKUDS)**\n\n[⭐ กดดาว](https://github.com/HKUDS/AidLearning/stargazers) · [🐛 รายงานบั๊ก](https://github.com/HKUDS/AidLearning/issues) · [💬 Discussions](https://github.com/HKUDS/AidLearning/discussions)\n\n---\n\nเผยแพร่ภายใต้สัญญาอนุญาต [Apache License 2.0](../../LICENSE)\n\n<p>\n <img src=\"https://visitor-badge.laobi.icu/badge?page_id=HKUDS.AidLearning&style=for-the-badge&color=00d4ff\" alt=\"Views\">\n</p>\n\n</div>\n"}}, "health-app/study/aid_learning_agent/aidlearning/services/provider_registry.py": {"1d1a93717421d10f6294c917a377ace11cb3c248": {"t": 1785674679.0273073, "n": 15354, "h": "308ab01652b61f3c", "c": "\"\"\"Provider Registry — LLM Provider 元数据注册表\n\n【调用链路位置】factory.py → find_by_name/find_by_model → ProviderSpec\n\nProviderSpec 定义每个 Provider 的属性:\n - name/keywords: 名称和匹配关键词\n - backend: 使用哪个实现(openai_compat/anthropic/azure_openai 等)\n - default_api_base: 默认 API 地址\n - is_gateway/is_local/is_oauth: 类型标记\n - supports_prompt_caching: 是否支持 prompt 缓存\n\n新增 Provider 只需在 PROVIDERS 列表中添加一个 ProviderSpec。\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Any\n\nfrom pydantic.alias_generators import to_snake\n\n\n@dataclass(frozen=True)\nclass ProviderSpec:\n \"\"\"单个 Provider 元数据条目。\n\n env_extras 值中的占位符:\n {api_key} — 用户的 API 密钥\n {api_base} — 配置中的 api_base,或此规格的 default_api_base\n \"\"\"\n\n name: str\n keywords: tuple[str, ...]\n env_key: str\n display_name: str = \"\"\n\n # 使用哪个 Provider 实现:\n # \"openai_compat\" | \"anthropic\" | \"azure_openai\" | \"openai_codex\" | \"github_copilot\"\n backend: str = \"openai_compat\"\n\n env_extras: tuple[tuple[str, str], ...] = ()\n is_gateway: bool = False\n is_local: bool = False\n detect_by_key_prefix: str = \"\"\n detect_by_base_keyword: str = \"\"\n default_api_base: str = \"\"\n strip_model_prefix: bool = False\n supports_max_completion_tokens: bool = False\n supports_prompt_caching: bool = False\n supports_stream_options: bool = True\n model_overrides: tuple[tuple[str, dict[str, Any]], ...] = ()\n is_oauth: bool = False\n is_direct: bool = False\n thinking_style: str = \"\"\n # 子串模式(不区分大小写),标记需要展示原生推理轨迹的模型。\n # 当调用方未传入显式 reasoning_effort 时,Provider 会自动注入 \"high\",\n # 以便发送 thinking_style 标志(如 extra_body.thinking.type=enabled)。\n reasoning_model_patterns: tuple[str, ...] = ()\n\n @property\n def mode(self) -> str:\n if self.is_oauth:\n return \"oauth\"\n if self.is_direct:\n return \"direct\"\n if self.is_gateway:\n return \"gateway\"\n if self.is_local:\n return \"local\"\n return \"standard\"\n\n @property\n def label(self) -> str:\n return self.display_name or self.name.title()\n\n\nPROVIDER_ALIASES = {\n \"azure\": \"azure_openai\",\n \"azure-openai\": \"azure_openai\",\n \"azureopenai\": \"azure_openai\",\n \"google\": \"gemini\",\n \"google_genai\": \"gemini\",\n \"claude\": \"anthropic\",\n \"openai_compatible\": \"custom\",\n \"openai-compatible\": \"custom\",\n \"anthropic_compatible\": \"custom_anthropic\",\n \"anthropic-compatible\": \"custom_anthropic\",\n \"volcenginecodingplan\": \"volcengine_coding_plan\",\n \"volcengineCodingPlan\": \"volcengine_coding_plan\",\n \"bytepluscodingplan\": \"byteplus_coding_plan\",\n \"byteplusCodingPlan\": \"byteplus_coding_plan\",\n \"github-copilot\": \"github_copilot\",\n \"openai-codex\": \"openai_codex\",\n \"lm-studio\": \"lm_studio\",\n}\n\n\ndef canonical_provider_name(name: str | None) -> str | None:\n \"\"\"标准化传入的 Provider 名称和旧版别名。\"\"\"\n if not name:\n return None\n key = name.strip()\n if not key:\n return None\n key = to_snake(key.replace(\"-\", \"_\"))\n return PROVIDER_ALIASES.get(key, key)\n\n\n# ---------------------------------------------------------------------------\n# PROVIDERS — 注册表。顺序 = 优先级。\n# ---------------------------------------------------------------------------\n\nPROVIDERS: tuple[ProviderSpec, ...] = (\n # === 直连(用户自行配置,无自动检测)================================\n ProviderSpec(\n name=\"custom\",\n keywords=(),\n env_key=\"\",\n display_name=\"Custom\",\n backend=\"openai_compat\",\n is_direct=True,\n ),\n ProviderSpec(\n name=\"custom_anthropic\",\n keywords=(),\n env_key=\"\",\n display_name=\"Custom (Anthropic API)\",\n backend=\"anthropic\",\n is_direct=True,\n ),\n ProviderSpec(\n name=\"azure_openai\",\n keywords=(\"azure\", \"azure_openai\"),\n env_key=\"\",\n display_name=\"Azure OpenAI\",\n backend=\"azure_openai\",\n is_direct=True,\n ),\n # === 网关(通过 api_key / api_base 检测,可路由任意模型)================\n ProviderSpec(\n name=\"openrouter\",\n keywords=(\"openrouter\",),\n env_key=\"OPENROUTER_API_KEY\",\n display_name=\"OpenRouter\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_key_prefix=\"sk-or-\",\n detect_by_base_keyword=\"openrouter\",\n default_api_base=\"https://openrouter.ai/api/v1\",\n supports_prompt_caching=True,\n ),\n ProviderSpec(\n name=\"aihubmix\",\n keywords=(\"aihubmix\",),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"AiHubMix\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_base_keyword=\"aihubmix\",\n default_api_base=\"https://aihubmix.com/v1\",\n strip_model_prefix=True,\n ),\n ProviderSpec(\n name=\"siliconflow\",\n keywords=(\"siliconflow\",),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"SiliconFlow\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_base_keyword=\"siliconflow\",\n default_api_base=\"https://api.siliconflow.cn/v1\",\n ),\n ProviderSpec(\n name=\"volcengine\",\n keywords=(\"volcengine\", \"volces\", \"ark\"),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"VolcEngine\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_base_keyword=\"volces\",\n default_api_base=\"https://ark.cn-beijing.volces.com/api/v3\",\n thinking_style=\"thinking_type\",\n ),\n ProviderSpec(\n name=\"volcengine_coding_plan\",\n keywords=(\"volcengine-plan\",),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"VolcEngine Coding Plan\",\n backend=\"openai_compat\",\n is_gateway=True,\n default_api_base=\"https://ark.cn-beijing.volces.com/api/coding/v3\",\n strip_model_prefix=True,\n thinking_style=\"thinking_type\",\n ),\n ProviderSpec(\n name=\"byteplus\",\n keywords=(\"byteplus\",),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"BytePlus\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_base_keyword=\"bytepluses\",\n default_api_base=\"https://ark.ap-southeast.bytepluses.com/api/v3\",\n strip_model_prefix=True,\n thinking_style=\"thinking_type\",\n ),\n ProviderSpec(\n name=\"byteplus_coding_plan\",\n keywords=(\"byteplus-plan\",),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"BytePlus Coding Plan\",\n backend=\"openai_compat\",\n is_gateway=True,\n default_api_base=\"https://ark.ap-southeast.bytepluses.com/api/coding/v3\",\n strip_model_prefix=True,\n thinking_style=\"thinking_type\",\n ),\n # === 标准 Provider(通过模型名称关键词匹配)============================\n ProviderSpec(\n name=\"anthropic\",\n keywords=(\"anthropic\", \"claude\"),\n env_key=\"ANTHROPIC_API_KEY\",\n display_name=\"Anthropic\",\n backend=\"anthropic\",\n default_api_base=\"https://api.anthropic.com/v1\",\n supports_prompt_caching=True,\n ),\n ProviderSpec(\n name=\"openai\",\n keywords=(\"openai\", \"gpt\"),\n env_key=\"OPENAI_API_KEY\",\n display_name=\"OpenAI\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.openai.com/v1\",\n supports_max_completion_tokens=True,\n ),\n ProviderSpec(\n name=\"openai_codex\",\n keywords=(\"openai-codex\",),\n env_key=\"\",\n display_name=\"OpenAI Codex\",\n backend=\"openai_codex\",\n detect_by_base_keyword=\"codex\",\n is_oauth=True,\n default_api_base=\"https://chatgpt.com/backend-api\",\n ),\n ProviderSpec(\n name=\"github_copilot\",\n keywords=(\"github_copilot\", \"copilot\"),\n env_key=\"\",\n display_name=\"GitHub Copilot\",\n backend=\"github_copilot\",\n is_oauth=True,\n default_api_base=\"https://api.githubcopilot.com\",\n strip_model_prefix=True,\n supports_max_completion_tokens=True,\n ),\n ProviderSpec(\n name=\"deepseek\",\n keywords=(\"deepseek\",),\n env_key=\"DEEPSEEK_API_KEY\",\n display_name=\"DeepSeek\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.deepseek.com\",\n thinking_style=\"thinking_type\",\n reasoning_model_patterns=(\"deepseek-v4-pro\", \"deepseek-reasoner\"),\n ),\n ProviderSpec(\n name=\"gemini\",\n keywords=(\"gemini\",),\n env_key=\"GEMINI_API_KEY\",\n display_name=\"Gemini\",\n backend=\"openai_compat\",\n default_api_base=\"https://generativelanguage.googleapis.com/v1beta/openai/\",\n ),\n ProviderSpec(\n name=\"zhipu\",\n keywords=(\"zhipu\", \"glm\", \"zai\"),\n env_key=\"ZAI_API_KEY\",\n display_name=\"Zhipu AI\",\n backend=\"openai_compat\",\n env_extras=((\"ZHIPUAI_API_KEY\", \"{api_key}\"),),\n default_api_base=\"https://open.bigmodel.cn/api/paas/v4\",\n ),\n ProviderSpec(\n name=\"dashscope\",\n keywords=(\"qwen\", \"dashscope\"),\n env_key=\"DASHSCOPE_API_KEY\",\n display_name=\"DashScope\",\n backend=\"openai_compat\",\n default_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n thinking_style=\"enable_thinking\",\n ),\n ProviderSpec(\n name=\"moonshot\",\n keywords=(\"moonshot\", \"kimi\"),\n env_key=\"MOONSHOT_API_KEY\",\n display_name=\"Moonshot\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.moonshot.cn/v1\",\n model_overrides=(\n (\"kimi-k2.5\", {\"temperature\": 1.0}),\n (\"kimi-k2.6\", {\"temperature\": 1.0}),\n ),\n ),\n ProviderSpec(\n name=\"minimax\",\n keywords=(\"minimax\",),\n env_key=\"MINIMAX_API_KEY\",\n display_name=\"MiniMax\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.minimaxi.com/v1\",\n thinking_style=\"reasoning_split\",\n ),\n ProviderSpec(\n name=\"minimax_anthropic\",\n keywords=(\"minimax_anthropic\",),\n env_key=\"MINIMAX_API_KEY\",\n display_name=\"MiniMax (Anthropic)\",\n backend=\"anthropic\",\n default_api_base=\"https://api.minimaxi.com/anthropic\",\n ),\n ProviderSpec(\n name=\"mistral\",\n keywords=(\"mistral\",),\n env_key=\"MISTRAL_API_KEY\",\n display_name=\"Mistral\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.mistral.ai/v1\",\n ),\n ProviderSpec(\n name=\"stepfun\",\n keywords=(\"stepfun\", \"step\"),\n env_key=\"STEPFUN_API_KEY\",\n display_name=\"Step Fun\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.stepfun.com/v1\",\n ),\n ProviderSpec(\n name=\"xiaomi_mimo\",\n keywords=(\"xiaomi_mimo\", \"mimo\"),\n env_key=\"XIAOMIMIMO_API_KEY\",\n display_name=\"Xiaomi MIMO\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.xiaomimimo.com/v1\",\n ),\n # === 本地部署 ==========================================================\n ProviderSpec(\n name=\"vllm\",\n keywords=(\"vllm\",),\n env_key=\"HOSTED_VLLM_API_KEY\",\n display_name=\"vLLM/Local\",\n backend=\"openai_compat\",\n is_local=True,\n ),\n ProviderSpec(\n name=\"ollama\",\n keywords=(\"ollama\", \"nemotron\"),\n env_key=\"OLLAMA_API_KEY\",\n display_name=\"Ollama\",\n backend=\"openai_compat\",\n is_local=True,\n detect_by_base_keyword=\"11434\",\n default_api_base=\"http://localhost:11434/v1\",\n ),\n ProviderSpec(\n name=\"lm_studio\",\n keywords=(\"lm-studio\", \"lmstudio\", \"lm_studio\"),\n env_key=\"LM_STUDIO_API_KEY\",\n display_name=\"LM Studio\",\n backend=\"openai_compat\",\n is_local=True,\n detect_by_base_keyword=\"1234\",\n default_api_base=\"http://localhost:1234/v1\",\n ),\n ProviderSpec(\n name=\"llama_cpp\",\n keywords=(\"llama_cpp\", \"llama.cpp\"),\n env_key=\"\",\n display_name=\"llama.cpp\",\n backend=\"openai_compat\",\n is_local=True,\n detect_by_base_keyword=\"8080\",\n default_api_base=\"http://localhost:8080/v1\",\n ),\n ProviderSpec(\n name=\"ovms\",\n keywords=(\"openvino\", \"ovms\"),\n env_key=\"\",\n display_name=\"OpenVINO Model Server\",\n backend=\"openai_compat\",\n is_direct=True,\n is_local=True,\n default_api_base=\"http://localhost:8000/v3\",\n ),\n # === 辅助 ============================================================\n ProviderSpec(\n name=\"nvidia_nim\",\n keywords=(\"nvidia_nim\", \"nvidia-nim\", \"nim\"),\n env_key=\"NVIDIA_NIM_API_KEY\",\n display_name=\"NVIDIA NIM\",\n backend=\"openai_compat\",\n is_gateway=True,\n detect_by_key_prefix=\"nvapi-\",\n detect_by_base_keyword=\"api.nvidia.com\",\n default_api_base=\"https://integrate.api.nvidia.com/v1\",\n supports_stream_options=False,\n ),\n ProviderSpec(\n name=\"groq\",\n keywords=(\"groq\",),\n env_key=\"GROQ_API_KEY\",\n display_name=\"Groq\",\n backend=\"openai_compat\",\n default_api_base=\"https://api.groq.com/openai/v1\",\n ),\n ProviderSpec(\n name=\"qianfan\",\n keywords=(\"qianfan\", \"ernie\"),\n env_key=\"QIANFAN_API_KEY\",\n display_name=\"Qianfan\",\n backend=\"openai_compat\",\n default_api_base=\"https://qianfan.baidubce.com/v2\",\n ),\n)\n\n\nNANOBOT_LLM_PROVIDERS: tuple[str, ...] = tuple(spec.name for spec in PROVIDERS)\n\n\ndef find_by_name(name: str | None) -> ProviderSpec | None:\n canonical = canonical_provider_name(name)\n if not canonical:\n return None\n for spec in PROVIDERS:\n if spec.name == canonical:\n return spec\n return None\n\n\ndef find_by_model(model: str | None) -> ProviderSpec | None:\n if not model:\n return None\n model_lower = model.lower()\n model_normalized = model_lower.replace(\"-\", \"_\")\n model_prefix = model_lower.split(\"/\", 1)[0] if \"/\" in model_lower else \"\"\n normalized_prefix = model_prefix.replace(\"-\", \"_\")\n standard_specs = [s for s in PROVIDERS if not s.is_gateway and not s.is_local]\n\n for spec in standard_specs:\n if model_prefix and normalized_prefix == spec.name:\n return spec\n for spec in standard_specs:\n if any(\n kw in model_lower or kw.replace(\"-\", \"_\") in model_normalized for kw in spec.keywords\n ):\n return spec\n return None\n\n\ndef find_gateway(\n provider_name: str | None = None,\n api_key: str | None = None,\n api_base: str | None = None,\n) -> ProviderSpec | None:\n spec = find_by_name(provider_name)\n if spec and (spec.is_gateway or spec.is_local):\n return spec\n\n for spec in PROVIDERS:\n if spec.detect_by_key_prefix and api_key and api_key.startswith(spec.detect_by_key_prefix):\n return spec\n if spec.detect_by_base_keyword and api_base and spec.detect_by_base_keyword in api_base:\n return spec\n return None\n\n\ndef strip_provider_prefix(model: str, spec: ProviderSpec | None) -> str:\n \"\"\"如果适用,从模型名称中去除 provider/ 前缀。\"\"\"\n if not model or not spec:\n return model\n if spec.strip_model_prefix and \"/\" in model:\n return model.split(\"/\", 1)[1]\n return model\n\n\n__all__ = [\n \"ProviderSpec\",\n \"PROVIDERS\",\n \"NANOBOT_LLM_PROVIDERS\",\n \"PROVIDER_ALIASES\",\n \"canonical_provider_name\",\n \"find_by_name\",\n \"find_by_model\",\n \"find_gateway\",\n \"strip_provider_prefix\",\n]\n"}}}}