f17a6ccbac
- Make AI routing rules DB-driven (read from system_configs, removed from config.py) - Add translation quota tracking to LLM translation (OpenAIProvider) - Add Alibaba MT ECS RAM role support (STS token, no AccessKey needed) - Fix admin sidebar link for AI模型配置 page - Fix Quota.vue API path (quotas → translation-quotas) - Fix login auto-redirect to dashboard - Add provider dropdown selects to AI routing config UI - Clean up stale ai_provider_* system_configs records - Remove OpencodeGo, Spark providers (code + DB) - Update deploy config: nginx port 8000, systemd cwd
8.1 KiB
8.1 KiB
TradeMate (外贸小助手) — Agent Guide
AI Assistant (Frontend AI Chatbot)
- Components:
user-frontend/src/components/AiAssistant.vue+admin-frontend/src/components/AiAssistant.vue - Backend:
backend/app/api/v1/ai_assistant.py—POST /api/v1/ai/chat,GET /api/v1/ai/quick-questions - Action types (configurable via
ACTION_INSTRUCTIONS): create_customer, create_product, create_quotation, scan_followups, generate_marketing, discovery_search, navigate, search_users, update_user, update_config, review_certification, process_invoice - Frontend action dispatch:
AiAssistant.vueswitch/case calls corresponding API from@/api - Layout integration:
<AiAssistant />inUserLayout.vue+AdminLayout.vue, floating button bottom-right - Quick questions: configurable via
ai_assistant_quick_questionsSystemConfigkey - System prompt: configurable via
ai_assistant_promptSystemConfigkey
Architecture
- Backend:
backend/— FastAPI + SQLAlchemy 1.4 async + asyncpg, singleapp.main:app - Frontends:
uni-app/(mobile H5/mini-program),admin-frontend/(PC admin),user-frontend/(PC workspace) - Config:
backend/app/config.pyreads from/.env(project root) via pydantic BaseSettings - Auth: JWT (python-jose). Default dep
get_current_user_idinbackend/app/api/v1/deps.py - AI Router:
backend/app/ai/router.py— singletonAIRouter, DB-driven providers + DB-driven routing rules. Routing readsai_routingfromsystem_configstable. - Database: PostgreSQL via
asyncpg, pool_size=20
AI Providers
- Active: Sensenova (商汤), NVIDIA, 阿里机器翻译 (alibaba-mt) — 5 providers in DB
- Removed: Claude, DeepL, Local, OpencodeGo, 讯飞 Spark — all git rm'd
- DB-driven:
AIProvidermodel +admin_ai.pyAPI — manage providers at runtime.router.seed_from_env()loads from.envon startup - ECS RAM role: 阿里翻译使用 ECS 实例 RAM 角色
trademate-translate获取 STS 临时凭证 - Provider type mapping in
router.py._build_provider(): sensenova, nvidia, alibaba-mt
Security
- CORS:
middleware.py— whitelist origins, restricted methods/headers - Rate Limit: endpoint-specific — login 5/min, register 3/h, password 3/5min, payment 20/min, admin 30/min
- CSRF:
core/csrf.py— double-submit cookie pattern. Required on auth/payment/profile. Webhooks skipped. - Login: JSON
LoginRequestmodel, notOAuth2PasswordRequestForm
Customer Discovery
discovery.py+discovery_record.py— Google Custom Search integration- Contact extraction from company websites (email/phone/WhatsApp/WeChat)
Dev Commands
# Backend (from project root — .env is there)
# Dev: matches Vite proxy (both frontends proxy /api → localhost:8000)
cd backend && source venv/bin/activate && uvicorn app.main:app --reload --port 8000
# Production: nginx proxies /api/ → localhost:8002
cd backend && source venv/bin/activate && uvicorn app.main:app --port 8002
# Mobile H5
cd uni-app && npm run dev:h5
# Admin frontend (PC management)
cd admin-frontend && npm run dev # port 5173, base: /admin/
# User workspace (PC workbench)
cd user-frontend && npm run dev # port 5174, base: /workspace/
# Tests (backend — needs PostgreSQL running with foreign_trade_test DB)
cd backend && venv/bin/pytest # all
venv/bin/pytest tests/test_auth_api.py # single file
venv/bin/pytest tests/ -k "test_login" # keyword filter
# Builds
cd uni-app && npm run build:h5 # uni-app (mobile H5)
cd admin-frontend && npm run build # admin => /www/wwwroot/trade.yuzhiran.com/admin/
cd user-frontend && npm run build # workspace => /www/wwwroot/trade.yuzhiran.com/workspace/
# Alembic migrations
cd backend && alembic upgrade head
alembic revision --autogenerate -m "desc"
Deployment
- Landing page:
trade.yuzhiran.com/— static marketing HTML - SPA:
trade.yuzhiran.com/app/— uni-app build (mobile) - Admin:
trade.yuzhiran.com/admin/— Vue 3 + Element Plus (standalone) - Workspace:
trade.yuzhiran.com/workspace/— Vue 3 + Element Plus (standalone) - Nginx: SPA fallbacks for
/app/,/admin/,/workspace/ - vite config: each project has its own
basepath and dev port - API: proxied via nginx
location /api/to127.0.0.1:8000
Critical Quirks
- Route ordering: FastAPI matches top-down. Specific routes (
/{customer_id}/health) must be registered before wildcard/{customer_id}. - AI
extract_info: Some models (e.g. deepseek-v4-flash) don't supportresponse_format={"type": "json_object"}.openai.pycatches the failure and retries without it. - Manual auth on some endpoints:
keywordsandcompetitor-analysisendpoints useauthorization: str = Header(None)instead ofDepends(get_current_user_id). - MarketingService fallback: When no AI providers initialized, returns template content instead of crashing.
- Onboarding service: calls
mkt.generate(product_info={"name": ..., ...}), not keyword args. Checkonboarding.pyfor the exact dict shape. - CustomerHealthService:
get_health_overviewendpoint must useCustomerHealthService(db)notCustomerService(db). - CSRF: Sensitive endpoints (auth/payment/profile) require
X-CSRF-Tokenheader. Token available viacsrf_tokencookie /X-CSRF-Tokenresponse header. - AI Router reload: After modifying AI providers via admin API, call
POST /api/v1/admin/ai/reloadto refresh in-memory providers. - Payment: Uses unified
pay-apigateway (UnifiedPayService). NOT direct WeChat/Alipay integration. Credentials:PAY_API_KEY/PAY_API_SECRETfrom.env. HMAC-SHA256 auth. Webhook atPOST /api/v1/payment/webhookskips CSRF. - Payment gateway config:
PAY_API_KEY,PAY_API_SECRET,PAY_API_BASE_URL,PAY_WEBHOOK_URLinconfig.py.pay_typeparam:"alipay"(returnspay_url) or"wechat"(returnscode_url).UnifiedPayServicenormalizes legacynative/jsapi/pctowechat/alipay. - Manual auth on some endpoints:
keywordsandcompetitor-analysisendpoints useauthorization: str = Header(None)instead ofDepends(get_current_user_id). - MarketingService fallback: When no AI providers initialized, returns template content instead of crashing.
- Onboarding service: calls
mkt.generate(product_info={"name": ..., ...}), not keyword args. Checkonboarding.pyfor the exact dict shape. - CustomerHealthService:
get_health_overviewendpoint must useCustomerHealthService(db)notCustomerService(db). - CSRF: Sensitive endpoints (auth/payment/profile) require
X-CSRF-Tokenheader. Token available viacsrf_tokencookie /X-CSRF-Tokenresponse header. - AI Router reload: After modifying AI providers via admin API, call
POST /api/v1/admin/ai/reloadto refresh in-memory providers. - Payment: Uses unified
pay-apigateway (UnifiedPayService). NOT direct WeChat/Alipay integration. Credentials:PAY_API_KEY/PAY_API_SECRETfrom.env. HMAC-SHA256 auth. Webhook atPOST /api/v1/payment/webhookskips CSRF. - Payment gateway config:
PAY_API_KEY,PAY_API_SECRET,PAY_API_BASE_URL,PAY_WEBHOOK_URLinconfig.py.pay_typeparam:"alipay"(returnspay_url) or"wechat"(returnscode_url).UnifiedPayServicenormalizes legacynative/jsapi/pctowechat/alipay.
Project Conventions
- No README.md — key context is in
PROGRESS.mdanddocs/ - Chinese UI — mobile-first, for foreign-trade SOHOs/small teams
- No comments in code unless explicitly asked
- Commit messages focus on "why" not "what", in English
- Services instantiate
MarketingService()(no db needed). For customer health:CustomerHealthService(db) - AI providers in
backend/app/ai/providers/— inherit fromOpenAIProviderif compatible with OpenAI API format - Static assets go in
uni-app/src/static/ - Test DB:
foreign_trade_test(uses credentials fromconftest.py, not.env)
Remember
- Write tests for new features
- Run
cd backend && venv/bin/pytestbefore committing - Keep context compact — avoid bloating the session with unnecessary file reads