2026-10-16 09:00:40 +07:00

AI Platform

AI Platform provides Lead Scoring with a Python backend and internal SvelteKit Admin Web. Behavior is in docs/specs/ai-platform-lead-scoring.md and the client contract in contracts/lead-scoring/; local checks do not establish client integration or production readiness.

Runtime layout

  • Python 3.13 backend package: src/ai_platform, served as ai_platform.main:app.
  • PostgreSQL 16 with a new, project-specific Compose volume named ai_platform_pgdata.
  • Alembic schema changes are applied as a one-shot Compose service before the backend starts.
  • SvelteKit is a separate web image under apps/web.
  • Historical implementation is retained in Git history, not as a separate source tree.

The local Compose stack runs one backend process. It is for development only; default credentials and loopback port mappings are not deployment settings. Keep production secrets outside .env and inject them through the deployment environment or a secrets manager.

Local setup

Copy the backend/Compose template and the separate SvelteKit server-only template only when setting up a new workspace. Both .env files are ignored by Git; preserve any existing .env and apps/web/.env instead of overwriting them.

cp .env.example .env
cp apps/web/.env.example apps/web/.env
make install

For a new database, prepare its schema once before starting the application:

make db-up
make migrate

Then start PostgreSQL and both native servers from one terminal:

make dev

Set BACKEND_PORT once in the root .env (default 8000; use 8002 to avoid a local conflict). make backend-dev uses that port, and make web-dev passes the matching server-only BACKEND_INTERNAL_URL to Web, overriding any old URL in apps/web/.env. An exported BACKEND_PORT or make dev BACKEND_PORT=8002 can override the root value. Other root secrets are not passed to Web. The web development server normally listens at 127.0.0.1:5173 (see its terminal output). Ctrl+C stops the native servers; PostgreSQL stays running. make dev does not run migrations or start Omni/AIHub. To run the servers in separate terminals instead, use make backend-dev and make web-dev.

The local web server should call the backend through server-only configuration. Do not expose BACKEND_INTERNAL_URL, database credentials, or provider keys as browser-visible PUBLIC_* variables.

Compose can instead build and start all services, including the one-shot migration step:

docker compose up --build

The database is reachable from the host at 127.0.0.1:55432, backend at 127.0.0.1:8000, and web at 127.0.0.1:3000 by default. To discard this Compose stack's database and its data, run docker compose down -v; unrelated project volumes are not targeted.

The local database starts with only the development database. To run tests safely, create a separate database in that same new PostgreSQL instance, then pass its URL explicitly:

docker compose exec postgres createdb -U ai_platform ai_platform_test
AI_PLATFORM_DATABASE_URL=postgresql+asyncpg://ai_platform:local-change-this-password@127.0.0.1:55432/ai_platform_test make test

make test rejects a database URL that does not contain ai_platform_test. CI provisions its own isolated PostgreSQL 16 test database.

Chấm điểm AI qua CLIProxy khi phát triển local

Không cần chạy AIHub để thử adapter OpenAI-compatible. Cấu hình URL trên backend (trong môi trường hoặc .env local đã có):

AI_PLATFORM_ENVIRONMENT=development
AI_PLATFORM_OPENAI_BASE_URL=http://127.0.0.1:8317
# AI_PLATFORM_OPENAI_API_KEY=...  # chỉ cần nếu CLIProxy yêu cầu xác thực

Chạy make backend-dev trên máy host: 127.0.0.1:8317 bên trong Docker không trỏ tới CLIProxy trên host. Trong Admin Web (Cấu hình AI), soạn một revision mới với OpenAI-compatible, URL http://127.0.0.1:8317, model gemini-3.5-flash-lite, hướng dẫn chấm và timeout, chạy thử rồi Kích hoạt. AI_PLATFORM_OPENAI_API_KEY chỉ được gửi tới AI_PLATFORM_OPENAI_BASE_URL; URL khác nhập trên Web không nhận key đó. Profile AIHub dùng khóa AI của client trong header X-AI-Key (không lưu).

