Show / hide:

🐳 Docker AI Agent — how it works (Mac)

This page explains what the local AI agent does, the four pieces it runs in Docker, and how to install Docker on macOS so you can run it on your own machine.

หน้านี้อธิบายว่า local AI agent ทำอะไร ประกอบด้วยสี่ชิ้นใน Docker อะไรบ้าง และวิธีติดตั้ง Docker บน macOS เพื่อให้รันเองได้

本页讲解这个 local AI agent 做什么、Docker 里跑的四个组件分别是什么、以及如何在 macOS 上装 Docker,让你能在自己电脑上跑起来。

On this page
  1. What you get
  2. The four services
  3. Identity & context dirs
  4. How a chat turn flows
  5. Voice (mic in, TTS out)
  6. What is Docker?
  7. Install Docker on macOS
  8. Running this agent

1. What you get

A self-hosted chatbot that:

แชทบอทที่โฮสต์เอง ทำได้ดังนี้:

一个自托管的聊天机器人,它能:

Trade-off. "Local" here means the language model (Ollama) and speech-to-text (Whisper) run on your machine. The TTS uses Microsoft Edge's free neural voices, which require an internet connection at speak-time but no account or API key. Swap to a fully offline TTS if you need air-gapped operation.

ข้อแลกเปลี่ยน คำว่า "local" ที่นี่หมายถึงโมเดลภาษา (Ollama) และระบบแปลงเสียงเป็นข้อความ (Whisper) รันในเครื่องคุณ ส่วน TTS ใช้เสียงนิวรัลฟรีของ Microsoft Edge ต้องการอินเทอร์เน็ตตอนพูด แต่ไม่ต้องใช้บัญชีหรือ API key เปลี่ยนเป็น TTS แบบออฟไลน์ทั้งหมดได้ถ้าต้องการตัดเน็ตเลย

权衡。这里说的 "local" 是指语言模型(Ollama)和语音转文字(Whisper)在你机器上跑。TTS 用的是微软 Edge 的免费神经语音,朗读时要联网,但不要账号也不要 API 密钥。要完全离线运行的话,可以换成全本地 TTS。

2. The four services

When you run docker compose up -d (defined in docker-compose.yml), four containers come up on a private docker network. Your browser only talks to agent; agent fans out to the other three over the internal network.

เมื่อรัน docker compose up -d (กำหนดใน docker-compose.yml) จะมี container สี่ตัวขึ้นมาในเครือข่าย docker ส่วนตัว เบราว์เซอร์ของคุณคุยกับ agent เท่านั้น agent จะส่งต่อไปยังอีกสามตัวผ่านเครือข่ายภายใน

运行 docker compose up -d(在 docker-compose.yml 里定义)后,四个容器会启动在一个私有 docker 网络里。你的浏览器只跟 agent 通信;agent 在内网里把请求转给另外三个。

docker network: local_ai_agent_default your browser localhost:8080 agent FastAPI · :8080 identity + LlamaIndex + web UI ollama LLM + embeddings · :11434 qwen2.5:3b · nomic-embed-text whisper faster-whisper STT · :9000 tts edge-tts neural voices · :8001 HTTP ./identity (ro) ./context (ro) context_index
four containers on one private docker network — your browser only sees the agent

agent

FastAPI · port 8080

The brains. Loads your persona from identity/, builds a LlamaIndex vector index over context/, serves the web UI, and orchestrates calls to the other three services. See main.py.

ตัวสมอง โหลด persona จาก identity/ สร้าง LlamaIndex vector index จาก context/ เสิร์ฟ web UI และประสานงานเรียกอีกสามบริการ ดู main.py

大脑。从 identity/ 加载角色设定,给 context/ 建 LlamaIndex 向量索引,提供网页 UI,并协调对其它三个服务的调用。见 main.py

ollama

Local LLM runtime · port 11434

Runs open-weight language models (default qwen2.5:3b) on your CPU or GPU. Also serves the embedding model used to index your context.

รันโมเดลภาษา open-weight (ค่าเริ่มต้น qwen2.5:3b) บน CPU หรือ GPU พร้อมเสิร์ฟโมเดล embedding สำหรับสร้าง index ของ context ด้วย

在你的 CPU 或 GPU 上跑开源权重的语言模型(默认 qwen2.5:3b)。同时也提供用来索引你 context 的嵌入模型。

