# External Integrations

**Analysis Date:** 2026-05-07

## APIs & External Services

**AI & Language Models:**
- Kimi (OpenAI-compatible) - LLM for multi-turn AI conversations
  - SDK: `openai` Python package (in `requirements.txt`)
  - Implementation: `aiapp/kimi.py` (lines 1-29)
  - Config: `KIMI_API_KEY`, `KIMI_BASE_URL` (set at `qy_lty/settings.py:349-350`, loaded from `.env`)
  - Purpose: Single/multi-turn chat with users via POST `/api/ai/chat/` and `/api/ai/multi-chat/`

**Real-Time Communications (RTC):**
- Volcengine (ByteDance) - RTC service for voice/video calls
  - SDK: Custom token generation in `common/VolcEngineAccessToken.py` (lines 1-204), HTTP API calls in `device_interaction/volcengine_api.py`
  - Config: `VOLCENGINE_ACCESS_KEY`, `VOLCENGINE_SECRET_KEY`, `VOLCENGINE_APP_ID`, `VOLCENGINE_APP_KEY` (at `qy_lty/settings.py:241-243`)
  - Purpose: Generate RTC tokens for device-to-device or device-to-app real-time communication
  - Endpoint: `POST /api/device/rtc-token/get_by_mac/?mac_address=...` (no auth required, returns RTC token for device's bound user)
  - Room structure: `room_id = f"room_{user_id}"` (shared with WebSocket group `device_{user_id}`)

**Audio/Speech Services (Multi-Provider):**
- Configured via `AUDIO_SERVICE_PROVIDER` setting (default: `'huoshan'`) at `qy_lty/settings.py:415`

  **Aliyun NLS (Natural Language Service):**
  - SDK: `aliyun-python-sdk-core` + custom integration
  - Implementation: `aiapp/audio/AliyunAudioService.py`
  - Config keys: `ALIYUN_NLS_ACCESS_KEY_ID`, `ALIYUN_NLS_ACCESS_KEY_SECRET`, `ALIYUN_NLS_APP_ID` (in `qy_lty/settings.py:419-421`)
  - Purpose: Speech synthesis (text→voice) and recognition (voice→text)
  - Storage: Audio uploaded to Aliyun OSS (see OSS section)

  **Tencent Audio:**
  - Implementation: `aiapp/audio/TencentAudioService.py`
  - Config keys: `AUDIO_SERVICE_TENCENT_API_KEY`, `AUDIO_SERVICE_TENCENT_API_SECRET` (at `qy_lty/settings.py:430-431`)
  - Purpose: Text-to-speech and speech-to-text via Tencent APIs

  **Volcengine/Huoshan (ByteDance):**
  - Implementation: `aiapp/audio/HuoshanAudioService.py`, `aiapp/audio/HuoshanAudioService_new.py`
  - Config keys: `AUDIO_SERVICE_HUOSHAN_APPID`, `AUDIO_SERVICE_HUOSHAN_ACCESS_TOKEN`, `AUDIO_SERVICE_HUOSHAN_CLUSTER`, `AUDIO_SERVICE_HUOSHAN_VOICE_TYPE`, `AUDIO_SERVICE_HUOSHAN_STORAGE_DIR`, `AUDIO_SERVICE_HUOSHAN_BASE_URL` (at `qy_lty/settings.py:434-439`)
  - Purpose: TTS (text→speech) and ASR (speech→text) with local storage fallback
  - Also includes nested Aliyun ASR config (lines 440-451) as fallback

  **Audio Service Factory:**
  - Entry point: `aiapp/audio/AudioService.py:get_audio_service()` (lines 8-19)
  - Base class: `aiapp/audio/BaseAudioService.py` (abstract interface at lines 1-35)
  - Used by: `aiapp/views.py` (ChatBotAPIView, MultiChatAPIView) and tests

## Data Storage

**Databases:**
- **PostgreSQL** (Primary)
  - Connection: `POSTGRESQL_DATABASE_*` env vars (configured at `qy_lty/settings.py:166-172`)
  - Client: psycopg2-binary
  - Contains: User models, AI conversations, device bindings, card data, achievement records, subscription info

- **Redis** (Cache + Message Queue)
  - Connection: `REDIS_LOCATION`, `REDIS_PASSWORD` (configured at `qy_lty/settings.py:252-260`)
  - Client: django-redis
  - Purpose: Token storage (key format: `token:{token}` or `admin_token:{token}` with 30-day TTL, see `CLAUDE.md` line 122), channel layer for WebSocket, caching
  - Channel layer config: `CHANNEL_LAYERS.default.BACKEND = 'channels_redis.core.RedisChannelLayer'` (at `qy_lty/settings.py:504-511`)

**File Storage:**
- **Aliyun OSS (Object Storage Service)** - Production storage for audio, images, documents
  - SDK: `oss2` Python package (in `requirements.txt`)
  - Implementation: `common/oss.py` (OSSUploader class at lines 1-90)
  - Config: `AUDIO_SERVICE_CONFIG['aliyun']` with `oss_key_id`, `oss_key_secret`, `oss_bucket`, `oss_endpoint`, `oss_host` (at `qy_lty/settings.py:422-427`)
  - Used by: Audio service, image processing endpoints, media uploads
  - Path pattern: `{base_dir}/[permanent|temporary]/{YYYYMMDD}/{filename}`
  - Dev fallback: Local filesystem storage at `MEDIA_ROOT` (`qy_lty/settings.py:238`)

**Caching:**
- Redis (see above)
- TTL for RTC tokens: `rtc_room:{user_id}:{task_id}` (see `CLAUDE.md` line 172)
- Device last-seen cache: `device:last_seen:{mac}` with 5-min TTL (see `CLAUDE.md` line 230)

## Authentication & Identity

**Auth Provider:**
- Custom Redis-backed token authentication + django-allauth social auth

  **Custom Token Auth:**
  - Implementation: `userapp/authentication.RedisTokenAuthentication` (at `userapp/authentication.py:10-34`)
  - Storage: Redis with keys `token:{token}` (users) and `admin_token:{token}` (admins)
  - TTL: 30 days
  - Used for: API requests via `Authorization: Bearer {token}` header
  - Generated by: `userapp/utils.py:generate_token()` (referenced in `CLAUDE.md` line 122)

  **WeChat Social Auth:**
  - Provider: django-allauth with Weixin provider (configured at `qy_lty/settings.py:56`)
  - Backend: `allauth.account.auth_backends.AuthenticationBackend` (at `qy_lty/settings.py:324`)

  **WebSocket Auth:**
  - Custom middleware: `device_interaction/auth.TokenAuthMiddleware` (lines 1-50)
  - Reuses `RedisTokenAuthentication` logic with mock request adapter
  - Routes: `ws://domain/ws/device/` (Header auth) and `ws://domain/ws/device/token/{token}/` (URL auth)
  - Group model: Messages routed to `device_{user_id}` (same user controls device and app)

  **Device MAC Login:**
  - Endpoint: `POST /api/user/mac-login/` (referenced in `CLAUDE.md` line 125)
  - Returns: User-token for device's bound user (latest binding via `order_by('-bound_at').first()`)
  - Model: `UserDevice` relationship with `bound_at` ordering

## Monitoring & Observability

**Error Tracking:**
- No dedicated external error tracking (Sentry, etc.) detected

**Logs:**
- **Aliyun Log Service** - Production logging integration
  - SDK: `aliyun-log-python-sdk` (in `requirements.txt`)
  - Implementation: `common/aliyun_logging.py` (AliyunLogHandler at lines 16-36, setup_logging() at lines 32-36)
  - Config: `ALIYUN_LOG_PROJECT`, `ALIYUN_LOG_STORE`, `ALIYUN_LOG_ENDPOINT`, `ALIYUN_LOG_ACCESS_KEY_ID`, `ALIYUN_LOG_ACCESS_KEY_SECRET` (env vars, loaded at lines 7-11)
  - Logging config: `qy_lty/settings.py:372-411` configures handlers for `django`, `django.request`, `aiapp`, `common`, `userapp` loggers
  - Log levels: INFO for production, DEBUG for console in dev

## CI/CD & Deployment

**Hosting:**
- Docker containers (self-managed or cloud-hosted)
- Image base: Python 3.8 via docker.m.daocloud.io (China mirror)

**CI Pipeline:**
- No dedicated CI/CD service detected in code (GitHub Actions, GitLab CI, etc. config not present)

**Deployment:**
- Docker Compose for local/staging (docker-compose.yml:1-33)
- Production via Docker Compose or Kubernetes (see Dockerfile for structure)
- Port exposure: 12012 (maps to ASGI 8000)

## Environment Configuration

**Required env vars (from settings.py and CLAUDE.md):**
- `SECRET_KEY` - Django secret
- `DEBUG` - Debug mode
- `POSTGRESQL_DATABASE_NAME`, `POSTGRESQL_DATABASE_USER`, `POSTGRESQL_DATABASE_PASSWORD`, `POSTGRESQL_DATABASE_HOST`, `POSTGRESQL_DATABASE_PORT`
- `REDIS_LOCATION`, `REDIS_PASSWORD`
- `KIMI_API_KEY`, `KIMI_BASE_URL` (default: https://api.moonshot.cn/v1)
- `ALIYUN_SMS_ACCESS_KEY_ID`, `ALIYUN_SMS_ACCESS_KEY_SECRET`, `ALIYUN_SMS_SIGN_NAME`, `ALIYUN_SMS_TEMPLATE_CODE`
- `ALIYUN_NLS_ACCESS_KEY_ID`, `ALIYUN_NLS_ACCESS_KEY_SECRET`, `ALIYUN_NLS_APP_ID`
- `ALIYUN_OSS_ACCESS_KEY_ID`, `ALIYUN_OSS_ACCESS_KEY_SECRET`, `ALIYUN_OSS_BUCKET`, `ALIYUN_OSS_ENDPOINT`, `ALIYUN_OSS_HOST`, `ALIYUN_OSS_AUDIO_BASE_DIR`
- `ALIYUN_VI_ACCESS_KEY_ID`, `ALIYUN_VI_ACCESS_KEY_SECRET`, `ALIYUN_VI_ENDPOINT`, `ALIYUN_VI_REGION`
- `ALIYUN_LOG_PROJECT`, `ALIYUN_LOG_STORE`, `ALIYUN_LOG_ENDPOINT`, `ALIYUN_LOG_ACCESS_KEY_ID`, `ALIYUN_LOG_ACCESS_KEY_SECRET`
- `VOLCENGINE_ACCESS_KEY`, `VOLCENGINE_SECRET_KEY`, `VOLCENGINE_APP_ID`, `VOLCENGINE_APP_KEY`
- `AUDIO_SERVICE_PROVIDER` (values: 'aliyun', 'tencent', 'huoshan'; default: 'huoshan')
- `AUDIO_SERVICE_HUOSHAN_APPID`, `AUDIO_SERVICE_HUOSHAN_ACCESS_TOKEN`, `AUDIO_SERVICE_HUOSHAN_CLUSTER`, `AUDIO_SERVICE_HUOSHAN_VOICE_TYPE`, `AUDIO_SERVICE_HUOSHAN_STORAGE_DIR`, `AUDIO_SERVICE_HUOSHAN_BASE_URL`
- `AUDIO_SERVICE_TENCENT_API_KEY`, `AUDIO_SERVICE_TENCENT_API_SECRET` (if provider='tencent')

**Secrets location:**
- `.env` file (git-ignored, copy from `.env.bak` template during setup per `CLAUDE.md` line 44)

## Webhooks & Callbacks

**Incoming:**
- WebSocket device messages routed to `device_{user_id}` group (see `CLAUDE.md` line 118)
- Volcengine RTC conversation callbacks: `conversation_status`, `conversation_subtitle` message types forwarded via WebSocket (see `CLAUDE.md` line 167)
- Device heartbeat: `device:last_seen:{mac}` refreshed on message receipt (see `CLAUDE.md` line 230)

**Outgoing:**
- No outbound webhooks detected (integrations are request/response based)

## API Documentation

**Documentation Endpoints:**
- Swagger UI: `http://localhost:8000/swagger/`
- ReDoc: `http://localhost:8000/redoc/`
- Generated by: drf-yasg (configured at `qy_lty/settings.py:513-549`)

**Main API Routes:**
- `/api/user/` - User auth & management (MAC login, token generation)
- `/api/ai/` - AI chat (single-turn, multi-turn, voice synthesis/recognition)
- `/api/device/` - Device interaction, RTC tokens, binding status
- `/api/card/` - Card system (batch generation, QR codes, usage tracking)
- `/api/achievement/` - Achievement tracking
- `/api/v1/admin/` - Admin operations
- `/ws/device/` - WebSocket for real-time device communication

---

*Integration audit: 2026-05-07*
