fix: bound AI analysis provider latency

This commit is contained in:
2026-07-09 01:11:29 -07:00
parent a8776f9d79
commit 153c501cf7
6 changed files with 173 additions and 7 deletions

View File

@@ -223,6 +223,76 @@ async function classifyOrder(orderData: OrderData) {
| Invalid API key | Missing/wrong credentials | Check environment variables |
| Schema validation failed | AI output doesn't match schema | Adjust schema or prompt |
## Scenario: Elder AI analysis latency controls
### 1. Scope / Trigger
- Trigger: backend elder AI analysis calls an OpenAI-compatible chat model through LangChain and returns a fixed API response to the UI.
- Apply this contract whenever changing `modules/ai/server/config.ts`, `modules/ai/server/analysis.ts`, or any elder AI analysis route that can block on a provider call.
### 2. Signatures
- Runtime config: `getAiRuntimeConfig() -> { success: true, config } | { success: false, reason }`.
- Config fields: `baseUrl`, `apiKey`, `chatModel`, `requestTimeoutMs`, `maxTokens`, `maxRetries`.
- Generation service: `generateElderAiAnalysis(context, elderId) -> ServiceResult<{ analysis }>`.
### 3. Contracts
- Environment keys:
- `AI_API_KEY`: required.
- `AI_BASE_URL`: optional OpenAI-compatible base URL.
- `AI_CHAT_MODEL`: optional model name.
- `AI_REQUEST_TIMEOUT_MS`: optional bounded integer request timeout.
- `AI_MAX_TOKENS`: optional bounded integer generation cap.
- `AI_MAX_RETRIES`: optional bounded integer retry count.
- `ChatOpenAI` construction must pass timeout, token cap, retry count, API key, model, and base URL from the runtime config.
- Provider errors must never persist prompts, resident context, API keys, raw provider messages, or stack traces in `elder_ai_analyses`.
### 4. Validation & Error Matrix
- Missing `AI_API_KEY` -> return `AI_API_KEY 未配置`, persist failed history with `errorCategory: "missing_config"` when organization context exists.
- Provider timeout, `AbortError`, or timeout-like provider message -> return `AI 服务响应超时`, persist failed history with `errorCategory: "timeout"`.
- Other provider failure -> return `AI 服务暂时不可用`, persist failed history with `errorCategory: "provider_error"`.
- Invalid model output -> return `AI 返回结构不符合固定分析格式`, persist failed history with `errorCategory: "schema_validation_failed"`.
### 5. Good/Base/Bad Cases
- Good: configured runtime uses a short timeout, bounded max tokens, and no hidden retry amplification; timeout failures are visible as sanitized failed history.
- Base: provider is slow or unreachable; user receives the timeout reason instead of waiting for default SDK retries and transport timeouts.
- Bad: service relies on LangChain/OpenAI defaults, causing long waits from high token caps, implicit retries, or unbounded request timeouts.
### 6. Tests Required
- Unit: assert `generateElderAiAnalysis` constructs `ChatOpenAI` with runtime-configured `timeout`, `maxTokens`, and `maxRetries`.
- Unit: assert `AbortError` and timeout-like model failures persist `errorCategory: "timeout"`, return `AI 服务响应超时`, and do not persist provider secrets or prompt text.
- Existing failure tests must continue to assert provider errors and schema failures use sanitized persisted history.
### 7. Wrong vs Correct
#### Wrong
```typescript
new ChatOpenAI({
apiKey,
model,
maxTokens: 1800,
});
```
#### Correct
```typescript
new ChatOpenAI({
apiKey: config.apiKey,
model: config.chatModel,
timeout: config.requestTimeoutMs,
maxTokens: config.maxTokens,
maxRetries: config.maxRetries,
configuration: config.baseUrl ? { baseURL: config.baseUrl } : undefined,
});
```
## 6. Prompt Engineering Best Practices
### Use XML Structure for Complex Prompts

View File

@@ -31,3 +31,4 @@
- [x] Run focused tests covering changed code.
- [x] Run `pnpm type-check`.
- [x] Smoke-test the dashboard route when feasible via `pnpm build` route compilation.
- [x] Add latency controls for AI provider timeout, token cap, retry count, and sanitized timeout failure history.

View File

@@ -23,7 +23,8 @@ Finish the currently visible operations surface by making collaboration modules
- [x] AI analysis board items redact result content when `canViewAnalysisScopes` denies one or more stored data scopes.
- [x] Focused tests cover idempotent collaboration seeding and AI board redaction behavior.
- [x] `pnpm type-check` and focused tests pass.
- [x] Elder AI generation uses bounded provider timeout, token, and retry controls so slow providers fail with sanitized timeout history instead of hanging indefinitely.
## Notes
- Out of scope: background alert-rule execution, family portal/authentication, AI generation changes, and new database schema.
- Out of scope: background alert-rule execution, family portal/authentication, AI recommendation/business-action generation changes, and new database schema.