whisper

OpenAI Whisper ASR · port 9000

Turns microphone recordings into text. Runs the faster-whisper engine — small model by default, fits on a laptop.

แปลงการบันทึกเสียงจากไมค์เป็นข้อความ ใช้ engine faster-whisper โมเดล small เป็นค่าเริ่มต้น พอใส่ในแล็ปท็อปได้

把麦克风录音转成文字。用 faster-whisper 引擎,默认 small 模型,笔记本能跑得动。

tts

Edge Neural Voices · port 8001

Turns text into spoken audio (WAV). Auto-detects script — English, Thai, Mandarin, Japanese, Korean each get the right voice; mixed-language replies are concatenated. Code: tts/server.py.

แปลงข้อความเป็นเสียง (WAV) ตรวจสคริปต์อัตโนมัติ — อังกฤษ ไทย จีน ญี่ปุ่น เกาหลี ได้เสียงที่ถูกของแต่ละภาษา ข้อความหลายภาษาผสมกันจะถูกต่อกัน โค้ดอยู่ที่ tts/server.py

把文字变成语音(WAV)。自动识别脚本 — 英、泰、中、日、韩各用对的嗓音;混合语言的回复会拼接起来。代码在 tts/server.py

3. Identity & context dirs

Identity — who the agent is

On boot the agent walks identity/ and reads every .md file. Each filename becomes a section header in the system prompt:

ตอน boot agent จะวนอ่านทุกไฟล์ .md ใน identity/ ชื่อไฟล์แต่ละไฟล์กลายเป็นหัวข้อใน system prompt:

启动时 agent 会遍历 identity/,读取每个 .md 文件。每个文件名变成 system prompt 里的一个小节标题:

identity/
  name.md          → first non-empty line is the display name
  job.md           → ## Job
  personality.md   → ## Personality
  tasks.md         → ## Tasks
  style.md         → ## Style       (anything you add is included)

Want a different agent? Edit the files. Restart the container. No code changes.

อยากได้ agent แบบอื่น? แก้ไฟล์ รีสตาร์ท container ไม่ต้องแก้โค้ด

想换个不同的 agent?改文件、重启容器、不用动代码。

Context — what the agent knows

Drop .md or .txt files into context/. First boot indexes them with LlamaIndex + Ollama embeddings, persists the vectors to a Docker volume, and reuses the index on every restart.

วางไฟล์ .md หรือ .txt ใน context/ boot ครั้งแรกจะสร้าง index ด้วย LlamaIndex + Ollama embeddings เก็บ vector ไว้ใน Docker volume และใช้ index เดิมในการ restart ครั้งถัดไป

.md.txt 文件丢进 context/。第一次启动用 LlamaIndex + Ollama 嵌入做索引,把向量持久化到 Docker 卷里,之后每次重启都复用这个索引。

Every chat turn:

ทุกครั้งที่แชท:

每次对话回合:

  1. The user's message is embedded. ข้อความผู้ใช้ถูก embed 把用户消息做嵌入。
  2. The top-K most similar chunks (default 3) are retrieved. ดึง chunk ที่คล้ายที่สุด top-K (ค่าเริ่มต้น 3) 取最相似的 top-K 个片段(默认 3 个)。
  3. Those chunks are injected as a system message before the model generates a reply. ใส่ chunk เหล่านั้นเป็น system message ก่อนให้โมเดลตอบ 把这些片段当作 system message 注入,再让模型生成回复。
  4. The chunks' filenames come back as sources: citations under the bot's reply. ชื่อไฟล์ของ chunk กลับมาเป็น sources: ใต้คำตอบของบอท 片段所在的文件名以 sources: 形式跟在 bot 回复下面。

Added new files? curl -X POST http://localhost:8080/reindex rebuilds without restarting.

เพิ่มไฟล์ใหม่? curl -X POST http://localhost:8080/reindex สร้าง index ใหม่ได้ไม่ต้องรีสตาร์ท

加了新文件?curl -X POST http://localhost:8080/reindex 重建索引,不用重启。

4. How a chat turn flows

This is the path a single text message takes from your keyboard to a streamed reply. Each box on the left is what the user sees / sends; each box on the right is what's actually happening inside the agent container.

