17 KiB
17 KiB
SDD: Model Alias Provider Pool과 Provider Catalog
위치
- Milestone:
agent-roadmap/phase/operational-observability-provider-management/milestones/provider-catalog-device-status.md - Phase:
agent-roadmap/phase/operational-observability-provider-management/PHASE.md
상태
[승인됨]
SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
- [D01] Edge config는
models[]를 model catalog이자 외부 model key 목록으로 두고, 각 model의providers에 provider id와 실제 served model name을 매핑한다. provider 정의는nodes[].providers[]아래에 두며, 각 provider는 제공 가능한models[]list를 가진다. - [D02] MVP provider 선택은 available provider 중
in_flight / capacityload ratio가 가장 낮은 후보를 우선한다. priority/weight/fallback 정책은 후속 확장으로 둔다. - [D03] provider별 실제 served target rewrite와 routing/control 책임은 Edge가 가진다. Node/provider adapter는 Edge가 전달한 concrete target을 실행한다.
- [D04] MVP provider category는
api,cli,local_inference로 시작하고, 상태 추적은health,capacity,in_flight, derivedload_ratio,models,queued까지 포함한다. runtime process와 resource telemetry는 후속으로 둔다. - [D05] MVP catalog에는 provider별 lifecycle capability를 coarse flags로만 표시하고, 상세 lifecycle 동작, compatibility, benchmark, quality, model별 qualification 결과는 후속 Qualification Report Milestone으로 둔다.
- [D06] MVP는 읽기 전용 관찰과 Edge config 기반 routing 계약까지만 포함한다. enable/disable, drain, fallback 우선순위 변경, capacity override 같은 runtime 제어는 후속 Milestone으로 둔다.
- [D01] Edge config는
문제 / 비목표
- 문제: 현재 OpenAI-compatible
modelroute는 단일adapter + target으로 해석되고, Edge queue도 같은 resolved target 기준으로 후보를 필터링한다.qwen3.6:35b같은 논리 model alias 아래에 vLLM, Lemonade, Ollama, SGLang 같은 여러 provider candidate를 묶으려면 alias를 canonical routing key로 유지하는 계약, candidate schema, selection/queue 정책, served target rewrite 책임, catalog 표시 기준을 먼저 고정해야 한다. - 비목표:
- vLLM, vLLM-MLX, Lemonade, SGLang provider adapter 구현 자체
- provider pool scheduler 코드 구현과 config migration 실행
- provider/device/model qualification report 저장/조회/비교
- 자동 benchmark, 품질 평가, provider marketplace, cross-Edge provider balancing
- cloud fallback과 품질 평가 feedback 구현
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | agent-roadmap/phase/operational-observability-provider-management/milestones/provider-catalog-device-status.md |
Milestone 목표, 범위, 기능 Task, 잠금 해제 기준 |
| Code | packages/go/config/config.go |
현재 openai.model_routes[], adapter instance config, capacity/queue config 구조 |
| Code | apps/edge/internal/openai/routes.go |
/v1/models가 model_routes를 catalog처럼 노출하는 현재 외부 model 표면 |
| Code | apps/edge/internal/service/run_dispatch.go |
ModelGroupKey 기반 queue, candidate filtering, capacity policy의 현재 dispatch 기준 |
| Code | proto/iop/runtime.proto |
ProviderSnapshot의 provider 상태, capacity, in-flight, queued 기준 |
| External Provider | 없음 | 이번 Milestone은 외부 provider 상태를 변경하지 않고 IOP 내부 계약과 catalog 기준을 고정한다. |
| User Decision | user_review_0.log |
D01-D06 resolved |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
| Model Accepted | OpenAI-compatible model 또는 내부 실행 요청이 models[].id에 정의된 model id를 포함한다. |
Candidate Resolving | agent-contract/provided/openai-compatible-api.md, SubmitRunRequest.ModelGroupKey |
| Candidate Resolving | Edge가 models[].providers에서 provider id와 실제 served model name 매핑을 읽는다. |
Candidate Ready 또는 No Candidate | packages/go/config/config.go, apps/edge/internal/service/run_dispatch.go |
| Provider Matched | models[].providers의 provider id가 nodes[].providers[].id와 매칭되고, served model name이 해당 provider의 models[]에 존재한다. |
Candidate Ready 또는 No Candidate | Edge config validation |
| Candidate Ready | candidate가 enabled이고 health/capacity/in-flight 기준을 만족한다. | Load Ranked | provider snapshot, adapter instance capacity, queue policy |
| Load Ranked | Edge가 available candidate의 in_flight / capacity load ratio를 계산한다. |
Target Rewritten 또는 Queued | 낮은 load ratio 우선, 동률 시 deterministic tie-break |
| Target Rewritten | Edge가 선택된 provider id의 served model name을 models[].providers[provider_id]에서 읽는다. |
Dispatched | Edge-owned routing/control 책임 |
| Queued | 즉시 사용 가능한 slot이 없고 queue policy가 대기를 허용한다. | Dispatched 또는 Timed Out | ModelGroupKey queue, max_queue, queue_timeout_ms |
| Dispatched | Edge가 선택한 node/provider와 concrete served target을 Node에 전달한다. | Completed 또는 Failed | Edge-Node run request, run event |
| Catalog Observed | Node/Edge가 provider snapshot 또는 catalog 상태를 갱신한다. | Available, Degraded, Unavailable | health, capacity, in_flight, load_ratio, models, queued |
Interface Contract
- 계약 원문:
agent-contract/provided/openai-compatible-api.md - 입력:
models[].id: OpenAI-compatible API의model로 호출 가능한 model id이며,qwen3.6:35b같은 형식을 유지한다.models[].display_name: 운영 화면에서 보여줄 model 이름이다.models[].providers: provider id를 key로, 해당 provider에서 실제 호출할 served model name을 value로 둔 map이다.models[].providers.<provider_id>:nodes[].providers[].id와 매칭되는 provider id다.models[].providers[<provider_id>]: provider가 실제로 제공하는 model id 또는 target profile이며, 해당 provider의models[]list 안에 있어야 한다.nodes[].id: provider를 소유하는 Node identity다.nodes[].providers[]: provider 정의는 Node 아래에 둔다. 같은 Node 아래에 여러 provider가 있을 수 있다.nodes[].providers[].id:models[].providers의 key로 참조되는 provider id다.nodes[].providers[].type: provider runtime type이다. 예:ollama,vllm,lemonade,sglang,openai_api,cli.nodes[].providers[].category: MVP provider category다. 값은api,cli,local_inference로 시작한다.nodes[].providers[].models: 해당 provider가 실제로 제공 가능한 served model name list다.provider.health:available,unavailable,unknown중 하나의 최소 provider health 상태다.provider.capacity: provider가 동시에 처리할 수 있는 실행 slot 수다.provider.in_flight: provider에서 현재 실행 중인 요청 수다.provider.load_ratio:in_flight / capacity로 계산하는 선택 기준이다. capacity가 0이거나 알 수 없으면 선택 대상에서 제외하거나 unavailable로 본다.provider.queued: Edge queue에서 관측 가능한 provider 또는 model group 대기 요청 수다.provider.lifecycle_capabilities: provider별 model lifecycle capability를 coarse flags로 표시한다. 예:list_models,load_model,unload_model,pull_model,delete_model.catalog.status: MVP에서는 health, capacity, in-flight, derived load ratio, model list, queued, coarse lifecycle capability를 표시한다. runtime process/container detail과 CPU/GPU/RAM/VRAM resource telemetry는 후속으로 둔다.catalog.control: MVP에서는 읽기 전용 관찰과 Edge config 기반 routing 계약만 포함한다. runtime control은 후속 Milestone 책임이다.
- 출력:
resolution.adapter: Node에 전달할 adapter type 또는 adapter instance key다.resolution.target: Node adapter가 실행할 concrete served target이다.resolution.node_id: 선택된 Node identity다.resolution.provider_id: Edge가 선택한 provider identity다.resolution.model_group_key: queue와 관측에 남길models[].id다.catalog.providers[]: 운영자가 provider pool과 provider 상태를 비교할 수 있는 표시 record다.
- 금지:
- OpenAI-compatible 외부 경계에서
model을 제거하거나 caller에게adapter + target을 직접 요구하지 않는다. models[]에 정의되지 않은 model id를 새 provider-pool 경로에서 암묵적으로 실행하지 않는다.- 단일 provider model이라도 별도 축약 구조를 만들지 않고
models[].providers에 provider 한 개만 둔다. models[].providers에서 참조한 provider id가nodes[].providers[].id에 없거나, served model name이 해당 provider의models[]에 없으면 유효한 route로 보지 않는다.- capacity가 남았다는 이유만으로 더 높은 load ratio의 provider를 우선 선택하지 않는다.
- MVP selection policy에 priority, weight, fallback policy를 필수 필드로 넣지 않는다.
- Node/provider adapter가 catalog model id나 alias를 자체적으로 provider별 served model name으로 rewrite하지 않는다.
- MVP catalog/status에 runtime process/container detail이나 CPU/GPU/RAM/VRAM resource telemetry를 필수 필드로 넣지 않는다.
- MVP catalog에 lifecycle API 상세 동작, compatibility, benchmark, quality score, model별 qualification 결과를 직접 넣지 않는다.
- MVP catalog/control 표면에 provider enable/disable, drain, fallback 우선순위 변경, capacity override 같은 runtime 제어를 넣지 않는다.
- Control Plane을 Edge-owned provider 상태의 canonical store로 만들지 않는다.
- SDD 본문에 agent-contract 원문을 복제하지 않는다.
- qualification report, benchmark, 품질 비교를 이번 Milestone의 필수 구현으로 끌어오지 않는다.
- OpenAI-compatible 외부 경계에서
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | alias-contract |
운영자가 models[]에 qwen3.6:35b 같은 model id를 정의한다. |
OpenAI-compatible 요청 또는 내부 실행 요청이 해당 model id를 사용한다. | model id는 queue와 catalog의 canonical key로 유지되고, dispatch 직전에만 provider별 served model name으로 해석된다. |
| S02 | candidate-schema |
하나의 models[] 항목에 여러 provider id와 served model name 매핑이 있다. |
provider pool schema를 검토한다. | models[].providers가 provider id -> 실제 served model name map으로 정리되어 있고, provider 정의는 Node 아래 provider list로 분리되며, provider별 models[] list가 제공 가능 모델의 기준이 된다. |
| S03 | target-rewrite |
provider마다 실제 served model id가 다르다. | Edge가 candidate를 선택한다. | Edge가 models[].providers[provider_id] 값을 concrete target으로 rewrite해 Node에 전달하고, Node/provider adapter는 전달받은 target만 실행한다. |
| S04 | selection-policy |
여러 candidate가 서로 다른 health, capacity, in-flight 값을 가진다. | Edge가 실행 후보를 고른다. | unavailable 후보를 제외하고 in_flight / capacity load ratio가 가장 낮은 provider를 우선 선택한다. 예: 1/3 provider가 2/3 provider보다 우선한다. |
| S05 | pool-compat |
기존 openai.model_routes, adapter + target, Node provider instance 설정이 존재한다. |
새 pool 계약을 도입하거나 compat layer를 설계한다. | 기존 route와 provider instance 설정의 호환/마이그레이션 방향이 정리되어 있다. |
| S06 | category-map |
API, CLI, local inference provider가 같은 catalog에 노출된다. | catalog 표시 필드를 검토한다. | MVP category는 api, cli, local_inference로 정의되어 있다. |
| S07 | device-status |
local inference provider가 health, capacity, in-flight, model list, queue 상태 일부를 제공한다. | 운영자가 상태를 조회한다. | MVP 상태 필드는 health, capacity, in_flight, derived load_ratio, models, queued이며 runtime/resource telemetry는 후속으로 분리되어 있다. |
| S08 | lifecycle-cap |
Ollama/Lemonade와 vLLM/SGLang의 model lifecycle 동작이 다르다. | catalog 또는 후속 report 입력을 설계한다. | MVP catalog에는 coarse lifecycle capability flags만 표시하고 상세 lifecycle/compatibility/benchmark/quality/qualification 결과는 후속 Milestone으로 분리되어 있다. |
| S09 | boundary |
adapter 구현, pool routing, 운영 catalog가 서로 다른 책임을 가진다. | 구현 계획을 작성한다. | provider adapter 구현, provider pool routing, read-only operations catalog, 후속 runtime control의 책임 경계가 분리되어 있다. |
| S10 | ops-review |
SDD와 사용자 결정 항목이 준비되어 있다. | 사용자가 MVP 범위와 2차 후보를 검토한다. | D01-D06 결정이 user_review_0.log와 SDD에 반영되고 SDD 잠금이 해제되어 있다. |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
Spec Completion 기대 |
|---|---|---|---|
| S01 | pool 계약 문서 또는 config/proto/API diff, OpenAI-compatible model id test | agent-task/m-provider-catalog-device-status/... |
alias-contract가 models[].id canonical key와 dispatch resolution 기준을 충족했다는 근거 |
| S02 | candidate schema diff 또는 SDD/plan 확정 표, config validation test | agent-task/m-provider-catalog-device-status/... |
candidate-schema가 models[].providers map, Node 하위 provider 정의, provider별 models[] list 검증 기준을 충족했다는 근거 |
| S03 | target rewrite 책임 문서, Edge/Node request mapping test | agent-task/m-provider-catalog-device-status/... |
target-rewrite가 Edge-owned routing/control 원칙을 따르고 concrete target 전달을 검증했다는 근거 |
| S04 | queue/selection policy test 또는 smoke, timeout/overflow case evidence | agent-task/m-provider-catalog-device-status/... |
selection-policy가 available provider 중 낮은 in_flight / capacity load ratio를 우선하고, 동률 tie-break와 queue timeout을 검증했다는 근거 |
| S05 | migration/compat note, 기존 model_routes regression test |
agent-task/m-provider-catalog-device-status/... |
pool-compat가 기존 OpenAI route와 Node provider instance 설정을 깨지 않는다는 근거 |
| S06 | catalog DTO/API/UI/CLI 표시 evidence | agent-task/m-provider-catalog-device-status/... |
category-map이 api, cli, local_inference category를 확인했다는 근거 |
| S07 | provider snapshot/status test, unknown/unavailable case evidence | agent-task/m-provider-catalog-device-status/... |
device-status가 health/capacity/in-flight/load-ratio/models/queued 범위를 검증하고 runtime/resource telemetry를 후속으로 분리했다는 근거 |
| S08 | lifecycle capability 표 또는 follow-up handoff evidence | agent-task/m-provider-catalog-device-status/... |
lifecycle-cap이 coarse flags로 catalog에 표시되고 상세 qualification 항목은 후속 Milestone으로 분리되었다는 근거 |
| S09 | architecture boundary note, package/API ownership evidence | agent-task/m-provider-catalog-device-status/... |
boundary가 adapter, routing, read-only catalog, 후속 runtime control 책임을 분리했다는 근거 |
| S10 | user_review_0.log 해결 log 또는 사용자 승인 기록 |
agent-task/m-provider-catalog-device-status/... |
ops-review가 완료되어 SDD 잠금 해제 상태를 확인했다는 근거 |
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 열린 사용자 리뷰가 없고 해결된 리뷰는
user_review_0.log에 남겼다.
사용자 리뷰 이력
user_review_0.log: D01-D06 결정 반영, SDD 잠금 해제
작업 컨텍스트
- 표준선: 외부 OpenAI-compatible 경계는
model을 유지하고, 내부 실행은adapter + target으로 resolve한다. Edge는 queue와 dispatch를 담당하며, Edge-owned 상태의 canonical store는 Control Plane이 아니라 Edge/Node 쪽에 둔다. - 후속 SDD: 없음. Provider-Device-Model Qualification 리포트 Milestone에서 lifecycle capability, benchmark, 품질 비교 저장/조회가 구현 범위가 되면 별도 SDD 필요 여부를 다시 판정한다.