7.5 KiB
7.5 KiB
SDD: OpenAI-compatible Think 제어 MVP
위치
- Milestone:
agent-roadmap/archive/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-think-control.md - Phase:
agent-roadmap/phase/knowledge-tool-optimization-extension/PHASE.md
상태
[승인됨]
SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
- 없음
문제 / 비목표
- 문제: dev-runtime provider는 reasoning-capable 상태로 기동되어 있지만, 현재 OpenAI-compatible 요청자는 요청 단위로 thinking 생성을 끄거나 reasoning 응답 노출을 숨길 수 없다. 공개 API가 provider별 raw option을 그대로 열면 호환성과 검증 경계가 흐려지므로, Edge가 검증 가능한 field를 받고 Node adapter가 provider별 option으로 매핑해야 한다.
- 비목표:
/v1/responses의 streaming 또는 reasoning output item 확장- provider runtime 기동/lifecycle 자동화
- usage ledger의 hidden reasoning token 정산
- 단계 호출 planner/generator/verifier 제품 UX 확정
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | agent-roadmap/archive/phase/knowledge-tool-optimization-extension/milestones/openai-compatible-think-control.md |
기능 Task와 완료 evidence 기준 |
| Code | apps/edge/internal/openai, apps/node/internal/adapters/openai_compat |
request decode, run input, provider request body, response filtering 구현 기준 |
| Contract | agent-contract/outer/openai-compatible-api.md |
공개 OpenAI-compatible request/response 계약 |
| External Provider | vLLM Qwen3, vLLM-MLX Qwen3, Lemonade | provider별 reasoning option 지원 여부는 dev smoke와 mock 테스트로 확인 |
| User Decision | 없음 | 공개 field와 기본값은 기존 OpenAI-compatible 원칙과 provider 동작을 기준으로 확정 가능 |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
| default | 요청에 think 관련 field가 없다 | provider-default | 기존 요청 호환성 유지 |
| think-disabled | think=false 또는 reasoning_effort=none이 유효하다 |
content-only | Edge request validation, provider request body |
| think-enabled | think=true 또는 thinking budget/effort가 유효하다 |
reasoning-capable | provider runtime capability와 request body |
| reasoning-hidden | include_reasoning=false가 유효하다 |
response-filtered | Edge stream/non-stream response writer |
| unsupported | provider가 요청 조합을 지원하지 않거나 field 타입/범위가 틀리다 | error | OpenAI-compatible 400 error 또는 명시 fallback 정책 |
Interface Contract
- 계약 원문:
agent-contract/outer/openai-compatible-api.md - 입력:
think: optional boolean.false는 reasoning/thinking 생성을 끄도록 요청하고,true는 provider가 지원하면 thinking 생성을 명시 활성화한다.reasoning_effort: optional string.none은think=false와 같은 disable 의미로 처리하고, 그 외 값은 provider가 지원하는 경우에만 전달한다.thinking_token_budget: optional non-negative integer. provider가 지원하면 thinking budget으로 전달하고, 지원하지 않으면 명시 error 또는 정의된 fallback을 반환한다.include_reasoning: optional boolean.false이면 provider가 reasoning을 생성하더라도 OpenAI-compatible 응답의reasoning_content를 노출하지 않는다.
- 출력:
- streaming:
include_reasoning이 true 또는 생략이면 reasoning delta를delta.reasoning_content로 반환하고, false이면 reasoning delta를 쓰지 않는다. - non-streaming:
include_reasoning이 true 또는 생략이면message.reasoning_content를 반환할 수 있고, false이면 반환하지 않는다. - content/tool output: reasoning 노출 정책과 별개로 기존 content/tool_calls 계약을 유지한다.
- streaming:
- 금지:
- 공개 request에 raw
optionswrapper 또는 provider rawchat_template_kwargswrapper를 그대로 추가하지 않는다. - provider가 지원하지 않는 think/budget 조합을 조용히 무시하지 않는다.
metadata에 think 제어 field를 넣어 공개 API 의미를 우회하지 않는다.include_reasoning=false를 provider raw trace나 진단 로그 비활성화로 해석하지 않는다.
- 공개 request에 raw
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | request-contract |
Chat Completions 요청에 think=false가 있다 |
Edge가 요청을 decode한다 | 요청은 400으로 거부되지 않고 run input에 think disable 의미가 들어간다 |
| S02 | provider-mapping |
provider pool 후보가 vLLM Qwen3, vLLM-MLX, Lemonade다 | think=false 요청을 dispatch한다 |
각 provider request body가 지원 field 또는 내부 chat_template_kwargs.enable_thinking=false로 매핑된다 |
| S03 | reasoning-visibility |
provider가 reasoning delta를 반환한다 | 요청에 include_reasoning=false가 있다 |
Edge OpenAI-compatible stream/non-stream 응답에는 reasoning_content가 없다 |
| S04 | default-compat |
기존 caller가 think field를 생략한다 | Chat Completions를 호출한다 | 현재 provider 기본 thinking 동작과 기존 content/tool behavior가 유지된다 |
| S05 | dev-smoke |
dev-runtime 세 provider가 connected/healthy다 | 기본값, think=false, include_reasoning=false smoke를 실행한다 |
provider raw trace와 Edge SSE의 reasoning 생성/노출 상태가 기대와 일치한다 |
| S06 | contract-docs |
구현이 완료되었다 | 계약 문서와 dev 문서를 확인한다 | 공개 field, 기본값, provider unsupported 정책이 문서화되어 있다 |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
완료 Evidence 기대 |
|---|---|---|---|
| S01 | Edge OpenAI request decoder/unit test | agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 request-contract와 테스트 명령 기록 |
| S02 | Node openai_compat request body unit test와 provider별 mock |
agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 provider-mapping과 mock 검증 기록 |
| S03 | stream/non-stream response filtering test | agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 reasoning-visibility와 테스트 명령 기록 |
| S04 | 기존 chat/tool/provider pool regression test | agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 default-compat와 회귀 테스트 기록 |
| S05 | dev-runtime smoke 결과와 raw trace/Edge SSE 비교 요약 | agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 dev-smoke와 provider별 관측 기록 |
| S06 | 계약 문서 diff와 문서 검증 | agent-task/m-openai-compatible-think-control/... |
Roadmap Completion에 contract-docs와 수정 문서 경로 기록 |
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 사용자 리뷰가 필요한 항목은
USER_REVIEW.md에만 남겼다.
사용자 리뷰 이력
- 없음
작업 컨텍스트
- 표준선: OpenAI-compatible 공개 표면은 provider raw wrapper가 아니라 검증 가능한 top-level field를 받으며, provider별 세부 option은 Edge/Node adapter 내부 매핑으로 처리한다.
- 후속 SDD: 없음