นี่คือเส้นทางที่ข้อความหนึ่งข้อความเดินทางจากคีย์บอร์ดของคุณไปสู่การ stream คำตอบกลับ กล่องด้านซ้ายคือสิ่งที่ผู้ใช้เห็น/ส่ง กล่องด้านขวาคือสิ่งที่เกิดขึ้นจริงใน container ของ agent

这是一条文本消息从键盘到流式回复的路径。左边的方框是用户看到 / 发送的内容;右边的方框是 agent 容器内部实际发生的事。

INPUT (browser) INSIDE THE AGENT OUTPUT (browser) user types message "what's the merit cap?" 1. embed via ollama nomic-embed-text → 768-dim vector 2. retrieve top-3 chunks llama-index → context_index volume 3. build messages array [system_prompt + grounded_chunks + chat_history + user_message] identity comes from here 4. ollama streams tokens POST /api/chat stream=true SSE stream {"chunk":"the"} {"chunk":" cap"} {"chunk":" is..."} {"done":true, "citations":[...]} browser renders progressively, shows "sources: combat_balance, monsters" total latency on CPU: ~0.3 s embed + ~0.05 s retrieve + ~3-8 s generation
a single /chat turn — RAG retrieval grounds the reply, SSE streams it token by token

Server-Sent Events (SSE) on POST /chat stream each token as a data: {"chunk":"..."} line, then a final {"done":true,"citations":[...]}.

Server-Sent Events (SSE) บน POST /chat ส่ง token แต่ละตัวเป็นบรรทัด data: {"chunk":"..."} แล้วปิดด้วย {"done":true,"citations":[...]}

POST /chat 用 Server-Sent Events(SSE)流式传 token,每个 token 一行 data: {"chunk":"..."},最后一条是 {"done":true,"citations":[...]}

Inputs and outputs of every endpoint

One view of the whole agent as a black box — everything it accepts and everything it produces:

มอง agent เป็นกล่องดำ — ทุกอย่างที่รับเข้าและทุกอย่างที่ส่งออก:

把整个 agent 当成黑盒 — 它接收的所有输入和产生的所有输出:

agent FastAPI on :8080 main.py build_messages() INPUTS identity/*.md read once at boot → system prompt context/**/*.md|txt embedded once → vector index POST /chat {message, history[]} POST /converse audio file (webm) POST /speak {text, language?} POST /reindex (no body — rebuild from disk) OUTPUTS GET /identity {name, files, system_prompt} GET /health {ollama,whisper,tts,rag : ok} /chat → text/event-stream {chunk}…{done,citations} /converse → JSON {user, bot, audio(b64), citations} /speak → JSON {audio: base64 WAV} /reindex → JSON {state: "ready"|"empty"|"error"}
every endpoint the agent exposes — six inputs on the left, six outputs on the right

5. Voice (mic in, TTS out)

🎙 your mic webm whisper faster-whisper speech → text "text" agent + RAG same path as /chat retrieve → ollama grounded reply "text" tts edge-tts text → speech WAV 🔊 browser POST /converse — one round trip, hands-free POST /speak — text → audio only (skip mic + LLM) POST /chat — text in / text out (skip mic + tts)
voice loop — /converse chains all three services in one request; /speak and /chat are the partial paths

Mic → text → reply → audio

Holding the 🎙 button records via the browser's MediaRecorder, posts the audio blob to POST /converse:

กดปุ่ม 🎙 ค้างไว้จะอัดเสียงผ่าน MediaRecorder ของเบราว์เซอร์ แล้วส่ง blob เสียงไปที่ POST /converse:

按住 🎙 按钮,浏览器用 MediaRecorder 录音,然后把音频 blob 发到 POST /converse

  1. Agent forwards the WebM clip to whisper's /asr. agent ส่ง WebM clip ไปที่ /asr ของ whisper agent 把 WebM 音频转发给 whisper 的 /asr
  2. Whisper returns transcribed text. whisper คืนข้อความที่ถอดเสียงแล้ว whisper 返回转写出的文本。
  3. Same RAG + Ollama path as a text chat. ใช้ RAG + Ollama เส้นทางเดียวกับการแชทด้วยข้อความ 和文本聊天同一套 RAG + Ollama 路径。
  4. Reply text goes to tts → base64 WAV → browser auto-plays it. ข้อความตอบส่งเข้า tts → base64 WAV → เบราว์เซอร์เล่นอัตโนมัติ 回复文本进 tts → base64 WAV → 浏览器自动播放。

