feat: LLM Batch API — OpenAI + Anthropic 50% cost reduction (v0.9.8)
Submit up to 1000 unbriefed documents to the provider Batch API in one
shot instead of individual synchronous LLM calls. Results are polled
every 30 minutes via a new Celery beat task and imported automatically.
- New worker: llm_batch_processor.py
- submit_llm_batch: guards against duplicate batches, builds JSONL
(OpenAI) or request list (Anthropic), stores state in AppSetting
- poll_llm_batch_results: checks batch status, imports completed
results with idempotency, emits notifications + triggers news fetch
- celery_app: register worker, route to llm queue, beat every 30 min
- admin API: POST /submit-llm-batch + GET /llm-batch-status endpoints
- Frontend: submitLlmBatch + getLlmBatchStatus in adminAPI; settings
page shows batch control row (openai/anthropic only) with live
progress line while batch is processing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -297,4 +297,10 @@ export const adminAPI = {
|
||||
apiClient.get<{ remaining: number; limit: number }>("/api/admin/newsapi-quota").then((r) => r.data),
|
||||
clearGnewsCache: () =>
|
||||
apiClient.post<{ cleared: number }>("/api/admin/clear-gnews-cache").then((r) => r.data),
|
||||
submitLlmBatch: () =>
|
||||
apiClient.post("/api/admin/submit-llm-batch").then((r) => r.data),
|
||||
getLlmBatchStatus: () =>
|
||||
apiClient.get<{ status: string; batch_id?: string; doc_count?: number; submitted_at?: string }>(
|
||||
"/api/admin/llm-batch-status"
|
||||
).then((r) => r.data),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user