Skip to content

Latest commit

 

History

History
582 lines (438 loc) · 20.4 KB

EN-README.md

File metadata and controls

582 lines (438 loc) · 20.4 KB

ChatAPI

English | 简体中文 | 繁體中文

[Telegram] | [LinuxDO] | [BiliBili]
This project allows various AI clients to call a human using the OpenAI Responses style API, and comes with a web console interface to help you assemble Tool Calling requests or set up auto-reply rules.
Through this project, you can let others configure you as an Agent or chatbot, and then you play the role of an AI assistant being called. You can also use it as a Mock LLM when developing your own Agent.

  • Backend: Flask
  • Frontend: React + Vite + Ant Design
  • Data storage: SQLite

Default features:

  • Login with username/password based on .env, optional TOTP support
  • Support for three API interfaces: /v1/chat/completions, /v1/responses, /messages
  • Conversation list and message persistence for debugging and context inspection
  • Automated reply output, supports scheduled streaming, loop output, conditional auto-reply, etc.
  • Optional ntfy message push

1. Deployment

Single-binary build

Run from the repository root:

make build EMBED_FRONTEND=1

This builds the frontend and compiles it into build/chatapi with the Go embed_frontend build tag. The executable does not require CHATAPI_WEB_DIST_DIR at runtime. Use make build to keep the external frontend directory mode.

One-click deployment without Nginx

Build frontend

cd ./frontend
npm i
npm run build

The homepage shows the current access source as the API base URL by default; if you need to specify another base URL at build time, set VITE_HOMEPAGE_API_BASE_URL before building.

Set .env

CHATAPI_USERNAME=your_username
CHATAPI_PASSWORD=your_password
# Optional; if not provided, the backend will auto-generate and write to the database config table on first start
# CHATAPI_SESSION_SECRET=random_string

CHATAPI_DB_PATH=./data/chatapi.sqlite3
CHATAPI_DATA_DIR=./data

CHATAPI_HOST=0.0.0.0
CHATAPI_PORT=443
CHATAPI_WEB_DIST_DIR=../frontend/dist
CHATAPI_TLS_CERT_FILE=../certs/server.crt
CHATAPI_TLS_KEY_FILE=../certs/server.key

Start Flask

cd ./backend
uv sync
uv run main.py

dev deployment

Start backend

cd ./backend
uv sync
uv run main.py

Start frontend

cd ./frontend
npm i
npm run dev

3. Configure environment variables

First copy the configuration template:

cp .env.example .env

At a minimum, modify the following:

CHATAPI_USERNAME=admin
CHATAPI_PASSWORD=change-me
# Optional; if not provided, the backend will auto-generate and write to the database config table on first start
# CHATAPI_SESSION_SECRET=change-this-session-secret

If deployment configuration is stored outside the project directory, you can set an external env file path:

CHATAPI_ENV_FILE=/path/to/chatapi.env

The external env file uses the same format as .env inside the project; existing process environment variables will not be overwritten by values in the file.

It is recommended to also verify the following configuration:

CHATAPI_DB_PATH=./data/chatapi.sqlite3
CHATAPI_DATA_DIR=./data
CHATAPI_HOST=0.0.0.0
CHATAPI_PORT=5000
CHATAPI_CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173

After logging in, you can enable and save API Key, site title, ntfy address, rate limiting, and TOTP in "System Settings"; these no longer need to be placed in .env.

Optional configuration:

# Let Flask directly host frontend static files (e.g., Vite build dist)
# CHATAPI_WEB_DIST_DIR=./frontend/dist

# Use when Flask directly provides HTTPS
# CHATAPI_TLS_CERT_FILE=./certs/server.crt
# CHATAPI_TLS_KEY_FILE=./certs/server.key

# Optional email sending configuration:
# CHATAPI_EMAIL_FROM=noreply@kirari.fun
# CHATAPI_SMTP_HOST=smtp.example.com
# CHATAPI_RESEND_API_KEY=re_xxxxxxxxx
# CHATAPI_BREVO_API_KEY=YOUR_BREVO_API_KEY
# CHATAPI_TENCENTCLOUD_SECRET_ID=AKIDxxxxxxxxxxxxxxxx
# CHATAPI_TENCENTCLOUD_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# CHATAPI_TENCENTCLOUD_SES_REGION=ap-guangzhou
# A standard SES account also requires a template ID; template data will be dynamically generated by the program.
# CHATAPI_TENCENTCLOUD_TEMPLATE_ID=100091