Text → audio only

The 🔊 button under each bot message calls POST /speak {text} and plays the result. The 🔇/🔊 toggle next to the mic flips autoplay on, so every reply spoken aloud as soon as it streams.

ปุ่ม 🔊 ใต้ข้อความแต่ละข้อความเรียก POST /speak {text} แล้วเล่นผล ปุ่ม 🔇/🔊 ข้างไมค์เปิด autoplay ทำให้ทุกคำตอบถูกอ่านออกเสียงทันทีที่ stream

每条 bot 消息下面的 🔊 按钮会调 POST /speak {text} 然后播放。麦克风旁边的 🔇/🔊 开关用来打开自动播放,每条回复一来就读出来。

Multilingual. The TTS service segments by script — "Hello! สวัสดี" is split into an English clip (Jenny) and a Thai clip (Premwadee), then concatenated with ffmpeg. No language flag needed at call-time.

หลายภาษา TTS แบ่งเซกเมนต์ตามสคริปต์ — "Hello! สวัสดี" ถูกแบ่งเป็นคลิปอังกฤษ (Jenny) และคลิปไทย (Premwadee) แล้วต่อกันด้วย ffmpeg ไม่ต้องระบุภาษาตอนเรียก

多语言。TTS 按脚本分段 — "Hello! สวัสดี" 会拆成一段英文(Jenny)和一段泰文(Premwadee),再用 ffmpeg 拼接。调用时不需要指定语言。

6. What is Docker?

Docker is a way of packaging an app together with everything it needs to run — operating system libraries, language runtimes, model weights — into a single immutable unit called an image. When you run an image, you get a container: an isolated process tree that thinks it's the only thing on a Linux machine.

Docker เป็นวิธี แพ็คแอปพร้อมทุกอย่างที่ต้องใช้รัน — ไลบรารีระบบ ตัวรันภาษาโปรแกรม น้ำหนักโมเดล — เข้าด้วยกันในหน่วยเดียวที่เปลี่ยนแปลงไม่ได้ เรียกว่า image เมื่อรัน image จะได้ container: ทรีของ process ที่แยกออกมา เข้าใจว่าตัวเองเป็นสิ่งเดียวบนเครื่อง Linux

Docker 是把 一个应用和它运行所需要的一切打包在一起 — 系统库、语言运行时、模型权重 — 装进一个不可变的单元,叫 image(镜像)。运行一个 image 就得到一个 container(容器):一棵隔离的进程树,自以为是 Linux 上唯一的东西。

Two things make it useful for this kind of project:

มีสองเหตุผลที่ Docker มีประโยชน์กับโปรเจคแบบนี้:

对这种项目来说,它有两个特别有用的地方:

ProblemHow Docker helps
Installing Ollama, Whisper, ffmpeg, Python + 30 pip packages by hand Each service ships pre-built. docker compose up downloads and runs them. No "works on my machine."
Four programs that need to talk to each other on local ports Compose creates a private network. The agent reaches the LLM at http://ollama:11434 by service name — no IP wrangling.
Cleaning up half-installed dependencies later docker compose down -v removes everything. Your real OS is untouched.

The two key files in this project:

ไฟล์สำคัญสองไฟล์ในโปรเจคนี้:

这个项目里两个关键文件:

7. Install Docker on macOS

On a Mac, "Docker" means Docker Desktop — a single app that bundles the Docker engine, the CLI, the Compose plugin, and a tiny Linux VM (containers are Linux-native; macOS runs them inside a VM).

บน Mac คำว่า "Docker" หมายถึง Docker Desktop — แอปเดียวที่รวม Docker engine, CLI, Compose plugin และ Linux VM เล็ก ๆ (container เป็นของ Linux โดยกำเนิด macOS รันใน VM)