Trang “Thử chấm điểm” có form sửa lead/custom fields, thêm/sửa/xóa hội thoại và tin nhắn (thời gian UTC), dựng rule với field/operator/giá trị/điểm và chọn tỷ lệ AI. Trọng số quy tắc tự bổ sung để tổng bằng 100%; AI 0% không gọi model. JSON nâng cao đồng bộ cùng kịch bản và gửi nguyên trọng số. Kết quả hiện điểm, breakdown và fallback ngay trên trang, kèm liên kết chi tiết. Ngưỡng ở đây là điều kiện rule; phân loại lead vẫn do client quyết định. Kịch bản không lưu thành chính sách và không ghi đè fixture chuẩn. Với AIHub, nhập “Khóa AI cho lần thử (không lưu)” trên trang này, hoặc đặt LEAD_SCORING_FIXTURE_AI_KEY trên server Web. Khóa nhập được ưu tiên, chỉ chuyển trong header X-AI-Key khi AI > 0%, không nằm trong JSON/kết quả và xóa khỏi ô nhập khi gửi. Khóa dùng thử ở trang Cấu hình AI không được lưu hay chuyển sang trang này. Thiếu khóa sẽ fallback bằng điểm quy tắc. Chế độ AI có thể phát sinh chi phí.

Với endpoint OpenAI-compatible chạy ở production, URL phải dùng HTTPS. Key được cấu hình trên server chỉ gửi tới URL được gắn với key đó; thay URL trên Web không tự chuyển key. Không đặt key vào Web hoặc file versioned. CLIProxy local chỉ xác minh được đường gọi thử; chưa chứng minh các điều kiện phát hành production.

App credentials

Mỗi installation/môi trường Omni dùng một app_id ổn định (tên đăng ký phía AI Platform, Omni không cần biết hay gửi) và một backend app key chung cho các account. Vận hành cấp/rotate/revoke qua CLI; raw key chỉ được xuất khi cấp/rotate, chuyển an toàn sang backend Omni, không qua browser/log/Git:

uv run --no-sync ai-platform create-app omni-local
uv run --no-sync ai-platform rotate-app-key omni-local
uv run --no-sync ai-platform revoke-app-key omni-local

Admin Web /platform/apps chỉ xem trạng thái và thu hồi, không hiển thị hay cấp/rotate key. POST /v1/lead-scoring/score đồng bộ, dùng Authorization: Bearer <app_api_key>, Idempotency-Key (UUID) và tùy chọn X-AI-Key. Dữ liệu riêng của client đi trong metadata và được lưu nguyên. Omni chỉ dùng AI_PLATFORM_URL và AI_PLATFORM_APP_API_KEY ở backend. Không có webhook hay đăng ký account ở AI Platform.

Generated OpenAPI và các fixture tại contracts/lead-scoring/; chạy make contract để tái sinh và uv run --no-sync python scripts/export_contract_fixtures.py --check để kiểm tra drift fixture mà không sửa file. Provider checks chưa chứng minh tích hợp Omni/EMS.

Schema chưa phát hành hiện có một migration 0001_initial, tạo thẳng app credentials, admin, AI profiles, runs. Database mới chạy make migrate. Database local còn revision cũ không tự upgrade sang baseline: dùng database mới, hoặc xác nhận phạm vi dữ liệu cần giữ/bỏ trước khi dựng lại hay stamp sau kiểm tra schema; không chạy alembic stamp head để che schema khác biệt. Startup vẫn kiểm tra revision và không tự migrate. Lịch sử migrations sau lần phát hành đầu tiên phải được giữ.

Fixture runner nội bộ dùng LEAD_SCORING_FIXTURE_APP_API_KEY server-only.

Backup và app/account offboarding cần chính sách riêng trước production.

Quality checks

The opt-in pre-commit runner is installed by make install as a project-local development dependency. Run:

make check-fast
make check

make check-fast runs the pinned Ruff and pre-commit-hooks rules. make check additionally runs Python type/import checks and tests; tests must use a separate test database, never a developer or production database. CI uses the same fast hooks and the Makefile test/check commands with an isolated PostgreSQL 16 service.

Operations notes

  • Apply migrations as a release step; application startup must not migrate the database.
  • /health/live is liveness; /health/ready checks readiness and PostgreSQL. The Compose backend health check waits for readiness.
  • Avoid logging credentials, request payloads containing personal data, or provider responses with sensitive content.
  • The Compose PostgreSQL volume is disposable development data. Backup, restore, retention, secrets, TLS, and alerting must be defined for the eventual deployment target.

The web container currently assumes package.json, bun.lock, a production SvelteKit build at build/index.js, and Bun compatibility with the selected SvelteKit adapter. Confirm those assumptions with the web implementation before treating the image as verified.

Description
No description provided
Readme 1.3 MiB
Languages
Python 46.5%
Svelte 37.1%
TypeScript 14.5%
Makefile 0.8%
CSS 0.7%
Other 0.3%