Deployment on Termux (mobile)

1. Precautions

Note: Make sure your system is normal and you are using [Termux] downloaded from Github or F-Droid, or the domestic packaged version [ZeroTermux]. Ensure the system is 64-bit (Arm64 or aarch64) to guarantee proper operation and deployment. You can check your device architecture with the following command. For better management, you can use a file manager such as [MT Manager]. If you encounter problems, first update the project to the latest version, or ask AI or others. To avoid confusing behavior from Doubao, you can use other AIs (e.g., DeepSeek, Qwen). If you encounter a genuine bug, please report it to the creator.

uname -m

Check the output against the following; it should output aarch64 to meet the requirement.

aarch64: 64-bit ARM (ARMv8-A or higher)
armv7l or armv8l: 32-bit ARM (ARMv7-A or compatible)
x86_64: 64-bit x86 architecture (Intel/AMD)
i686 or i386: 32-bit x86 architecture
riscv64: RISC-V 64-bit architecture

At least Android 5 or higher, preferably Android 12 or higher.

Note: This project is originally designed for computers and has no optimization for mobile, but it can still run on mobile. Also ensure you have updated Termux related files to the latest. Now for preparation, enter the following commands to install some dependencies, etc.

2. Preparation

termux-setup-storage # grant file permissions
termux-change-repo # change mirror source, steps: ok, ↓↓, ok, wait for completion, choose Chinese
pkg update && pkg upgrade -y # update
pkg install -y git wget curl vim binutils clang make pkg-config # install essential dependencies
pkg install -y python python-pip build-essential
pkg install -y libjpeg-turbo libpng freetype harfbuzz libtiff libwebp openjpeg
pip install uv
uname -m # check architecture again
pkg install -y nodejs # install the indispensable thing
node --version && npm --version # verify installation

3. Official deployment

One-click deployment without Nginx

Download project + build frontend

cd ~/
git clone https://github.com/zyf2007/ChatAPI.git # If Github cannot be accessed, see [Other Requirements]
cd ChatAPI
cd frontend
npm i
npm run build

The homepage shows the current access source as the API base URL by default; if you need to specify another base URL at build time, set VITE_HOMEPAGE_API_BASE_URL before building.

4. Configure environment variables

First copy the configuration template:

cd ~/ChatAPI/backend
cp .env.example .env

At a minimum, modify the following:

CHATAPI_USERNAME=admin # username (admin name)
CHATAPI_PASSWORD=change-me # user password (admin password)
# Optional; if not provided, the backend will auto-generate and write to the database config table on first start
# CHATAPI_SESSION_SECRET=change-this-session-secret

If deployment configuration is stored outside the project directory, you can set an external env file path:

CHATAPI_ENV_FILE=/path/to/chatapi.env

The external env file uses the same format as .env inside the project; existing process environment variables will not be overwritten by values in the file.

It is recommended to also verify the following configuration:

CHATAPI_DB_PATH=./data/chatapi.sqlite3
CHATAPI_DATA_DIR=./data
CHATAPI_HOST=0.0.0.0
CHATAPI_PORT=5000
CHATAPI_CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173

After logging in, you can enable and save API Key, site title, ntfy address, rate limiting, and TOTP in "System Settings"; these no longer need to be placed in .env.

Optional configuration:

# Let Flask directly host frontend static files (e.g., Vite build dist)
# CHATAPI_WEB_DIST_DIR=./frontend/dist

# Use when Flask directly provides HTTPS
# CHATAPI_TLS_CERT_FILE=./certs/server.crt
# CHATAPI_TLS_KEY_FILE=./certs/server.key

# Optional email sending configuration:
# CHATAPI_EMAIL_FROM=noreply@kirari.fun
# CHATAPI_SMTP_HOST=smtp.example.com
# CHATAPI_RESEND_API_KEY=re_xxxxxxxxx
# CHATAPI_BREVO_API_KEY=YOUR_BREVO_API_KEY
# CHATAPI_TENCENTCLOUD_SECRET_ID=AKIDxxxxxxxxxxxxxxxx
# CHATAPI_TENCENTCLOUD_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# CHATAPI_TENCENTCLOUD_SES_REGION=ap-guangzhou
# A standard SES account also requires a template ID; template data will be dynamically generated by the program.
# CHATAPI_TENCENTCLOUD_TEMPLATE_ID=100091

5. Start services (both)

Start backend