在 Mac 上 "Docker" 指的是 Docker Desktop — 一个应用打包了 Docker 引擎、CLI、Compose 插件和一个小型 Linux 虚拟机(容器是 Linux 原生的,macOS 在 VM 里跑它们)。

  1. Check your chip. Click the Apple menu → About This Mac. Look for "Chip: Apple M1 / M2 / M3 / M4" (Apple silicon) or "Processor: Intel" (older Macs). You'll need the matching installer.

    เช็คชิปก่อน เมนู Apple → About This Mac ดูคำว่า "Chip: Apple M1 / M2 / M3 / M4" (Apple silicon) หรือ "Processor: Intel" (Mac รุ่นเก่า) ต้องใช้ installer ที่ตรงกัน

    先看芯片。苹果菜单 → 关于本机。看 "芯片:Apple M1 / M2 / M3 / M4"(Apple 芯片)还是 "处理器:Intel"(老款 Mac)。要用对应的安装包。

  2. Download Docker Desktop. Go to docker.com/products/docker-desktop and pick: Mac with Apple silicon for M1/M2/M3/M4, or Mac with Intel chip for older Macs. Wrong installer = it won't launch.

    ดาวน์โหลด Docker Desktop ไปที่ docker.com/products/docker-desktop เลือก Mac with Apple silicon ถ้าเป็น M1/M2/M3/M4 หรือ Mac with Intel chip ถ้าเป็น Mac รุ่นเก่า เลือกผิด = เปิดไม่ขึ้น

    下载 Docker Desktop。docker.com/products/docker-desktop 选:M1/M2/M3/M4 选 Mac with Apple silicon,老 Mac 选 Mac with Intel chip。装错版本 = 起不来。

  3. Install. Double-click the downloaded .dmg, drag the Docker whale into Applications, then open it from Launchpad. macOS will ask for your password to grant network/privileged-helper permissions — say yes.

    ติดตั้ง ดับเบิ้ลคลิก .dmg ที่ดาวน์โหลดมา ลาก Docker whale เข้า Applications แล้วเปิดจาก Launchpad macOS จะถามรหัสผ่านเพื่อให้สิทธิ์เครือข่าย/privileged-helper — กด yes

    安装。双击下载的 .dmg,把 Docker 鲸鱼图标拖进 Applications,然后从 Launchpad 打开。macOS 会要密码授予网络 / privileged-helper 权限 — 同意。

  4. Wait for the whale. The Docker icon appears in your menu bar (top right). It animates while the VM starts. When it stops animating and says "Docker Desktop is running", you're ready.

    รอ whale ไอคอน Docker จะขึ้นที่ menu bar (มุมขวาบน) มันจะเคลื่อนไหวระหว่างที่ VM เริ่ม เมื่อหยุดเคลื่อนไหวและขึ้น "Docker Desktop is running" ก็พร้อมใช้

    等鲸鱼。Docker 图标出现在菜单栏(右上角)。VM 启动时它会动。停下不动并显示 "Docker Desktop is running",就可以用了。

  5. Verify in the terminal. Open Terminal.app (or iTerm) and run:

    ตรวจสอบใน terminal เปิด Terminal.app (หรือ iTerm) แล้วรัน:

    在 terminal 里验证。打开 Terminal.app(或 iTerm)运行:

    docker --version
    docker compose version

    Both should print a version. If you see command not found, restart Terminal — Docker Desktop adds itself to your PATH on first launch.

    ทั้งสองต้องพิมพ์เวอร์ชันออกมา ถ้าเห็น command not found ให้รีสตาร์ท Terminal — Docker Desktop เพิ่มตัวเองใน PATH ตอนรันครั้งแรก

    两条都应该打印出版本号。看到 command not found 的话重启 Terminal — Docker Desktop 第一次启动才把自己加进 PATH。

  6. Give it room. Open Docker Desktop → Settings (⚙) → Resources. Bump Memory to at least 6 GB (the LLM needs it) and Disk image size to at least 40 GB (the model weights and indices add up). Apply & Restart.

    ให้ที่ เปิด Docker Desktop → Settings (⚙) → Resources เพิ่ม Memory อย่างน้อย 6 GB (LLM ต้องใช้) และ Disk image size อย่างน้อย 40 GB (น้ำหนักโมเดลกับ index รวมแล้วเยอะ) Apply & Restart

    给它空间。Docker Desktop → 设置(⚙)→ Resources。把 Memory 调到至少 6 GB(LLM 需要),Disk image size 至少 40 GB(模型权重和索引加起来不小)。Apply & Restart。

Apple silicon GPU note. Ollama on Apple silicon uses the integrated GPU via Metal automatically — no driver setup needed. Whisper inside the container runs on CPU only (Docker Desktop's Linux VM can't reach the Metal GPU). If you want GPU-accelerated transcription on a Mac, run Whisper natively outside Docker.

