Skip to content

feat(llm): OpenRouter 제공자 — 생각 이어 가기·200 실패·비용 (4.92.0) - #163

Merged
SonAIengine merged 1 commit into
mainfrom
feat/openrouter-provider
Oct 15, 2026
Merged

SonAIengine merged 1 commit into
mainfrom
feat/openrouter-provider

Conversation

@SonAIengine

Copy link
Copy Markdown
Contributor

변경

한 키로 여러 회사 모델(Claude·GPT·Gemini·DeepSeek·Qwen …)을 부르는 OpenRouter 를 openrouter 제공자로 등록한다.
API 모양이 OpenAI Chat Completions 라서 OpenAIClient 를 그대로 쓰고(llm_client/openrouter.py), 표준 밖의 것만 더했다.

  • 생각 이어 가기: 답의 reasoning_details(스트림은 index 별로 이어 붙임)를 앞머리 reasoning 블록으로 받고,
    다음 호출의 모델이 같으면 고치지 않고 돌려준다. 도구 루프에서 Claude·Gemini 가 생각을 이어 가려면 이게 필요하다.
  • 200 으로 오는 실패: choices 없이 error 만 있는 본문과 스트림 error 청크를 error.code 로 분류
    (402 → TERMINAL, 429 → RATE_LIMITED, 401/403 → AUTH, 5xx → SERVER_ERROR, 문맥 초과 → TOKEN_LIMIT).
  • 비용: usage.cost → TokenUsage.cost_usd.
  • 생각 강도: extra_body.reasoning(effort·enabled). 단계는 밑의 모델 표(anthropic/openai/google)를 따르고,
    모델이 받지 않는 설정이면 한 번 빼고 다시 보낸다. 끌 때는 enabled: false.
  • system 역할 사용, warmup 은 /key, 컨텍스트 기본값 128k(호스트가 카탈로그 값을 먼저 씀), temperature 0~2.
  • 함께 고친 것: Chat Completions 스트림에서 choices 가 있는 사용량 청크를 버려 토큰이 0 으로 남던 문제.
  • 4.92.0, CHANGELOG. (4.91.0 은 feat(observability): LLM 호출·도구 실행 OpenTelemetry span #162 가 먼저 썼다.)

테스트

  • 새 테스트 31개(tests/llm_client/unit/test_openrouter_client.py). 전체 6119 passed, 14 skipped (Python 3.12).
  • ruff check · ruff format --check · mypy(core + llm_client) · gen_event_docs.py --check 통과.
  • 실키 QA(son 스택, xgen-workflow 연동, qwen/qwen3.8-flash): 일반 대화, 도구 루프(Bash → ToolSearch → ShareFile),
    이미지 입력, 생각 high(추론 블록이 도구 호출 앞뒤로 보존됨) / off(추론 0개), usage.cost 기록까지 확인.

머지 후

v4.92.0 태그를 push 하면 릴리스 휠이 만들어진다. xgen-workflow MR 이 이 휠 URL 을 가리키므로 그 MR 보다 먼저 필요하다.

🤖 Generated with Claude Code

한 키로 Claude·GPT·Gemini·DeepSeek·Qwen 등을 부르는 OpenRouter 를 `openrouter` 로 등록한다.
OpenAI Chat Completions 모양이라 OpenAIClient 를 그대로 쓰고 표준 밖의 셋만 더했다.

- reasoning_details 를 reasoning 블록으로 받아 같은 모델의 다음 호출에 그대로 돌려준다
  (스트림은 index 별로 이어 붙임). 도구 루프에서 Claude·Gemini 가 생각을 잇는 데 필요하다.
- choices 없이 error 만 오는 200 본문·스트림 error 청크를 error.code 로 분류
  (402 → TERMINAL, 429 → RATE_LIMITED, 401/403 → AUTH, 5xx → SERVER_ERROR).
- usage.cost → TokenUsage.cost_usd.
- 생각 강도는 extra_body.reasoning 으로. 단계는 밑의 모델 표(anthropic/openai/google)를 따르고,
  받지 않으면 한 번 빼고 다시 보낸다.

함께 고친 것: Chat Completions 스트림이 choices 가 있는 사용량 청크를 버려 토큰이 0 으로 남던 것.

테스트: 새 테스트 31개, 전체 6108 passed. ruff·mypy(core+llm_client)·events 문서 검사 통과.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SonAIengine
SonAIengine merged commit b3ccadb into main Oct 15, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant