AI Docs Assistant

The dbbot website includes a lightweight AI docs assistant for answering questions from the public documentation. It does not require MySQL, Redis, or a vector database. The backend reads the Hugo offline search indexes and calls the OpenCode Go DeepSeek model to generate the final answer.

Architecture

Browser
  -> /api/docs/ask
  -> dbbot-docs-assistant
      -> public/offline-search-index.*.json
      -> OpenCode Go / DeepSeek

The first implementation uses the existing Docsy offline search indexes:

  • public/offline-search-index.zh-cn.*.json
  • public/offline-search-index.en.*.json

Build the Hugo site first, then start or restart the docs assistant.

Build

npm run build
npm run build:assistant

The backend binary is written to:

bin/dbbot-docs-assistant

Environment

Minimal configuration:

OPENCODE_GO_API_KEY=replace-with-your-opencode-go-api-key
DOCS_ASSISTANT_INDEX_GLOB=/var/www/dbbot.ai/public/offline-search-index.*.json

Common options:

DOCS_ASSISTANT_ADDR=127.0.0.1:8787
DOCS_ASSISTANT_MODEL=deepseek-v4-flash
DOCS_ASSISTANT_ENDPOINT=https://opencode.ai/zen/go/v1/chat/completions
DOCS_ASSISTANT_PER_IP_MINUTE_LIMIT=5
DOCS_ASSISTANT_DAILY_REQUEST_LIMIT=300
DOCS_ASSISTANT_CACHE_TTL_SECONDS=21600
DOCS_ASSISTANT_CACHE_ENTRIES=256

The default model is deepseek-v4-flash. Documentation Q&A usually does not need the stronger reasoning model; a later “deep answer” mode can switch a separate entry point to deepseek-v4-pro.

Local Run

export OPENCODE_GO_API_KEY=replace-with-your-opencode-go-api-key
export DOCS_ASSISTANT_INDEX_GLOB=public/offline-search-index.*.json
npm run dev:assistant

Health check:

curl http://127.0.0.1:8787/healthz

Ask a question:

curl -s http://127.0.0.1:8787/api/docs/ask \
  -H 'Content-Type: application/json' \
  -d '{"lang":"en","question":"What is dbbot?"}'

Nginx

Merge the location /api/docs/ block from scripts/nginx-docs-assistant-location.conf into the dbbot.ai server block, then run:

nginx -t
systemctl reload nginx

The frontend calls /api/docs/ask by default, so the static site and API service should be served from the same domain.

systemd

Reference files:

  • scripts/dbbot-docs-assistant.env.example
  • scripts/dbbot-docs-assistant.service

For production, keep using the unified deploy script:

cd /opt/dbbot_web
sudo BRANCH="admin" \
APP_DIR="/opt/dbbot_web" \
SITE_ROOT="/var/www/dbbot.ai/public" \
BASE_URL="https://dbbot.ai/" \
bash scripts/deploy-from-git-on-server.sh

The script automatically builds and restarts the docs assistant when /etc/dbbot-docs-assistant.env exists or when OPENCODE_GO_API_KEY is passed for this run.

Typical deployment:

install -m 755 bin/dbbot-docs-assistant /usr/local/bin/dbbot-docs-assistant
install -m 600 scripts/dbbot-docs-assistant.env.example /etc/dbbot-docs-assistant.env
install -m 644 scripts/dbbot-docs-assistant.service /etc/systemd/system/dbbot-docs-assistant.service
systemctl daemon-reload
systemctl enable --now dbbot-docs-assistant

Edit /etc/dbbot-docs-assistant.env and set the real OPENCODE_GO_API_KEY before starting the service.

Runtime Boundaries

  • Do not expose the API key to the browser.
  • Do not write user questions into MySQL.
  • Do not execute commands from user prompts.
  • Answer only from retrieved public documentation snippets.
  • If the docs do not clearly state an answer, say so.
  • Nginx rate limits /api/docs/ask by IP and returns 429 when the limit is exceeded.
  • The Go service also applies per-IP minute limits, a daily site-wide limit, and in-process response caching.

These boundaries keep the service suitable for a small 2c4g server and avoid turning documentation Q&A into an operations execution surface.