iop/agent-roadmap/archive/phase/serving-routing-optimization/milestones/model-serving-load-routing.md

120 lines
12 KiB
Markdown

# Milestone: Ollama E2E 서빙 안정화
## 위치
- Roadmap: `agent-roadmap/ROADMAP.md`
- Phase: `agent-roadmap/phase/serving-routing-optimization/PHASE.md`
## 목표
Edge에 OpenAI API 방식으로 접속한 외부 agent/client가 Edge-Node 소켓 경로를 의식하지 않고 Node에서 serving 중인 Ollama를 사용할 수 있게 한다.
현재 1차 우선순위는 `/v1/models` 조회, `/v1/chat/completions` non-streaming/streaming 호출, Ollama thinking/reasoning stream 보존, 수동 Node/model 선택, 실제 Ollama 사용자 흐름 검증까지 E2E 한 사이클을 자연스럽게 완성하는 것이다.
자동 라우팅, 부하 라우팅, cloud fallback, 품질 평가 feedback, Responses API 세부 호환은 이 E2E baseline 이후의 후속 작업으로 분리한다.
## 상태
[완료]
## 구현 잠금
- 상태: 해제
- 결정 필요: 없음
## 범위
- OpenAI-compatible `/v1/chat/completions` 호출을 내부 `adapter + target` 실행으로 해석하는 경계
- OpenAI-compatible `/v1/models` 조회와 `/v1/chat/completions` non-streaming/streaming 호출을 Edge -> Node -> Ollama 경로로 완성하는 1차 full-cycle
- 외부 agent/client가 일반 Ollama 또는 OpenAI-compatible endpoint를 쓰는 것과 유사하게 model을 조회하고, 요청 model을 내부 target으로 사용하고, 지원 가능한 generation option을 명확히 전달하는 경험
- Ollama `message.thinking`은 기본적으로 숨기거나 `think:false`로 끄지 않고, OpenWebUI류 UX처럼 thinking 중임을 알 수 있는 별도 reasoning stream으로 보존한다.
- Ollama 관련 조회/상태/관리 command를 IOP OpenAI-compatible 표면에서 어디까지 pass-through할지에 대한 1차 기준과 unsupported 응답 정책
- 여러 Node와 여러 model은 자동 라우팅이 아니라 `openai.node`, `openai.models`, 요청 `model`, `openai.target` 조합을 수동으로 바꿔 검증한다.
- 당시 repo 내부 `bin/edge.sh``bin/node.sh` 진단 흐름으로 필드 테스트 환경을 문서화한다.
- IOP native protocol, A2A, routing 최적화 계층과 OpenAI-compatible 서빙 표면의 책임 경계를 충돌 없이 정리한다.
## 필수 기능
### Epic: [e2e-serving-core] E2E Serving Core
- [x] [edge-node-ollama-path] Edge OpenAI-compatible API 요청이 Edge-Node 소켓을 통해 Node Ollama adapter로 전달되는 E2E 경로가 검증되어 있다.
- [x] [manual-node-select] Node 선택은 자동 라우팅이 아니라 `openai.node` 또는 단일 Node fallback 같은 수동 설정 기준으로 동작한다.
- [x] [manual-model-select] model 선택은 요청 `model` 또는 `openai.target` 고정값을 통해 수동으로 검증할 수 있다.
- [x] [routing-later] 자동 라우팅, 부하 라우팅, cloud fallback, 품질 평가 feedback은 후속 마일스톤으로 분리되어 있다.
### Epic: [ollama-openai-cycle] Ollama OpenAI-Compatible Full Cycle
- [x] [models-list] Edge `/v1/models`가 Node/Ollama에서 사용 가능한 model 목록을 외부 client가 기대하는 OpenAI-compatible 형식으로 제공한다.
- [x] [chat-cycle] Edge `/v1/chat/completions` 호출이 내부 `adapter=ollama`, `target=<model>` 실행으로 변환되어 Node Ollama adapter까지 왕복한다.
- [x] [streaming-cycle] non-streaming 응답과 streaming SSE 응답이 일반 OpenAI-compatible client에서 사용할 수 있는 형태로 동작한다.
- [x] [model-target-map] `openai.target` 고정 라우팅과 요청 `model` 기반 라우팅의 우선순위가 명확하며 Ollama model 선택 경험과 충돌하지 않는다.
- [x] [option-pass-through] temperature, top_p, max_tokens, stop, stream 등 1차 지원 option의 매핑과 미지원 option 응답 정책이 정리되어 있다.
- [x] [thinking-passthrough] Ollama `message.thinking` stream이 Edge-Node `RunEvent`에서 content delta와 구분되어 전달된다.
- [x] [openai-reasoning-ux] Edge OpenAI-compatible streaming/non-streaming 응답이 thinking을 `reasoning_content` 계열 확장 필드로 노출하고, 답변 content stream과 섞지 않는다.
- [x] [think-control] `think:false`는 기본값이 아니라 명시 옵션 또는 후속 client별 제어로만 다루며, 기본 UX는 thinking 보존으로 둔다.
- [x] [ollama-command-pass-through] Ollama 관련 모델 조회, 상태, 관리 command를 Edge OpenAI-compatible 표면에서 어디까지 pass-through할지 1차 범위가 정의되어 있다.
- [x] [openai-ollama-aux-smoke] fake Ollama 기반 보조 smoke가 OpenAI-compatible 입력 표면과 edge-node relay의 최소 생존을 확인한다.
- [x] [toki-labs-field-flow] 공통 필드 테스트 환경에서 `toki-labs` Ollama `gemma4:26b` 모델을 사용해 당시 repo 내부 bin edge-node 진단 흐름이 문서화되고 검증된다.
### Epic: [protocol-boundary] Protocol Boundary
- [x] [a2a-boundary] A2A API는 외부 agent의 작업 위임 표면으로 제한한다.
- [x] [nomadcode-a2a] NomadCode의 A2A 도입 시점은 이 Milestone에서 강제하지 않고 별도 판단으로 남긴다.
- [x] [native-protocol] IOP native protocol은 proto-socket 기반 내부/운영 호출 기준으로 두고 OpenAI-compatible UX에 운영 제어 기능을 억지로 싣지 않는다.
- [x] [optimization-later] RAG, MCP, web search, output validation은 기본 serving/load routing 이후 단계로 명시한다.
## 완료 기준
- [x] Edge `/v1/models``/v1/chat/completions`를 통해 Node의 Ollama serving을 조회하고 사용할 수 있다.
- [x] 외부 agent/client가 Edge endpoint를 일반 OpenAI-compatible 또는 Ollama-backed endpoint처럼 설정해 한 차례 모델 조회와 chat completion을 완료할 수 있다.
- [x] streaming/non-streaming 응답, thinking/reasoning passthrough, model-to-target 매핑, 1차 option pass-through, unsupported option 응답 정책이 검증되어 있다.
- [x] `gemma4:26b`처럼 thinking을 먼저 내보내는 모델에서도 사용자는 thinking 중임을 볼 수 있고, content가 시작되면 답변 stream을 자연스럽게 받을 수 있다.
- [x] 당시 repo 내부 `bin/edge.sh``bin/node.sh` 진단 흐름으로 Edge -> Node -> Ollama 흐름을 재현할 수 있다.
- [x] 최종 완료 검증은 fake Ollama smoke가 아니라 `toki-labs` 실제 Ollama 필드 흐름으로 수행된다.
- [x] 공통 필드 테스트 환경의 Node host, Ollama endpoint, model, 당시 내부 진단 config 기준이 문서화되어 있다.
- [x] Node/model 선택은 수동 설정으로 검증하고, 자동 라우팅과 부하 라우팅은 후속 작업으로 분리되어 있다.
- [x] 외부 API 표면과 IOP native protocol의 역할이 충돌하지 않는다.
- [x] 다음 단계인 model routing/fallback 최적화로 넘어갈 선행 조건이 정의된다.
## 완료 리뷰
- 상태: 승인됨
- 요청일: 2026-05-25
- 완료 근거: 실제 `toki-labs` Ollama `gemma4:26b` 필드 흐름에서 `/v1/models`, non-streaming chat, streaming SSE, reasoning/content 분리, `data: [DONE]`, Ollama native `/api/tags``/api/show` passthrough, Ollama option passthrough가 검증되었다. 다음 routing/fallback 선행 조건도 하드코딩 route test, 모든 에러 fallback raising, Ollama 기준 model profile, 수동 node/target 독립 제약으로 정리했다.
- 리뷰 필요:
- [x] 사용자가 완료 결과를 확인했다
- [x] archive 이동을 승인했다
- 리뷰 코멘트: 2026-05-25 사용자 확인에 따라 완료 처리하고 archive 이동한다.
## 범위 제외
- RAG 검색, context 압축, web search, MCP/tool policy 구현
- output validation, retry/fallback loop의 세부 알고리즘 구현
- NomadCode 전용 task metadata 계약 확정
- 외부 Agent CLI adapter 추가 구현
- 자동 Node 라우팅, 부하 라우팅, cloud fallback, 품질 평가 feedback 구현
- Responses API 세부 호환 구현
## 작업 컨텍스트
- 관련 경로: `apps/edge`, `apps/node`, `packages/config`, `packages/observability`, `proto/iop`, `docs/architecture.md`, `apps/edge/README.md`
- 1차 우선순위: OTO/bootstrap 연동보다 Edge OpenAI-compatible API -> Node -> Ollama serving full-cycle을 먼저 완성한다.
- 공통 필드 테스트 환경: `docs/deploy-dev.md``공통 Ollama 필드 테스트 환경`을 따른다.
- 표준선(선택): 내부 실행 계약은 `adapter + target`을 유지하고, OpenAI-compatible API는 외부 호환 입력 표면으로 둔다.
- 표준선(선택): 1차 구현은 local Ollama를 기준으로 하며 cloud fallback, 품질 평가 feedback, Responses API 세부 호환은 chat completions baseline 이후 확장한다.
- 표준선(선택): Edge `/v1/models`는 설정된 model 목록과 Node capability/Ollama 조회 결과 중 사용 가능한 근거를 우선해 반환하고, 요청 `model``openai.target`이 비어 있을 때 내부 target으로 사용한다.
- 표준선(선택): Ollama thinking은 `RunEvent.type=reasoning_delta` 같은 별도 event type으로 content delta와 구분하고, OpenAI-compatible SSE에서는 `delta.reasoning_content` 확장 필드로 노출한다.
- 표준선(선택): non-streaming 응답은 최종 `message.content`에 답변만 담고, thinking은 `message.reasoning_content` 확장 필드로 분리한다.
- 표준선(선택): `think:false`는 테스트 우회 기본값으로 쓰지 않고, 명시 요청 또는 후속 설정 항목으로만 고려한다.
- 진행 근거(2026-05-25): `b7d636c`에서 `EventTypeReasoningDelta`, Ollama `message.thinking` 분리 event, OpenAI-compatible `reasoning_content` streaming/non-streaming 응답, fake Ollama smoke의 reasoning 검증이 반영되어 있다.
- 검증 근거(2026-05-25): `go test ./apps/edge/internal/openai ./apps/node/internal/adapters/ollama`, `scripts/e2e-openai-ollama.sh` 통과.
- 검증 근거(2026-05-25): 당시 임시 Edge/Node config와 repo 내부 `bin/edge.sh`, `bin/node.sh` 진단 흐름으로 `http://192.168.0.97:11434``gemma4:26b`를 호출했다. `/v1/models``gemma4:26b`를 반환했고, non-streaming 응답 content는 `IOP_OLLAMA_E2E_OK`, reasoning 길이는 681 bytes였다. streaming SSE는 content delta를 이어 붙였을 때 `IOP_OLLAMA_STREAM_OK`, reasoning 길이는 695 bytes였고 `data: [DONE]`을 확인했다.
- 검증 메모(2026-05-25): `ssh toki@toki-labs.com` 원격 host는 접근 가능하지만 확인한 기본 경로에는 repo가 없고 `go`도 PATH에 없어, 이번 검증은 로컬 임시 Node가 실제 Ollama endpoint를 호출하는 방식으로 수행했다.
- 정책 확정(2026-05-25): OpenAI generation option과 Ollama 관련 command pass-through는 IOP가 별도 의미를 재정의하지 않고 Ollama가 지원하는 형식을 그대로 전달/노출하는 것을 기준으로 한다.
- 선행 조건 확정(2026-05-25): routing/fallback 최적화의 route test는 초기에는 하드코딩한다. 모든 에러는 fallback raising 조건이며, 에러 분류는 관측/정책 판단을 위한 구분일 뿐 fallback 트리거 자체를 막지 않는다.
- 선행 조건 확정(2026-05-25): 품질 평가, cloud fallback, 자동 부하 분산은 이 Milestone의 후속 단계에서 제외한다.
- 선행 조건 확정(2026-05-25): model profile은 IOP 고유 profile taxonomy를 새로 만들지 않고 Ollama가 제공/지원하는 model 정보와 option/capability 형식을 기준으로 맞춘다.
- 선행 조건 확정(2026-05-25): 수동 `node``target`은 우선순위 경쟁 관계가 아니라 독립 제약이다. 명시된 node에 target이 없거나 실행할 수 없으면 자동 보정하지 않고 에러로 처리한다.
- 검증 근거(2026-05-25): 실제 `toki-labs` Ollama field 환경에서 option 포함 non-streaming 응답 content는 `IOP_OLLAMA_OPTIONS_OK`, streaming SSE는 content delta를 이어 붙였을 때 `IOP_OLLAMA_STREAM_OK`, reasoning 길이는 537 bytes였고 `data: [DONE]`을 확인했다. Ollama native `/api/tags`는 6개 model을 반환했고 `/api/show``gemma4:26b` model info를 반환했다.
- 완료 후보(2026-05-25): 모든 필수 기능과 완료 기준이 evidence와 함께 충족되어 `[검토중]`으로 전환한다.
- 선행 작업: Edge 입력 표면, CLI Automation Runtime 안정화
- 후속 작업: 모델 라우팅/fallback 최적화, 지식/도구 정책/검증 최적화
- 확인 필요: cloud fallback 도입 시점, Responses API 세부 호환 범위, 모델 품질 평가와 routing feedback의 초기 신호