cd ~/ChatAPI/backend
uv sync
uv run main.py

Start frontend (requires backend)

Since both need to run simultaneously, you need to create a new session. Two sessions will run backend and frontend separately. The frontend provides a web management interface.

cd ~/ChatAPI/frontend
npm i
npm run dev

6. Termux service management solutions

Solution 1: Use tmux to manage multiple sessions (recommended)

Install tmux
pkg install tmux -y
Create backend session
tmux new -s chatapi-backend
cd ~/ChatAPI/backend
uv run main.py

Ctrl+B, D detach session

Create frontend session
tmux new -s chatapi-frontend
cd ~/ChatAPI/frontend
npm run dev -- --host 0.0.0.0

Ctrl+B, D detach session

List running sessions
tmux ls
Reattach to a session
tmux attach -t chatapi-backend

Solution 2: Use nohup to run in background

Backend
cd ~/ChatAPI/backend
nohup uv run main.py > backend.log 2>&1 &
Frontend
cd ~/ChatAPI/frontend
nohup npm run dev -- --host 0.0.0.0 > frontend.log 2>&1 &

Auto-start on boot (requires Termux:Boot add-on)

  1. Install Termux:Boot add-on/[(ZT)Termux:Boot]
  2. Create startup script ~/.termux/boot/start-chatapi.sh:
#!/data/data/com.termux/files/usr/bin/bash
cd ~/ChatAPI/backend
nohup uv run main.py > backend.log 2>&1 &
sleep 3
cd ~/ChatAPI/frontend
nohup npm run dev -- --host 0.0.0.0 > frontend.log 2>&1 &

Grant execute permission:

chmod +x ~/.termux/boot/start-chatapi.sh

7. Public access solutions

Services in Termux usually run on the local area network. For public access, you can use the following intranet penetration tools:

Use cloudflared (Cloudflare Tunnel)
pkg install cloudflared -y
cloudflared tunnel --url http://localhost:5000
Or use ngrok (requires registration for token)
pkg install wget -y
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-arm64.tgz
tar xzf ngrok-v3-stable-linux-arm64.tgz
./ngrok config add-authtoken YOUR_TOKEN
./ngrok http 5000

8. Security enhancement recommendations

8.1 Account security policies

  1. Change the default admin password: Modify CHATAPI_PASSWORD immediately after deployment, avoid weak passwords.

  2. Enable TOTP two-factor authentication: Enable TOTP in the web console's "System Settings", use with Google Authenticator or other authenticators. The TOTP secret should be stored securely in the database.

  3. Enable API Key authentication: Enable Bearer Token authentication for API calls; calls must carry the Authorization: Bearer <api_key> header.

  4. Enable rate limiting: Configure request rate limiting in system settings to prevent abuse.

8.2 Network security configuration

  1. Use HTTPS in production: Strongly recommended to use Nginx reverse proxy + Let's Encrypt free certificate

  2. Restrict CORS origins: Only allow necessary domains, avoid using wildcards

  3. Configure firewall: In Termux you can use iptables or nftables to restrict access source IPs

8.3 Sensitive information management

  1. After login, enable and save API Key, site title, ntfy address, and TOTP in the web console; these configurations should not be placed in the .env file

  2. If SESSION_SECRET is not provided, the backend will auto-generate it on first start and write it to the database config table

Message Push URL Security Settings

ChatAPI supports sending message notifications via ntfy. Users can enter an ntfy push URL in "My Settings".

Q: When do I need to modify the "Message Push URL"?

In most cases, leaving it as the default "Disabled" is sufficient. Only enable it when you self-host ntfy on the same machine, same internal network, or a private network as ChatAPI, for example: http://127.0.0.1:8080/topic or http://192.168.1.10:8080/topic.

If you use the official https://ntfy.sh/your-topic, or a self‑hosted ntfy with a public domain name (e.g., https://ntfy.example.com/topic), you do not need to change this setting.

Meaning of the three options:

  • Disabled: No user may fill in a local or intranet push URL.
  • Admin only: Only the administrator may fill in a local or intranet push URL.
  • All users: Any logged‑in user may fill in a local or intranet push URL.

It is recommended to use "Admin only" first, and only select "All users" if you fully trust every user. The default is disabled to prevent SSRF risks where users could force the server to access 127.0.0.1, localhost, internal IP addresses, or cloud metadata addresses via the push URL.

Termux common troubleshooting

Q1: Database is locked error