หมายเหตุ GPU Apple silicon Ollama บน Apple silicon ใช้ GPU ในตัวผ่าน Metal โดยอัตโนมัติ ไม่ต้องตั้งค่าไดรเวอร์ Whisper ใน container รันบน CPU เท่านั้น (Linux VM ของ Docker Desktop เข้าถึง Metal GPU ไม่ได้) ถ้าอยากให้ Whisper ใช้ GPU บน Mac ต้องรันแยกข้างนอก Docker

Apple 芯片 GPU 提示。Apple 芯片上的 Ollama 会通过 Metal 自动用集成 GPU — 不用配驱动。容器里的 Whisper 只能跑 CPU(Docker Desktop 的 Linux VM 摸不到 Metal GPU)。Mac 上要 GPU 加速转写的话,得在 Docker 之外原生跑 Whisper。

8. Running this agent

Once Docker is installed:

เมื่อติดตั้ง Docker เสร็จแล้ว:

装完 Docker 后:

  1. Open a terminal in this project's folder.

    เปิด terminal ที่โฟลเดอร์ของโปรเจคนี้

    在项目目录里打开 terminal。

    cd /path/to/local_ai_agent
  2. Start the stack. First run pulls ~5 GB of images. Subsequent runs start in seconds.

    เริ่ม stack ครั้งแรกจะดึง image ~5 GB ครั้งถัดไปขึ้นในไม่กี่วินาที

    启动栈。第一次会拉 ~5 GB 镜像。之后几秒就起来。

    docker compose up -d
  3. Pull the models. Ollama doesn't ship with any models — pull two:

    ดึงโมเดล Ollama ไม่มาพร้อมโมเดล — ดึงสองตัว:

    拉模型。Ollama 不自带模型 — 拉两个:

    docker compose exec ollama ollama pull qwen2.5:3b
    docker compose exec ollama ollama pull nomic-embed-text

    These live in the ollama_data Docker volume and persist across restarts.

    โมเดลอยู่ใน Docker volume ollama_data และอยู่รอดข้ามการรีสตาร์ท

    这些模型存在 ollama_data 这个 Docker 卷里,重启后还在。

  4. Open the UI. Visit http://localhost:8080. The header should show your agent's name and four green pills: rag, ollama, whisper, tts.

    เปิด UI ไปที่ http://localhost:8080 ส่วนหัวควรแสดงชื่อ agent ของคุณกับ pill สีเขียวสี่ตัว: rag, ollama, whisper, tts

    打开 UI。访问 http://localhost:8080。顶栏应该显示你 agent 的名字和四个绿色标签:ragollamawhispertts

  5. Customise. Edit files in identity/ to change the agent's persona, drop your docs into context/, then:

    ปรับแต่ง แก้ไฟล์ใน identity/ เพื่อเปลี่ยน persona ของ agent ใส่เอกสารของคุณใน context/ แล้ว:

    自定义。identity/ 里的文件来换 agent 的角色,把你的文档丢进 context/,然后:

    docker compose restart agent          # picks up new identity/
    curl -X POST http://localhost:8080/reindex  # picks up new context/
  6. Stop it. docker compose down stops everything but keeps the indexed context and downloaded models. docker compose down -v wipes the volumes too — a full reset.

    หยุด docker compose down หยุดทุกอย่างแต่เก็บ index และโมเดลที่ดาวน์โหลดไว้ docker compose down -v ล้าง volume ด้วย — รีเซ็ตทั้งหมด

    停止。docker compose down 停掉所有服务但保留索引和已下载的模型。docker compose down -v 把卷也清掉 — 全部重置。


All source files are linked at the top of this page or on GitHub: github.com/ddtraveller/watdonchan/tree/main/local_ai_agent. The README has the same install steps as a cheatsheet.

ไฟล์ต้นทางทั้งหมดลิงก์อยู่ด้านบนของหน้านี้หรือบน GitHub: github.com/ddtraveller/watdonchan/tree/main/local_ai_agent README มีขั้นตอนติดตั้งแบบเดียวกันเป็น cheatsheet

所有源代码文件都在页面顶部或 GitHub 上:github.com/ddtraveller/watdonchan/tree/main/local_ai_agentREADME 里有同样的安装步骤速查表。