Cause: SQLite may encounter lock conflicts under high concurrency writes.

Solutions:

  1. Enable WAL mode (?journal_mode=WAL)

  2. Use connection pooling to limit concurrent connections

  3. Wrap busy write operations in transactions

Q2: Session Secret related error

Cause: CHATAPI_SESSION_SECRET not set in .env.

Solution: Leave it blank; the backend will auto-generate on first start and write to the database config table. If you need to specify manually, use a high-entropy random string.

Q3: Email sending failure

Check items:

  1. SMTP server address and port are correct

  2. SMTP authentication is enabled (some providers require it)

  3. The sender email has been verified

  4. When using third-party APIs (e.g., Resend, Tencent Cloud SES), the API key is valid and has correct permissions. Resend suggests setting permissions to "only send" to reduce leakage risk.

Q4: Node.js frontend build fails in Termux

Solutions:

  1. Increase swap space: dd if=/dev/zero of=$PREFIX/swapfile bs=1M count=1024 && chmod 600 $PREFIX/swapfile && mkswap $PREFIX/swapfile && swapon $PREFIX/swapfile

  2. Ensure sufficient memory before running npm run build (1GB+ available RAM recommended)

Download via Github

Defaults to the latest version; if your device is not supported, please find an adapted version yourself. [ZeroTermux‖0.118.3.58‖all architectures]

[Termux‖V0.119.0-beta3‖all architectures]

Download via download site

Defaults to the latest version; if your device is not supported, please find an adapted version yourself. Use download site: [gh-proxy], Cloudflare

Termux

[Termux‖V0.119.0-beta3‖all architectures] Main site acceleration, global high-speed distribution

[Termux‖V0.119.0-beta3‖all architectures] Preferred acceleration server, IPv4 only, smart DNS resolution

[Termux‖V0.119.0-beta3‖all architectures] Preferred acceleration server, supports IPv6/IPv4 smart DNS resolution

ZeroTermux

[ZeroTermux‖0.118.3.58‖all architectures] Main site acceleration, global high-speed distribution

[ZeroTermux‖0.118.3.58‖all architectures] Preferred acceleration server, IPv4 only, smart DNS resolution

[ZeroTermux‖0.118.3.58‖all architectures] Preferred acceleration server, supports IPv6/IPv4 smart DNS resolution

Other requirements

Domestic software uses domestic channels; for Github, use the [download site]. Defaults to the latest version; if your device is not supported, please find an adapted version yourself.

Clone this project (download site)

Main site acceleration, global high-speed distribution
git clone https://gh-proxy.org/https://github.com/zyf2007/ChatAPI.git
Preferred acceleration server, IPv4 only, smart DNS resolution
git clone https://v4.gh-proxy.org/https://github.com/zyf2007/ChatAPI.git
Preferred acceleration server, supports IPv6/IPv4 smart DNS resolution
git clone https://v6.gh-proxy.org/https://github.com/zyf2007/ChatAPI.git

MT Manager

[MT Manager]

MT Manager alternative [NP Manager]

[NP Manager]

Nginx reverse proxy example

The following example assumes:

  • Frontend static file directory: /path/to/ChatAPI/frontend/dist
  • Backend address: http://127.0.0.1:5000
  • Domain name: chat.example.com
server {
    listen 80;
    server_name chat.example.com;

    root /path/to/ChatAPI/frontend/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:5000/api/;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /v1/ {
        proxy_pass http://127.0.0.1:5000/v1/;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

If you want to enable HTTPS, it is recommended that Nginx handles the certificate rather than using Flask's built-in server.

If you do not want to deploy Nginx additionally, you can also let Flask directly serve both the API and frontend static files:

CHATAPI_WEB_DIST_DIR=./frontend/dist

After setting:

  • /api/* and /v1/* continue to go to the backend interface
  • Other paths will return static files directly from that directory
  • When the requested path does not exist and the directory contains index.html, it will automatically fall back to index.html, which can be used for frontend single-page application routing

Call examples:

curl https://127.0.0.1:5000/v1/responses \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer sk-i-love-you-hutao' \
  -d '{
    "model": "胡桃酱",
    "input": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "Type here to talk directly with Hu Tao!"
          }
        ]
      }
    ],
    "stream": true
  }'

Anthropic Messages compatible interface uses /messages, for example:

curl https://127.0.0.1:5000/messages \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer sk-i-love-you-hutao' \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": "Hello"
      }
    ],
    "stream": true
  }'