From 89b6aaf9d68d23a71a46ae7ec07f7e428201aba4 Mon Sep 17 00:00:00 2001 From: toki Date: Mon, 13 Jul 2026 11:45:56 +0900 Subject: [PATCH] update test rules and docs --- .../project/dev-corp-runtime-deploy/SKILL.md | 54 +- agent-test/dev-corp/control-plane-smoke.md | 2 +- agent-test/dev-corp/edge-smoke.md | 65 +- agent-test/dev-corp/inventory.yaml | 624 +++++++----------- agent-test/dev-corp/node-smoke.md | 61 +- agent-test/dev-corp/platform-common-smoke.md | 2 +- agent-test/dev-corp/rules.md | 8 +- agent-test/dev-corp/testing-smoke.md | 8 +- docs/dev-corp-openai-compatible-call-guide.md | 75 --- docs/edge-local-dev-guide.md | 14 +- docs/openai-compatible-api-contract.md | 2 +- 11 files changed, 367 insertions(+), 548 deletions(-) delete mode 100644 docs/dev-corp-openai-compatible-call-guide.md diff --git a/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md b/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md index 9e3104e..97c69bf 100644 --- a/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md +++ b/agent-ops/skills/project/dev-corp-runtime-deploy/SKILL.md @@ -1,6 +1,6 @@ --- name: dev-corp-runtime-deploy -version: 1.0.7 +version: 1.0.10 description: dev-corp 배포, public digitalplatform Edge와 내부 DGX/Mac Studio provider pool 배포 및 OpenAI-compatible capacity smoke 절차 --- @@ -20,7 +20,7 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. ## 입력 - `env`: 배포 대상 환경. 기본값은 `dev-corp`이다. -- `model`: OpenAI-compatible model alias. 지정하지 않으면 `agent-test/dev-corp/inventory.yaml`의 `model.alias`를 사용한다. +- `model`: OpenAI-compatible model alias. 지정하지 않으면 `agent-test/dev-corp/inventory.yaml`의 `model.aliases`에 기록된 model-specific alias를 사용한다. - `capacity_targets`: provider별 기대 capacity. 지정하지 않으면 `agent-test/dev-corp/inventory.yaml`의 target 후보 값을 사용한다. - `source_ref`: 배포할 git ref. 지정하지 않으면 mac-mini checkout의 기본 배포 branch 기준을 따른다. @@ -31,12 +31,13 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. - [ ] dev-corp Edge 배포/검증 통로는 `iop.ai.kr`이다. mac-mini runner/provider 관리 경유지를 Edge 배포, OpenAI-compatible smoke, Node `edge_addr`, bootstrap 기본 URL로 잡지 않는다. - [ ] dev-corp provider pool과 compose/local/dev-runtime profile을 섞지 않는다. dev-corp provider pool은 public `iop.ai.kr` Edge와 dev-corp config를 기준으로 한다. - [ ] mac-mini에 `/Users/fe/agent-work/iop-dev-corp` checkout이 없으면 배포를 시작하지 말고 checkout 생성과 source sync를 setup blocker로 보고한다. -- [ ] mac-mini에서 `192.168.2.2:8002`, `192.168.2.4:8004`, `192.168.2.3:8004`의 `/health`와 `/v1/models`가 성공하는지 확인한다. +- [ ] mac-mini에서 Spark Ornith `192.168.2.2:8003`, `192.168.2.4:8005`와 Mac Studio Gemma4 `192.168.2.3:8004`의 `/health`와 `/v1/models`가 성공하는지 확인한다. - [ ] Edge config의 OpenAI-compatible adapter endpoint는 각 Node process 기준으로 평가된다. direct preflight는 `192.168.2.x` 주소로 하되, Edge가 Node에 내려주는 provider endpoint는 node-local `127.0.0.1:`를 우선한다. - [ ] DGX Spark 01/02와 Mac Studio Node의 Edge addr은 `iop.ai.kr:18087`이다. mac-mini local route 또는 reverse SSH tunnel은 현재 기준 잘못된 Edge addr이며 명시적인 rollback/장애 비교 외에는 사용하지 않는다. -- [ ] `gemma4:26b` alias와 총 capacity `13`은 `agent-test/dev-corp/inventory.yaml`의 최신 검증 상태를 기준으로 판단한다. 새 배포에서 Edge config 반영과 capacity smoke가 통과하기 전에는 새 결과를 확정값으로 보고하지 않는다. -- [ ] DGX Spark vLLM provider는 capacity `4`, 호출당 최대 context window `262144`, requested KV `262144x2` 이상을 기준으로 한다. vLLM에는 vLLM-MLX식 `--max-kv-size`가 없으므로 실제 KV cache는 `gpu_memory_utilization` 적용 후 startup log의 `GPU KV cache size`와 `Maximum concurrency for 262,144 tokens per request`로 검증한다. DGX01/02 검증 기준은 `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`이고, FP4 MoE 커널 한계 보정을 위해 `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304`도 함께 둔다. Gemma4 agent/tool-call profile은 `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, Gemma4 tool chat template, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 함께 둔다. -- [ ] DGX Spark 02 endpoint는 Docker publish 때문에 `192.168.2.4:8004`이다. `8000`, `8001`, `8002`를 기본 endpoint로 쓰지 않는다. +- [ ] `gemma4:26b`와 `ornith:35b` alias, 그리고 현재 provider별 capacity는 `agent-test/dev-corp/inventory.yaml`의 최신 검증 상태를 기준으로 판단한다. 현재 방향은 Gemma4는 Mac Studio, Ornith는 Spark 01/02 provider pool이다. 새 배포에서 Edge config 반영과 capacity smoke가 통과하기 전에는 새 결과를 확정값으로 보고하지 않는다. +- [ ] DGX Spark vLLM provider의 catalog capacity `4`는 `262144` token request 4개가 항상 context 100%를 채우는 보장이 아니다. dev-corp 운영 기준은 호출당 prompt+generated KV가 최대 context의 `50-70%`라는 가정이다. capacity `4`, max context `262144`에서 KV `524,288` tokens / full-context concurrency `2.0x`는 lower bound이고, 운영 target은 KV `734,004-786,432` tokens / full-context concurrency `2.8x-3.0x`이다. 이 값이 `4.0x`가 아니라는 이유만으로 under-capacity로 판정하지 않되, `2.0x-2.8x`는 workload-specific smoke 없이는 운영 적합으로 보지 않는다. vLLM에는 vLLM-MLX식 `--max-kv-size`가 없으므로 실제 KV cache는 `gpu_memory_utilization` 적용 후 startup log의 `GPU KV cache size`와 `Maximum concurrency for 262,144 tokens per request`로 검증한다. 2026-07-13 기준 Ornith Spark01은 `8003`, `--gpu-memory-utilization 0.47`, KV `783,347`, full-context `2.99x`; Spark02는 `8005`, `--gpu-memory-utilization 0.50`, KV `1,074,276`, full-context `4.10x`이다. +- [ ] provider catalog admission queue timeout은 `queue_timeout_ms=0`으로 비활성화하고, Node `openai_compat_instances` adapter queue/request budget은 long reasoning/long-context 요청을 위해 `queue_timeout_ms=1800000`, `request_timeout_ms=1800000`으로 유지한다. +- [ ] DGX Spark 02 Ornith endpoint는 Docker publish 때문에 host `192.168.2.4:8005` -> container `8000`이다. `8000`, `8001`, `8002`, `8004`를 Spark02 Ornith 기본 endpoint로 쓰지 않는다. - [ ] Mac Studio `192.168.2.3:8005` DiffusionGemma endpoint는 secondary provider 후보이며 기본 pool에 자동 포함하지 않는다. - [ ] Mac Studio `192.168.2.3:8004` provider catalog type은 `openai_compat`이고 실제 runtime은 vLLM-MLX이다. provider catalog capacity는 `5`로 유지하고, vLLM-MLX runtime은 `vllm-mlx=0.4.0`, 호출당 최대 context window `262144`, requested KV `262144x3` 기준으로 runtime headroom `--max-num-seqs 6`, `--prefill-batch-size 6`, `--completion-batch-size 6`, `--max-request-tokens 262144`, `--max-kv-size 786432`을 사용한다. Continuous batching은 필수로 유지하고, Gemma4 MLLM/prefix-cache 불안정성을 피하기 위해 `--disable-prefix-cache`를 둔다. Gemma4 agent/tool-call profile은 현재 지원되는 `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 함께 둔다. - [ ] Mac Studio `192.168.2.3:8004` vLLM-MLX runtime은 2026-06-25 기준 detached `screen` session `vllm_mlx_8004`로 관리한다. 이 host는 Python `pyexpat` 로딩에 `DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib`가 필요하므로 재시작 명령에 반드시 포함한다. @@ -47,20 +48,21 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. ## known/current runtime update notes - DGX Spark 01/02의 requested KV `262144x2`는 vLLM에서 직접 `--max-kv-size`로 표현하지 않는다. `--max_num_batched_tokens`는 scheduler iteration budget이므로 KV cache 총량으로 취급하지 않는다. dev-corp 기준은 `--max-model-len 262144`와 `gpu_memory_utilization` 적용 후 startup log의 KV cache/concurrency 확인이다. -- DGX Spark에서 explicit `--max-num-batched-tokens 524288`를 사용하는 경우 first profile 중 FP4 MoE token-per-expert 기본 한계에 걸릴 수 있다. `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304`를 반드시 유지한다. -- DGX Spark 01은 0.24.0 venv toolchain을 사용하므로 `/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin`을 PATH 앞에 둔다. -- DGX Spark 02 Docker image `vllm/vllm-openai:v0.24.0`의 entrypoint는 이미 `vllm serve`이다. container command에는 `serve`를 중복으로 넣지 말고 positional model `/models/gemma-4-26B-A4B-it-NVFP4`부터 둔다. 현재 Docker publish는 host `8004` -> container `8004` 기준이다. -- Gemma4 tool-call/parser profile은 capacity/KV 튜닝과 별개로 agent 동작 가능성을 결정한다. DGX Spark 01은 `/home/digitalcommerce_dgx_spark_01/tool_chat_template_gemma4.jinja`, DGX Spark 02는 `/vllm-workspace/examples/tool_chat_template_gemma4.jinja`를 `--chat-template`로 사용하고, 둘 다 `--enforce-eager --skip-mm-profiling --limit-mm-per-prompt '{"image": 0, "video": 0}' --mm-processor-cache-gb 0 --enable-auto-tool-choice --tool-call-parser gemma4 --reasoning-parser gemma4 --default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. Mac Studio vLLM-MLX는 별도 chat template override 없이 `--continuous-batching --disable-prefix-cache --enable-auto-tool-choice --tool-call-parser gemma4 --reasoning-parser gemma4 --default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. +- capacity/KV 해석 기준은 `agent-test/dev-corp/inventory.yaml`의 `model.capacity_planning_policy`를 우선한다. catalog capacity는 일반 요청 admission/queue target이고, `Maximum concurrency for 262,144 tokens per request`는 full-context upper-bound 진단값이다. capacity `4` 기준 `2.0x`는 lower bound, `2.8x-3.0x`는 운영 target이다. `4.0x` 미만이라는 이유만으로 실패로 보고하지 않되, `2.8x` 미만은 workload-specific smoke 없이 운영 적합으로 보고하지 않는다. +- queue timeout 해석 기준은 `agent-test/dev-corp/inventory.yaml`의 `model.timeout_policy`를 우선한다. provider catalog `queue_timeout_ms=0`은 provider admission queue timeout을 두지 않는다는 뜻이고, adapter instance의 `queue_timeout_ms=1800000`은 backend request budget과 같은 30분 장기 요청 예산이다. +- Historical Spark Gemma4/FP4 profile note: explicit `--max-num-batched-tokens 524288`를 revive하는 경우 first profile 중 FP4 MoE token-per-expert 기본 한계에 걸릴 수 있으므로 `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304`를 유지한다. 현재 Spark Ornith Docker profile의 active capacity source로 취급하지 않는다. +- Historical Spark Gemma4 venv note: DGX Spark 01 Gemma4 0.24.0 venv profile을 revive하는 경우에만 `/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin`을 PATH 앞에 둔다. 현재 Spark Ornith provider는 Docker `vllm/vllm-openai:nightly-aarch64` 기준이다. +- DGX Spark 01/02 Ornith Docker image는 `vllm/vllm-openai:nightly-aarch64`이고 container command에는 `serve`를 중복으로 넣지 않는다. Spark01은 host `8003` -> container `8000`, Spark02는 host `8005` -> container `8000` 기준이다. +- Spark Ornith parser/tool-call profile은 capacity/KV 튜닝과 별개로 agent 동작 가능성을 결정한다. DGX Spark 01/02 Ornith는 `--enable-auto-tool-choice --tool-call-parser qwen3_xml --reasoning-parser qwen3 --trust-remote-code --runner generate`를 둔다. Gemma4는 Mac Studio vLLM-MLX `8004`만 기본 대상으로 하며 별도 chat template override 없이 `--continuous-batching --disable-prefix-cache --enable-auto-tool-choice --tool-call-parser gemma4 --reasoning-parser gemma4 --default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. - 모델별 parser/template 값은 섞지 않는다. Gemma 계열은 `tool_call_parser=gemma4`, `reasoning_parser=gemma4`, Gemma4 tool chat template 또는 vLLM-MLX 기본 template kwargs를 사용한다. Qwen 계열은 dev-runtime 문서의 `tool_call_parser=qwen`, `reasoning_parser=qwen3`, Qwen 전용 chat template 검증값을 따르며 Gemma4 parser/template을 재사용하지 않는다. -- Pi agent dev-corp profile은 `agent-test/dev-corp/inventory.yaml`의 `model.pi_agent_profile`을 기준으로 한다. 2026-07-09 현재 Pi 기본 경로는 Edge OpenAI-compatible alias route인 `dev-corp` / `gemma4:26b` / thinking `high`이고, base URL은 `http://digitalplatform.iop.ai.kr:18086/v1`이다. Mac Studio direct provider `dev-corp-direct` / `mlx-community/gemma-4-26b-a4b-it-nvfp4`와 DGX Spark 01 direct provider `dev-corp-spark01` / `gemma-4-26B-A4B-it-NVFP4`는 non-default direct/fallback profile로 둔다. - Mac Studio는 `DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib` 없이 Python `pyexpat` import가 실패할 수 있다. `screen` session `vllm_mlx_8004` 안에서 이 환경변수를 export한 뒤 시작한다. -- 2026-07-08 재확인 기준 Mac Studio vLLM-MLX는 `/Users/dc_dev/vllm-env-0.4.0/bin/python` 환경의 `vllm-mlx=0.4.0`, `mlx=0.32.0`, `mlx-lm=0.31.3`, `mlx-vlm=0.6.4`, `transformers=5.12.1`, `huggingface-hub=1.22.0`로 동작한다. `--continuous-batching`은 유지하고 `--disable-prefix-cache`를 추가했으며, `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer, Pi `-p` tool-call, Pi TUI 초기 프롬프트 tool-call 로그 종료를 확인했다. -- Mac Studio vLLM-MLX의 현 값은 "구동 가능한 최종 체크포인트"로 취급한다. 추가 미세 조정은 새 포트/새 venv 또는 명시적 rollback 지점을 둔 별도 실험으로만 수행하고, Spark 01/02 vLLM 설정이나 Pi 기본 provider/model을 함께 변경하지 않는다. 알려진 잔여 이슈는 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있는 점이며, 이 경우 serving 옵션을 계속 흔들기보다 Pi extension/provider adapter에서 vLLM-MLX Gemma 전용 sanitizer로 containment 하는 방향을 우선 검토한다. -- 2026-07-08 재확인 기준 DGX Spark 01은 vLLM 0.24.0 text-only/eager profile과 `default_chat_template_kwargs.enable_thinking=true`로 재기동 후 mac-mini 내부 endpoint `http://192.168.2.2:8002`에서 `/health` 200과 `/v1/models`, 직접 API forced/auto/streaming tool-call smoke, 로컬 Pi TUI bash/git-push tool-call 흐름을 통과했고 startup log에서 GPU KV cache `1,453,705` tokens, full-context concurrency `5.55x`를 확인했다. -- 2026-07-08 재확인 기준 DGX Spark 02는 Docker `vllm-gemma4` image `vllm/vllm-openai:v0.24.0`, host/container `8004`, text-only/eager profile과 `default_chat_template_kwargs.enable_thinking=true`로 동작하며 mac-mini와 node-local `/health`, `/v1/models`, 직접 API auto/streaming tool-call smoke를 통과했다. startup log에서 GPU KV cache `1,452,633` tokens, full-context concurrency `5.54x`를 확인했다. +- Mac Studio vLLM-MLX는 `/Users/dc_dev/vllm-env-0.4.0/bin/python` 환경의 `vllm-mlx=0.4.0`, `mlx=0.32.0`, `mlx-lm=0.31.3`, `mlx-vlm=0.6.4`, `transformers=5.12.1`, `huggingface-hub=1.22.0`로 동작한다. `--continuous-batching`은 유지하고 `--disable-prefix-cache`를 추가했으며, `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer를 확인했다. +- Mac Studio vLLM-MLX의 현 값은 "구동 가능한 최종 체크포인트"로 취급한다. 추가 미세 조정은 새 포트/새 venv 또는 명시적 rollback 지점을 둔 별도 실험으로만 수행하고, Spark 01/02 vLLM 설정과 함께 변경하지 않는다. 알려진 잔여 이슈는 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있는 점이며, 이 경우 serving 옵션을 계속 흔들기보다 Edge/provider adapter sanitizer로 containment 하는 방향을 우선 검토한다. +- 2026-07-13 기준 Spark Gemma4 `8002`/`8004` runtime은 내린 상태로 보고, Spark 01/02는 Ornith `8003`/`8005`를 IOP provider로 둔다. Gemma4는 Mac Studio `192.168.2.3:8004` provider만 기본 대상으로 둔다. +- 2026-07-13 재확인 기준 DGX Spark 01 Ornith는 Docker `iop-vllm-ornith35b-fp8`, host `8003`, `--gpu-memory-utilization 0.47`로 동작하며 startup log에서 GPU KV cache `783,347` tokens, full-context concurrency `2.99x`를 확인했다. DGX Spark 02 Ornith는 host `8005`, `--gpu-memory-utilization 0.50`으로 동작하며 GPU KV cache `1,074,276` tokens, full-context concurrency `4.10x`를 확인했다. - 2026-07-02 mac-mini native Control Plane `18002/19004/19005` 관측값은 historical evidence다. 2026-07-09 현재 dev-corp Edge source of truth는 public `iop.ai.kr`이고, current runner에서 public host SSH와 public Control Plane status 접근은 확인되지 않았다. -- 2026-07-09 기준 dev-corp provider-pool Edge OpenAI-compatible capacity smoke 표준은 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions` 15개 동시 요청이다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 성공 기준에서 제외한다. -- 2026-07-09 public Edge 재연결 검증에서 DGX Spark 01/02와 Mac Studio node를 `iop.ai.kr:18087`로 변경한 뒤 `/v1/chat/completions` 15개 동시 요청이 15/15 성공했다. 같은 날 current passthrough source로 public Edge를 재빌드/재시작하고 최신 node 바이너리를 DGX Spark 01/02와 Mac Studio에 배포한 뒤 기본 streaming `/v1/chat/completions` 15/15에서 provider reasoning delta가 유지됐고 transformed `chatcmpl-manual` ID는 0/15였다. 원격 evidence는 `build/dev-corp-runtime/logs/public_latest_edge_node_chat_15_20260709_181222.json`이다. 2026-07-08 `/v1/responses` 통과 기록은 mac-mini provider-pool runtime 기준 legacy evidence로만 본다. +- 2026-07-13 기준 dev-corp provider-pool Edge OpenAI-compatible capacity smoke 표준은 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 성공 기준에서 제외한다. +- 2026-07-13 live status 기준 DGX Spark 01/02와 Mac Studio node는 `iop.ai.kr:18087`로 연결되어 있으며, provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. 같은 날 model-specific smoke에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. ## 실행 절차 @@ -71,7 +73,7 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. - 필수 정보가 없거나 서로 충돌하면 배포를 시작하지 말고 누락/충돌 항목을 보고한다. 2. **provider direct preflight** - - mac-mini에서 DGX Spark 01 `http://192.168.2.2:8002/v1/models`, DGX Spark 02 `http://192.168.2.4:8004/v1/models`, Mac Studio `http://192.168.2.3:8004/v1/models`를 확인한다. + - mac-mini에서 DGX Spark 01 Ornith `http://192.168.2.2:8003/v1/models`, DGX Spark 02 Ornith `http://192.168.2.4:8005/v1/models`, Mac Studio Gemma4 `http://192.168.2.3:8004/v1/models`를 확인한다. - 각 endpoint가 기대 `served_model`을 노출하는지 확인한다. - DGX Spark 02가 provider port down과 SSH banner exchange timeout을 동시에 보이면 runtime 추가 조작을 보류하고, SSH 회복 후 process/log부터 확인한다. - 실패한 provider는 Edge config에 넣지 않거나 배포 blocker로 보고한다. @@ -104,8 +106,8 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. - Edge는 public `iop.ai.kr` host에서 `18085/18086/18087`을 기준으로 재시작/확인한다. mac-mini runner runtime은 dev-corp Edge source of truth가 아니다. - DGX Spark 01/02는 Linux ARM64 node binary를 mac-mini 경유로 배포하고 기존 node process를 재시작한다. - Mac Studio는 macOS node binary를 mac-mini 경유로 배포하고 기존 node process를 재시작한다. - - provider runtime 옵션을 갱신하는 배포라면 DGX Spark 01은 `/home/digitalcommerce_dgx_spark_01/start_vllm_8002.sh`의 `PATH=/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin:$PATH`, `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /home/digitalcommerce_dgx_spark_01/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 확인하고 tmux `vllm_server_8002`를 재기동한다. - - provider runtime 옵션을 갱신하는 배포라면 DGX Spark 02는 Docker container `vllm-gemma4`를 image `vllm/vllm-openai:v0.24.0` entrypoint `vllm serve` 기준으로 재생성한다. container env에는 `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304`를 넣고, container args는 positional model `/models/gemma-4-26B-A4B-it-NVFP4` 뒤에 `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, `--max-num-seqs 4`, `--port 8004`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /vllm-workspace/examples/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. + - provider runtime 옵션을 갱신하는 배포라면 DGX Spark 01은 `/home/digitalcommerce_dgx_spark_01/start_vllm_ornith35b_docker_8003.sh` 기준으로 Docker container `iop-vllm-ornith35b-fp8`를 재생성한다. 핵심 옵션은 `--max-model-len 262144`, `--gpu-memory-utilization 0.47`, `--max-num-seqs 4`, `--port 8000`, `--enable-prefix-caching`, `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`, `--runner generate`이다. + - provider runtime 옵션을 갱신하는 배포라면 DGX Spark 02는 `/home/dplab/start_vllm_ornith35b_docker_8005.sh` 기준으로 Docker container `iop-vllm-ornith35b-fp8`를 재생성한다. 핵심 옵션은 `--max-model-len 262144`, `--gpu-memory-utilization 0.50`, `--max-num-seqs 4`, `--port 8000`, `--enable-prefix-caching`, `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`, `--runner generate`이다. - provider runtime 옵션을 갱신하는 배포라면 Mac Studio는 `screen -dmS vllm_mlx_8004` 안에서 `DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib`를 export한 뒤 `/Users/dc_dev/vllm-env-0.4.0/bin/python -m vllm_mlx.cli serve`를 `--continuous-batching`, `--max-num-seqs 6`, `--prefill-batch-size 6`, `--completion-batch-size 6`, `--chunked-prefill-tokens 1024`, `--disable-prefix-cache`, `--max-kv-size 786432`, `--max-request-tokens 262144`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`로 재기동한다. - Node bootstrap은 Edge의 `node register`가 출력한 OS별 완성 명령을 우선한다. Node `edge_addr`는 `iop.ai.kr:18087`이어야 한다. node-local provider endpoint 또는 별도 `IOP_HOME`이 필요한 경우에는 `~/iop-dev-corp-field/node.yaml`을 수동 배치할 수 있고, token 원문은 로그/보고에 남기지 않는다. @@ -118,12 +120,12 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. 9. **OpenAI-compatible capacity smoke** - `/v1/chat/completions`를 검증한다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 provider-pool capacity 성공 기준에서 제외한다. legacy `/v1/completions`는 route가 구현되어 있지 않으면 실패로 보지 않는다. - 표준 부하 프롬프트는 700~1200 token 수준의 구조화된 답변을 유도해 요청이 동시에 관측될 시간을 만든다. - - endpoint별로 15개 요청을 동시에 보낸다. Edge config에서 기본 dev-corp 후보 capacity `4 + 4 + 5 = 13`을 확정한 경우 15개 동시 호출에서 capacity 초과분 2개 이상이 queue에 잡혀야 한다. - - public Control Plane status가 접근 가능하면 요청 실행 중 반복 polling하여 대상 provider들의 `in_flight` 합이 총 capacity에 도달하고 `queued` 합이 2 이상이 되는 순간을 증거로 남긴다. + - model-specific smoke를 실행한다. `ornith:35b`는 Spark01/02 합산 capacity `8` 기준 9개와 6개 동시 요청을 보내고, `gemma4:26b`는 Mac Studio capacity `5` 기준 9개와 6개 동시 요청을 보낸다. + - Control Plane status가 접근 가능하면 요청 실행 중 반복 polling하여 대상 provider들의 `in_flight`가 각 model capacity에 도달하고 초과 요청이 queue에 들어가는지 증거로 남긴다. 짧은 요청에서는 polling이 queued 순간을 놓칠 수 있으므로 HTTP 성공, max in_flight, 최종 회복을 함께 판정한다. - public Control Plane status가 접근 가능하면 각 provider의 `in_flight`가 자기 capacity를 넘지 않고, 적어도 한 번은 기대 capacity까지 차는지 확인한다. - - public Control Plane status가 접근 가능하면 모든 요청 완료 후 같은 status에서 대상 provider들의 `in_flight=0`, `queued=0`으로 돌아오는지 확인한다. 접근할 수 없으면 HTTP 15/15 결과와 Node 연결 로그만으로 smoke 통과와 capacity snapshot 미관측을 구분한다. + - public Control Plane status가 접근 가능하면 모든 요청 완료 후 같은 status에서 대상 provider들의 `in_flight=0`, `queued=0`으로 돌아오는지 확인한다. 접근할 수 없으면 model-specific HTTP 성공 결과와 Node 연결 로그만으로 smoke 통과와 capacity snapshot 미관측을 구분한다. - Gemma 계열 reasoning/tool-parser 텍스트는 정상 응답으로 허용한다. exact-output match를 smoke 성공 기준으로 삼지 않는다. - - Pi/Cline형 agent/tool-call 경계를 검증할 때는 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 provider direct와 Edge OpenAI-compatible 경로에서 나눠 확인한다. provider direct가 통과하고 Edge 경유만 실패하면 provider runtime option 문제가 아니라 Edge/Node relay 또는 validation 경계 문제로 분리한다. + - agent/tool-call 경계를 검증할 때는 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 provider direct와 Edge OpenAI-compatible 경로에서 나눠 확인한다. provider direct가 통과하고 Edge 경유만 실패하면 provider runtime option 문제가 아니라 Edge/Node relay 또는 validation 경계 문제로 분리한다. 10. **결과 보고** - source ref, clean sync 결과, 테스트 결과, 빌드 산출물, process/port 상태, connected node 목록, provider capacity snapshot, capacity smoke 관측값을 보고한다. @@ -138,7 +140,7 @@ dev-corp provider pool을 현재 dev-runtime과 같은 구조로 배포한다. - [ ] dev-corp Control Plane/Edge/mac/Linux ARM64 binary가 같은 source ref에서 rebuild되었는가 - [ ] 빌드 후 config check, refresh help, refresh dry-run이 통과했는가 - [ ] Edge와 3개 provider node가 재시작되고 connected 상태인가 -- [ ] `/v1/chat/completions` capacity smoke에서 총 capacity만큼 `in_flight`가 차고 초과 요청이 queue에 잡혔는가 +- [ ] `/v1/chat/completions` model-specific capacity smoke에서 각 model/provider capacity까지 `in_flight`가 차고 초과 요청이 queue에 잡혔는가 - [ ] 완료 후 provider `in_flight=0`, `queued=0`으로 회복되었는가 - 검증 실패 시: 실패 단계, 실패한 host/provider/endpoint, 관측된 snapshot, 진행 중단 여부를 보고한다. @@ -166,7 +168,7 @@ dev-corp runtime 배포 결과 - 사용자가 명시적으로 요청하지 않았는데 mac-mini runner/provider 관리 경로를 dev-corp Edge runtime, Node `edge_addr`, bootstrap 기본 URL, OpenAI-compatible base URL로 사용하지 않는다. - `git clean -fdx`를 기본 cleanup으로 사용하지 않는다. - 빌드 전 테스트 실패 후 배포를 계속하지 않는다. -- DGX Spark 02 provider endpoint를 `192.168.2.4:8000`, `8001`, `8002`로 잘못 사용하지 않는다. +- DGX Spark 02 Ornith provider endpoint를 `192.168.2.4:8000`, `8001`, `8002`, `8004`로 잘못 사용하지 않는다. 현재 기본은 `192.168.2.4:8005`이다. - Mac Studio secondary `8005` endpoint를 별도 alias/capacity 결정 없이 기본 provider pool에 포함하지 않는다. - Mac Studio `8004` vLLM-MLX runtime 재시작 방식을 확인하지 않고 provider process를 임의 종료하지 않는다. - node02처럼 tunnel 예외가 필요한 경우를 제외하고 Node bootstrap 기본 경로에서 수동 token 치환, named env parameter, 수동 `node.yaml` 작성을 요구하지 않는다. diff --git a/agent-test/dev-corp/control-plane-smoke.md b/agent-test/dev-corp/control-plane-smoke.md index 446b7bb..14c2941 100644 --- a/agent-test/dev-corp/control-plane-smoke.md +++ b/agent-test/dev-corp/control-plane-smoke.md @@ -67,7 +67,7 @@ last_rule_updated_at: 2026-07-02 - Edge config는 `control_plane.enabled=true`, `wire_addr=127.0.0.1:19005`이며 Edge id는 `dev-corp-edge`다. - `/edges`에서 `dev-corp-edge`가 `connected=true`로 관측된다. - `/edges/dev-corp-edge/status`는 Edge-owned snapshot을 반환하며 3개 provider node의 `provider_snapshots`를 포함한다. 이 status는 provider capacity smoke의 `in_flight`/`queued` evidence 기준이다. -- 2026-07-02 mac-mini runtime capacity smoke에서 `/v1/responses`와 `/v1/chat/completions` 모두 peak total `in_flight=13`, `queued=3`, 완료 후 provider별 `in_flight=0`, `queued=0` 회복을 확인했다. 이 기록은 historical evidence이며, current public Edge provider-pool 표준 smoke는 `/v1/chat/completions`만 사용한다. +- 2026-07-02 mac-mini runtime capacity smoke에서 `/v1/responses`와 `/v1/chat/completions` 모두 peak total `in_flight=13`, `queued=3`, 완료 후 provider별 `in_flight=0`, `queued=0` 회복을 확인했다. 이 기록은 historical evidence이며, current public Edge provider-pool 표준 smoke는 `/v1/chat/completions`에서 model-specific `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청만 사용한다. ## 판정 기준 diff --git a/agent-test/dev-corp/edge-smoke.md b/agent-test/dev-corp/edge-smoke.md index 38d9041..fa11b4a 100644 --- a/agent-test/dev-corp/edge-smoke.md +++ b/agent-test/dev-corp/edge-smoke.md @@ -3,7 +3,7 @@ test_env: dev-corp test_profile: edge-smoke domain: edge verification_type: smoke -last_rule_updated_at: 2026-07-11 +last_rule_updated_at: 2026-07-13 --- # edge-smoke dev-corp 테스트 @@ -56,27 +56,27 @@ dev-corp provider pool과 3-node 연결 상태를 점검할 때는 `agent-test/d - Edge OpenAI-compatible base URL 기본 후보: `http://digitalplatform.iop.ai.kr:18086/v1` - Edge-Node TCP transport 기본 후보: `iop.ai.kr:18087` - mac-mini/internal 후보는 dev-corp Edge 경로가 아니다. Node `edge_addr`는 `iop.ai.kr:18087`이어야 한다. -- model alias 후보: `gemma4:26b` -- host Pi dev-corp profile: `agent-test/dev-corp/inventory.yaml`의 `model.pi_agent_profile` 기준. 2026-07-10 현재 Pi 기본 provider/model/thinking level은 `dev-corp` / `gemma4:26b` / `high`이며, base URL은 public Edge route `http://digitalplatform.iop.ai.kr:18086/v1`이고 sampling parameter는 Pi extension으로 `temperature=0.2`, `top_p=0.95`를 주입한다. dev `qwen3.6:35b` Pi profile은 `agent-test/dev/inventory.yaml`에서 별도로 관리한다. +- model alias 후보: `gemma4:26b`, `ornith:35b` +- provider pool model mapping: `gemma4:26b`는 Mac Studio provider capacity `5`, `ornith:35b`는 Spark01/02 provider 합산 capacity `8`이다. Pi 설정은 이 dev-corp environment smoke 범위에 포함하지 않는다. 노드 후보: - DGX Spark 01 vLLM node: `corp-dgx-spark-01-vllm-node` / `corp-dgx-spark-01-vllm` - SSH/user: mac-mini에서 `ssh digitalcommerce_dgx_spark_01@192.168.2.2` - - provider endpoint: `http://192.168.2.2:8002/v1` - - Edge adapter endpoint: node-local `http://127.0.0.1:8002/v1` + - provider endpoint: `http://192.168.2.2:8003/v1` + - Edge adapter endpoint: node-local `http://127.0.0.1:8003/v1` - Edge connectivity: direct public Edge `iop.ai.kr:18087`. - - served model: `gemma-4-26B-A4B-it-NVFP4` + - served model: `ornith:35b` - capacity baseline 후보: `4` - - runtime: tmux `vllm_server_8002`, start script `/home/digitalcommerce_dgx_spark_01/start_vllm_8002.sh`, `vllm=0.24.0`, `PATH=/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin:$PATH`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /home/digitalcommerce_dgx_spark_01/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`, 2026-07-08 startup log GPU KV cache `1,453,705` tokens / full-context concurrency `5.55x`, `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` + - runtime: Docker container `iop-vllm-ornith35b-fp8`, start script `/home/digitalcommerce_dgx_spark_01/start_vllm_ornith35b_docker_8003.sh`, image `vllm/vllm-openai:nightly-aarch64`, `vllm=0.23.1rc1.dev1042+g8e981630c`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.47`, `--enable-prefix-caching`, `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`, 2026-07-13 startup log GPU KV cache `783,347` tokens / full-context concurrency `2.99x` - DGX Spark 02 vLLM node: `corp-dgx-spark-02-vllm-node` / `corp-dgx-spark-02-vllm` - SSH/user: mac-mini에서 `ssh dplab@192.168.2.4` - - provider endpoint: `http://192.168.2.4:8004/v1` - - Edge adapter endpoint: node-local `http://127.0.0.1:8004/v1` + - provider endpoint: `http://192.168.2.4:8005/v1` + - Edge adapter endpoint: node-local `http://127.0.0.1:8005/v1` - Edge connectivity: direct public Edge `iop.ai.kr:18087`. - - served model: `gemma-4-26B-A4B-it-NVFP4` + - served model: `ornith:35b` - capacity baseline 후보: `4` - - runtime: Docker container `vllm-gemma4`, start script `/home/dplab/start_vllm_gemma4_8004.sh`, host `8004` -> container `8004`, image `vllm/vllm-openai:v0.24.0`, `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /vllm-workspace/examples/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`, 2026-07-08 startup log GPU KV cache `1,452,633` tokens / full-context concurrency `5.54x`, `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` + - runtime: Docker container `iop-vllm-ornith35b-fp8`, start script `/home/dplab/start_vllm_ornith35b_docker_8005.sh`, host `8005` -> container `8000`, image `vllm/vllm-openai:nightly-aarch64`, `vllm=0.23.1rc1.dev1042+g8e981630c`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.50`, `--enable-prefix-caching`, `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`, 2026-07-13 startup log GPU KV cache `1,074,276` tokens / full-context concurrency `4.10x` - Mac Studio vLLM-MLX node: `corp-mac-studio-mlx-vllm-node` / `corp-mac-studio-mlx-vllm` - SSH/user: mac-mini에서 `ssh dc_dev@192.168.2.3` - provider endpoint: `http://192.168.2.3:8004/v1` @@ -91,26 +91,29 @@ Mac Studio의 `http://192.168.2.3:8005/v1` mlx-vlm DiffusionGemma endpoint는 ## provider runtime 설정/검증 상태 -- DGX Spark 01 provider runtime은 capacity `4`, context window `262144`, requested KV `262144x2` 이상의 기준으로 재설정했다. dev-corp DGX01 vLLM 기준으로는 `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, `--enforce-eager`, text-only multimodal limits, `--default-chat-template-kwargs '{"enable_thinking":true}'`, `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` 조합이며, 2026-07-08 startup log에서 GPU KV cache `1,453,705` tokens와 `262144` tokens/request concurrency `5.55x`를 확인했다. -- DGX Spark 02 provider runtime은 capacity `4`, context window `262144`, requested KV `262144x2` 이상의 기준으로 설정됐다. Docker `vllm-gemma4`는 host/container `8004`, image `vllm/vllm-openai:v0.24.0`, text-only/eager, `--default-chat-template-kwargs '{"enable_thinking":true}'` 기준으로 동작하며 2026-07-08 startup log에서 GPU KV cache `1,452,633` tokens와 `262144` tokens/request concurrency `5.54x`를 확인했다. -- DGX Spark 01은 0.24.0 venv의 toolchain을 사용하므로 start script에 `PATH=/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin:$PATH`를 둔다. -- Gemma4 agent/tool-call compatibility profile은 DGX Spark 01/02 vLLM에서 `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, Gemma4 tool chat template, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`을 함께 둔다. Mac Studio vLLM-MLX는 별도 chat template override 없이 `--continuous-batching`, `--disable-prefix-cache`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. Qwen provider는 dev-runtime 문서의 Qwen 전용 parser/template 값을 따른다. -- Mac Studio provider runtime은 `vllm-mlx=0.4.0`, provider catalog capacity `5`, context window `262144`, requested KV `262144x3` 기준으로 `--continuous-batching`, runtime headroom `--max-num-seqs 6`, `--prefill-batch-size 6`, `--completion-batch-size 6`, `--chunked-prefill-tokens 1024`, `--disable-prefix-cache`, `--max-request-tokens 262144`, `--max-kv-size 786432`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 적용했고 `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer, Pi `-p` tool-call, Pi TUI 초기 프롬프트 tool-call 로그 종료를 확인했다. -- Mac Studio vLLM-MLX의 위 값은 2026-07-08 기준 구동 가능한 최종 체크포인트다. 잔여 이슈로 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있으며, 이 경우 runtime option 미세 조정보다 vLLM-MLX Gemma provider 전용 Pi extension/provider adapter sanitizer를 우선 검토한다. 추가 튜닝은 Spark vLLM 설정과 분리된 별도 실험으로만 수행한다. -- 2026-07-08 재확인 기준 DGX Spark 01은 mac-mini 내부 endpoint `http://192.168.2.2:8002`에서 `/health` 200과 `/v1/models`, 직접 API forced/auto/streaming tool-call smoke, 로컬 Pi TUI bash/git-push tool-call 흐름을 통과했다. DGX Spark 02는 mac-mini 내부 endpoint `http://192.168.2.4:8004`에서 `/health` 200과 `/v1/models`, 직접 API auto/streaming tool-call smoke를 통과했다. 이때의 `/v1/responses` capacity 결과는 mac-mini provider-pool runtime 기준 legacy evidence이며, 2026-07-09 public Edge 표준 smoke는 `/v1/chat/completions` 15개 동시 요청이다. -- Gemma provider-pool `gemma4:26b`는 `default_thinking_token_budget: 1024` 기준으로 thinking을 기본 활성화한다. Edge strict output이 켜져 있어도 provider-pool catalog의 thinking policy가 우선하며, vLLM/vLLM-MLX adapter에는 `chat_template_kwargs.enable_thinking=true`로 전달되는지 확인한다. -- Gemma provider를 Pi/Cline형 agent/tool-call 용도로 검증할 때는 일반 chat smoke와 별도로 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 확인한다. raw `<|tool_call>`/`<|"|>` marker나 thought channel text가 assistant content로 새면 provider parser/template profile 또는 Edge relay 경계 문제로 판정한다. -- Gemma provider-pool의 IOP queue timeout은 두지 않는다. config 값은 `queue_timeout_ms=0`이며, caller context cancellation 또는 연결 종료로만 queued request를 중단한다. OpenAI run timeout과 backend request timeout은 long reasoning/long-context 요청을 위해 각각 `openai.timeout_sec=1800`, `request_timeout_ms=1800000`으로 둔다. +- capacity `4`는 `262144` max context 요청 4개가 항상 100% context를 채운다는 보장이 아니다. dev-corp 운영 기준은 일반 호출이 prompt+generated KV 기준으로 max context의 `50-70%`를 사용한다는 가정이다. +- `context_window_max=262144`, `capacity=4`에서 KV `524,288` tokens / full-context concurrency `2.0x`는 lower bound이고, 운영 target은 KV `734,004-786,432` tokens / full-context concurrency `2.8x-3.0x`이다. 이 metric이 catalog capacity `4`보다 작다는 이유만으로 under-capacity로 판정하지 않되, `2.0x-2.8x`는 workload-specific smoke 없이는 운영 적합으로 보지 않는다. +- capacity smoke는 provider admission, queue behavior, health, completion 후 `in_flight=0`/`queued=0` 회복을 검증한다. 모든 capacity slot이 동시에 `262144` tokens를 100% 채울 수 있는지 검증하는 테스트가 아니다. +- DGX Spark 01 provider runtime은 Ornith `8003` 기준으로 capacity `4`, context window `262144`, `--gpu-memory-utilization 0.47`을 사용한다. 2026-07-13 startup log에서 GPU KV cache `783,347` tokens와 `262144` tokens/request concurrency `2.99x`를 확인했고, 이는 capacity/KV 운영 기준에 부합한다. +- DGX Spark 02 provider runtime은 Ornith `8005` 기준으로 capacity `4`, context window `262144`, `--gpu-memory-utilization 0.50`을 사용한다. 2026-07-13 startup log에서 GPU KV cache `1,074,276` tokens와 `262144` tokens/request concurrency `4.10x`를 확인했다. +- Spark의 Gemma4 `8002`/`8004` runtime은 2026-07-13 Ornith IOP provider 전환을 위해 내린 상태로 본다. Gemma4 provider pool은 Mac Studio `192.168.2.3:8004`만 기본 대상으로 둔다. +- Mac Studio vLLM-MLX는 별도 chat template override 없이 `--continuous-batching`, `--disable-prefix-cache`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. Ornith Spark provider는 `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3` 기준이다. Qwen provider는 dev-runtime 문서의 Qwen 전용 parser/template 값을 따른다. +- Mac Studio provider runtime은 `vllm-mlx=0.4.0`, provider catalog capacity `5`, context window `262144`, requested KV `262144x3` 기준으로 `--continuous-batching`, runtime headroom `--max-num-seqs 6`, `--prefill-batch-size 6`, `--completion-batch-size 6`, `--chunked-prefill-tokens 1024`, `--disable-prefix-cache`, `--max-request-tokens 262144`, `--max-kv-size 786432`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 적용했고 `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer를 확인했다. +- Mac Studio vLLM-MLX의 위 값은 구동 가능한 최종 체크포인트로 취급한다. 잔여 이슈로 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있으며, 이 경우 runtime option 미세 조정보다 Edge/provider adapter sanitizer로 containment 하는 방향을 우선 검토한다. 추가 튜닝은 Spark vLLM 설정과 분리된 별도 실험으로만 수행한다. +- Historical only: 2026-07-08 DGX Spark Gemma4 `8002`/`8004` 결과와 2026-07-09 aggregate 15-concurrency 결과는 legacy evidence이며 현재 provider endpoint/표준 smoke가 아니다. 현재 Spark 기본 provider는 Ornith `8003`/`8005`이고, current public Edge 표준 smoke는 2026-07-13 기준 model-specific `/v1/chat/completions` 9/6 동시 요청이다. +- Gemma provider-pool `gemma4:26b`는 Mac Studio vLLM-MLX provider에서 `default_thinking_token_budget: 1024` 기준으로 thinking을 기본 활성화한다. Edge strict output이 켜져 있어도 provider-pool catalog의 thinking policy가 우선하며, vLLM-MLX adapter에는 `chat_template_kwargs.enable_thinking=true`로 전달되는지 확인한다. +- Gemma provider를 agent/tool-call 용도로 검증할 때는 일반 chat smoke와 별도로 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 확인한다. raw `<|tool_call>`/`<|"|>` marker나 thought channel text가 assistant content로 새면 provider parser/template profile 또는 Edge relay 경계 문제로 판정한다. +- provider catalog의 admission queue timeout은 두지 않는다. provider catalog `queue_timeout_ms=0`이고, Node `openai_compat_instances` adapter queue/request budget은 long reasoning/long-context 요청을 위해 `queue_timeout_ms=1800000`, `request_timeout_ms=1800000`으로 둔다. OpenAI run timeout은 `openai.timeout_sec=1800`이다. ## 2026-07-09 dev-corp public Edge runtime 상태 - Active Edge runtime is `iop.ai.kr` (`115.21.224.82`) with public `18085` bootstrap, `18086` OpenAI-compatible, and `18087` Edge-Node TCP. - mac-mini checkout/runtime is a runner and must not be used as Edge source of truth unless explicitly doing a local-runner comparison. -- On 2026-07-09 the three provider nodes were moved from mac-mini/reverse-tunnel Edge addresses to `iop.ai.kr:18087`, and public `/v1/chat/completions` 15-concurrency smoke passed 15/15. -- On 2026-07-09 after rebuilding the public Edge from the current passthrough source, default streaming `/v1/chat/completions` preserved provider reasoning deltas for 15/15 concurrent requests; transformed `chatcmpl-manual` IDs were 0/15. Evidence: `build/dev-corp-runtime/logs/public_passthrough_chat_15_20260709_180115.json`. -- On 2026-07-09 after deploying latest node binaries to DGX Spark 01/02 and Mac Studio, public streaming `/v1/chat/completions` again passed 15/15 with provider reasoning deltas preserved and transformed `chatcmpl-manual` IDs 0/15. Evidence: `build/dev-corp-runtime/logs/public_latest_edge_node_chat_15_20260709_181222.json`. +- On 2026-07-09 the three provider nodes were moved from mac-mini/reverse-tunnel Edge addresses to `iop.ai.kr:18087`; the public `/v1/chat/completions` aggregate 15-concurrency smoke passed 15/15 and is retained as historical routing evidence. +- On 2026-07-09 after rebuilding the public Edge from the current passthrough source, default streaming `/v1/chat/completions` preserved provider reasoning deltas for 15/15 historical aggregate concurrent requests; transformed `chatcmpl-manual` IDs were 0/15. Evidence: `build/dev-corp-runtime/logs/public_passthrough_chat_15_20260709_180115.json`. +- On 2026-07-09 after deploying latest node binaries to DGX Spark 01/02 and Mac Studio, public streaming `/v1/chat/completions` again passed 15/15 historical aggregate concurrency with provider reasoning deltas preserved and transformed `chatcmpl-manual` IDs 0/15. Evidence: `build/dev-corp-runtime/logs/public_latest_edge_node_chat_15_20260709_181222.json`. - Mac Studio provider catalog `type`은 최신 config validator 기준으로 `openai_compat`를 사용한다. 실제 provider runtime은 vLLM-MLX이고 `runtime_type: vllm-mlx`로 추적한다. -- `/v1/chat/completions` capacity smoke 표준: 15개 동시 요청을 public `http://digitalplatform.iop.ai.kr:18086/v1`로 보낸다. 2026-07-09 public Edge 재연결 검증에서는 15/15 성공했다. +- `/v1/chat/completions` capacity smoke 표준: public `http://digitalplatform.iop.ai.kr:18086/v1`에서 `ornith:35b`는 9개/6개 동시 요청, `gemma4:26b`는 9개/6개 동시 요청을 확인한다. 2026-07-13 live smoke에서는 네 시나리오 모두 성공했고 완료 후 provider `in_flight=0`, `queued=0`, `healthy`로 회복했다. - `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 provider-pool capacity 성공 기준에서 제외한다. ## 명령 @@ -120,8 +123,8 @@ Mac Studio의 `http://192.168.2.3:8005/v1` mlx-vlm DiffusionGemma endpoint는 - unit: `go test ./apps/edge/...` - smoke: `./scripts/e2e-smoke.sh`는 기본 포트 임시 설정을 쓰는 보조 smoke이므로 dev-corp 포트 override 필요 여부를 먼저 확인한다. - e2e: `make test-e2e`는 보조 smoke이며 full-cycle 실제 구동을 대체하지 않는다. -- model: dev-corp OpenAI-compatible profile을 띄운 경우 `OPENAI_API_KEY=$(cat build/dev-corp-runtime/.secrets/openai_api_key) iop-edge smoke openai --model gemma4:26b --base-url http://digitalplatform.iop.ai.kr:18086` -- direct-provider: mac-mini에서 `curl -fsS http://192.168.2.2:8002/v1/models`, `curl -fsS http://192.168.2.4:8004/v1/models`, `curl -fsS http://192.168.2.3:8004/v1/models` +- model: dev-corp OpenAI-compatible profile을 띄운 경우 `gemma4:26b`와 `ornith:35b`를 각각 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`로 확인한다. +- direct-provider: mac-mini에서 `curl -fsS http://192.168.2.2:8003/v1/models`, `curl -fsS http://192.168.2.4:8005/v1/models`, `curl -fsS http://192.168.2.3:8004/v1/models` - full-cycle: repo 내부 edge-node 진단, `iop-edge smoke openai`, OpenAI-compatible 입력 표면 수동 검증 ## 필수 검증 @@ -144,15 +147,15 @@ Mac Studio의 `http://192.168.2.3:8005/v1` mlx-vlm DiffusionGemma endpoint는 - node 로컬 `[node-message]` payload 라인 목록과 edge `[node-*-message]` payload 라인 목록이 run별로 내용/순서까지 동일해야 한다. - edge complete는 같은 run의 마지막 `[node-*-message]` 이후에만 정상이다. - OpenAI-compatible smoke에서 `/healthz`, `/v1/models`, `/v1/chat/completions`가 기대 상태로 응답한다. provider-pool `/v1/responses`는 현재 미지원이다. -- dev-corp provider-pool capacity smoke는 현재 `/v1/chat/completions`에 15개 동시 요청을 보낸다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 capacity 성공 기준에서 제외한다. +- dev-corp provider-pool capacity smoke는 현재 `/v1/chat/completions`에 model-specific 동시 요청을 보낸다. 표준 시나리오는 `ornith:35b` 9/6, `gemma4:26b` 9/6이다. `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 capacity 성공 기준에서 제외한다. - capacity smoke 완료 후 대상 provider의 `in_flight=0`, `queued=0` 회복을 확인한다. - Gemma 계열 provider-pool smoke는 thinking enabled 기준이며 reasoning/tool-parser 관련 텍스트가 포함될 수 있다. exact-output match를 기본 판정으로 쓰지 않는다. ## 기준 출력 예시 ```text -curl -fsS http://192.168.2.2:8002/v1/models -curl -fsS http://192.168.2.4:8004/v1/models +curl -fsS http://192.168.2.2:8003/v1/models +curl -fsS http://192.168.2.4:8005/v1/models curl -fsS http://192.168.2.3:8004/v1/models ``` @@ -160,7 +163,7 @@ curl -fsS http://192.168.2.3:8004/v1/models - mac-mini host 또는 Edge-Node TCP 후보 port 접근이 불가능하다. - mac-mini에 `/Users/fe/agent-work/iop-dev-corp` checkout이 없어 dev-corp runtime artifact를 만들 수 없다. -- provider endpoint `192.168.2.2:8002`, `192.168.2.4:8004`, `192.168.2.3:8004` 중 필수 endpoint가 닫혀 있다. +- provider endpoint `192.168.2.2:8003`, `192.168.2.4:8005`, `192.168.2.3:8004` 중 필수 endpoint가 닫혀 있다. - 외부 CLI profile 검증에 필요한 CLI 설치, 계정, provider 상태가 없다. - dev-corp 포트가 local/test/dev baseline과 충돌한다. diff --git a/agent-test/dev-corp/inventory.yaml b/agent-test/dev-corp/inventory.yaml index 3081274..62ac163 100644 --- a/agent-test/dev-corp/inventory.yaml +++ b/agent-test/dev-corp/inventory.yaml @@ -54,7 +54,7 @@ edge: - corp-dgx-spark-01-vllm-node - corp-dgx-spark-02-vllm-node - corp-mac-studio-mlx-vllm-node - public_chat_completions_15: + public_chat_completions_15_historical_routing_evidence: ok: 15 concurrent_requests: 15 elapsed_sec: 5.678 @@ -104,25 +104,69 @@ build: model: alias: gemma4:26b - alias_status: candidate - alias_policy: expose one IOP model alias and map provider-specific served_model values per provider + alias_status: active_multi_model_pool_primary_alias + primary_alias: gemma4:26b + additional_aliases: + - ornith:35b + alias_policy: expose IOP model aliases per served model and map each alias to its current device/provider pool. provider_capacity_total: 13 - provider_capacity_status: verified_with_control_plane_provider_snapshots_2026_07_08_15_concurrency + provider_capacity_status: verified_with_control_plane_provider_snapshots_2026_07_13_device_sync + aliases: + gemma4:26b: + capacity_total: 5 + providers: + - corp-mac-studio-mlx-vllm + served_model: mlx-community/gemma-4-26b-a4b-it-nvfp4 + device_policy: served only from Mac Studio in current dev-corp provider pool. + default_thinking_token_budget: 1024 + reasoning_policy: bounded_thinking_enabled + think_policy: + default: enabled + strict_output_behavior: provider_pool_catalog_default_overrides_strict_disable + adapter_mapping: vllm_mlx_uses_chat_template_kwargs_enable_thinking_true + ornith:35b: + capacity_total: 8 + providers: + - corp-dgx-spark-01-ornith + - corp-dgx-spark-02-ornith + served_model: ornith:35b + device_policy: served from Spark01 and Spark02 in current dev-corp provider pool. + default_thinking_token_budget: null + reasoning_policy: reasoning_parser_enabled_without_catalog_thinking_budget + think_policy: + default: provider_runtime_default + adapter_mapping: qwen3_reasoning_parser_without_model_catalog_thinking_budget context_window_max: 262144 - default_thinking_token_budget: 1024 - reasoning_policy: bounded_thinking_enabled - think_policy: - default: enabled - strict_output_behavior: provider_pool_catalog_default_overrides_strict_disable - adapter_mapping: vllm_and_vllm_mlx_use_chat_template_kwargs_enable_thinking_true - direct_ornith_profile: + thinking_policy_scope: per_alias + capacity_planning_policy: observed_at: "2026-07-13" - status: active_direct_only_via_mac_mini_port_forward_not_iop_connected + applies_to: + - gemma4:26b + - ornith:35b + max_context_tokens: 262144 + catalog_capacity_meaning: provider admission/concurrency target for typical requests, not a guarantee that every admitted request consumes 100% of max context. + typical_request_context_ratio_of_max: "0.50-0.70" + typical_request_context_scope: prompt tokens plus generated tokens that occupy KV cache during the request. + kv_lower_bound_ratio_per_capacity_slot: "0.50" + kv_operating_target_ratio_per_capacity_slot: "0.70-0.75" + full_context_concurrency_metric: "vLLM startup Maximum concurrency for 262,144 tokens per request is a diagnostic upper-bound metric, not the catalog capacity requirement." + capacity_4: + lower_bound_kv_tokens: 524288 + lower_bound_full_context_concurrency: 2.00 + operating_target_kv_tokens_min: 734004 + operating_target_kv_tokens_max: 786432 + operating_target_full_context_concurrency_min: 2.80 + operating_target_full_context_concurrency_max: 3.00 + interpretation: capacity 4 is operationally suitable when runtime KV covers roughly 2.8x-3.0x full 262144-token requests; 2.0x-2.8x is only a lower-bound/test-line range and should not be described as covering four 70% context requests. + operating_note: Do not mark a provider under-capacity solely because full-context concurrency is below catalog capacity; for capacity 4, prefer 2.8x-3.0x full-context concurrency and treat 2.0x as the minimum lower bound requiring workload-specific smoke evidence. + spark_ornith_profile: + observed_at: "2026-07-13" + status: active_iop_provider_pool_and_direct_test_lines family: spark_ornith model_id: ornith:35b - display_name: Ornith 1.0 35B FP8 Direct vLLM + display_name: Ornith 1.0 35B FP8 vLLM api: openai-completions - route_policy: Spark Ornith endpoints are direct-only until the separate IOP connection step; do not add them to the dev-corp Edge/provider pool from this inventory entry alone. + route_policy: Spark Ornith endpoints are connected to the dev-corp Edge/provider pool as IOP providers; device inventory uses provider-internal endpoints and node-local Edge adapter endpoints only. upstream_model: deepreinforce-ai/Ornith-1.0-35B-FP8 upstream_url: https://huggingface.co/deepreinforce-ai/Ornith-1.0-35B-FP8 upstream_revision: 1ab57ce0b44950e498a88756f40ad1ed4d0f30ca @@ -142,39 +186,37 @@ model: language_model_only_equivalent: runner_generate endpoints: spark01: - provider: dev-corp-spark01-ornith + provider: corp-dgx-spark-01-ornith endpoint: http://192.168.2.2:8003/v1 - pi_forward_base_url_current_host: http://172.24.63.178:18003/v1 - pi_forward_base_url_runner: http://127.0.0.1:18003/v1 + edge_adapter_endpoint: http://127.0.0.1:8003/v1 health: http://192.168.2.2:8003/health container_name: iop-vllm-ornith35b-fp8 start_script: /home/digitalcommerce_dgx_spark_01/start_vllm_ornith35b_docker_8003.sh host_port: 8003 container_port: 8000 - gpu_memory_utilization: 0.46 - gpu_memory_utilization_note: Document baseline 0.50 was attempted but failed while preserving Gemma4 8002 because startup free GPU memory 56.02GiB was below the 59.85GiB reservation; KV cache was reduced through gpu_memory_utilization only. + gpu_memory_utilization: 0.47 + gpu_memory_utilization_note: 2026-07-13 single-node test selected 0.47; 0.50 failed KV init, 0.40 yielded 369057 KV tokens and 1.41x full-context concurrency, and 0.47 yielded 783347 KV tokens and 2.99x full-context concurrency. Under capacity_planning_policy this satisfies the capacity 4 operating target because it is about 74.7% KV per slot, near the 70-75% target, without requiring 4.0x full 262144-token requests. hf_home: /models/.cache/huggingface host_model_root: /home/digitalcommerce_dgx_spark_01/Data/models model_load_memory_gib: 34.9 - gpu_kv_cache_tokens: 857365 - max_concurrency_for_262144_token_requests: 3.27 + gpu_kv_cache_tokens: 783347 + max_concurrency_for_262144_token_requests: 2.99 verification: - gemma4_8002_health: passed + gemma4_8002_status: stopped_2026_07_13_for_spark_ornith_iop_provider_pool ornith_8003_health: passed models_endpoint: ornith:35b direct_chat_completion: passed - pi_direct_print: PI_SPARK01_ORNITH_OK spark02: - provider: dev-corp-spark02-ornith + provider: corp-dgx-spark-02-ornith endpoint: http://192.168.2.4:8005/v1 - pi_forward_base_url_current_host: http://172.24.63.178:18005/v1 - pi_forward_base_url_runner: http://127.0.0.1:18005/v1 + edge_adapter_endpoint: http://127.0.0.1:8005/v1 health: http://192.168.2.4:8005/health container_name: iop-vllm-ornith35b-fp8 start_script: /home/dplab/start_vllm_ornith35b_docker_8005.sh host_port: 8005 container_port: 8000 gpu_memory_utilization: 0.50 + gpu_memory_utilization_note: 0.50 remains above the capacity 4 operating target because startup observed 1074276 KV tokens and 4.10x full-context concurrency. hf_home: /models/.cache/huggingface host_model_root: /home/dplab/Data/models cache_source: copied_from_spark01_ornith_hf_cache_after_slow_hf_download @@ -183,295 +225,165 @@ model: max_concurrency_for_262144_token_requests: 4.10 north_runtime_status: stopped_2026_07_12_for_ornith_direct_memory_headroom verification: - gemma4_8004_health: passed + gemma4_8004_status: stopped_2026_07_13_for_spark_ornith_iop_provider_pool ornith_8005_health: passed models_endpoint: ornith:35b direct_chat_completion: passed - pi_direct_print: PI_SPARK02_ORNITH_OK - pi_direct_profile: - observed_at: "2026-07-13" - config_scope: host_local_pi_agent - default_provider: dev-corp-spark01-ornith - default_model: ornith:35b - default_thinking_level: high - route_policy: current host Pi must use the mac-mini 172.24.63.178 port-forward endpoints, not the provider-internal 192.168.2.x addresses. - port_forward: - runner: fe@172.24.63.178 - script: /Users/fe/server/start_port_forward.sh - restart_command: cd ~/server && ./start_port_forward.sh spark_01 && ./start_port_forward.sh spark_02 - sshpass_path_note: non-login SSH uses /opt/homebrew/bin/sshpass fallback in the script. - forwards: - spark01: - provider: dev-corp-spark01-ornith - current_host_base_url: http://172.24.63.178:18003/v1 - runner_local_base_url: http://127.0.0.1:18003/v1 - provider_internal_base_url: http://192.168.2.2:8003/v1 - spark02: - provider: dev-corp-spark02-ornith - current_host_base_url: http://172.24.63.178:18005/v1 - runner_local_base_url: http://127.0.0.1:18005/v1 - provider_internal_base_url: http://192.168.2.4:8005/v1 - validation: - current_host_models: - spark01: ornith:35b - spark02: ornith:35b - current_host_chat_completions_no_thinking: - spark01: ORNITH_OK - spark02: ORNITH_OK - pi_direct_print: PI_ORNITH_172_OK - enabled_model_patterns: - - dev-corp-spark02-ornith/* - - dev-corp-spark01-ornith/* - - dev-corp-direct/** - - dev-corp-spark01/** - - dev-corp/* - providers: - dev-corp-spark01-ornith: - base_url: http://172.24.63.178:18003/v1 - provider_internal_base_url: http://192.168.2.2:8003/v1 - model_id: ornith:35b - dev-corp-spark02-ornith: - base_url: http://172.24.63.178:18005/v1 - provider_internal_base_url: http://192.168.2.4:8005/v1 - model_id: ornith:35b - api_key_value_tracked: false - iop_connection_status: not_connected_pending_separate_step - pi_agent_profile: - observed_at: "2026-07-13" - config_scope: host_local_pi_agent - config_dir: ~/.pi/agent - install: - package: pi-coding-agent - version: 0.80.3 - binary: /opt/homebrew/bin/pi - settings_file: ~/.pi/agent/settings.json - models_file: ~/.pi/agent/models.json - extension_files: - - ~/.pi/agent/extensions/dev-corp-temperature.ts - profile_namespace: dev_corp_spark_ornith_pi - current_default_provider: dev-corp-spark01-ornith - current_default_model: ornith:35b - current_default_runtime: spark_ornith_direct_via_mac_mini_port_forward - current_default_base_url: http://172.24.63.178:18003/v1 - current_default_api: openai-completions - current_default_auth_header: true - current_default_thinking_level: high - current_default_temperature: null - current_default_top_p: null - current_default_sampling_parameter_source: none_for_direct_ornith - edge_provider_pool_fallback: - provider: dev-corp - model_id: gemma4:26b - base_url: http://digitalplatform.iop.ai.kr:18086/v1 - sampling_parameter_source: before_provider_request extension dev-corp-temperature.ts - hide_thinking_block: false - http_idle_timeout_ms: 300000 - retry_provider_timeout_ms: 300000 - retry_provider_max_retries: 0 - retry_provider_max_retry_delay_ms: 60000 - enabled_model_patterns: - - dev-corp-spark02-ornith/* - - dev-corp-spark01-ornith/* - - dev-corp-direct/** - - dev-corp-spark01/** - - dev-corp/* - extensions: - - path: ~/.pi/agent/extensions/dev-corp-temperature.ts - registered_in_settings: extensions/dev-corp-temperature.ts - hook: before_provider_request - scope: dev-corp provider only - effect: inject temperature 0.2 and top_p 0.95 into provider request payload - api_key_value_tracked: false - route_policy: current dev-corp Pi default uses mac-mini 172.24.63.178 port-forward endpoints for Spark Ornith direct; public Edge dev-corp/gemma4 remains a separate fallback provider profile. - pi_model_parameters: - provider: dev-corp-spark01-ornith - model_id: ornith:35b - display_name: dev-corp Spark 01 Ornith 1.0 35B FP8 - api: openai-completions - context_window: 262144 - max_tokens: 32768 - reasoning: true - thinking_level: high - request_temperature: null - request_top_p: null - sampling_parameter_source: none_for_direct_ornith - expected_iop_thinking_token_budget: null - compat: - supports_developer_role: false - supports_usage_in_streaming: false - max_tokens_field: max_tokens - supports_reasoning_effort: false - supports_strict_mode: true - supports_store: false - requires_tool_result_name: true - requires_assistant_after_tool_result: true - direct_provider_profiles: - mac_studio_vllm_mlx: - provider: dev-corp-direct - default_provider: false - base_url: http://172.24.63.178:8004/v1 - served_model: mlx-community/gemma-4-26b-a4b-it-nvfp4 - runtime: mac_studio_vllm_mlx - compat: - supports_strict_mode: true - thinking_format: chat-template - chat_template_kwargs: - enable_thinking: thinking.enabled - dgx_spark_01_vllm: - provider: dev-corp-spark01 - default_provider: false - base_url: http://127.0.0.1:8002/v1 - served_model: gemma-4-26B-A4B-it-NVFP4 - runtime: dgx_spark_01_vllm - route_note: host-local direct or tunnel route only; keep as fallback and do not treat it as the Edge alias route - compat: - supports_strict_mode: true - thinking_format: chat-template - chat_template_kwargs: - enable_thinking: thinking.enabled - dgx_spark_01_ornith_direct: - provider: dev-corp-spark01-ornith - default_provider: true - base_url: http://172.24.63.178:18003/v1 - provider_internal_base_url: http://192.168.2.2:8003/v1 - served_model: ornith:35b - runtime: dgx_spark_01_ornith_direct - route_note: direct-only Pi provider before IOP connection; current host reaches it through mac-mini port-forward, not the provider-internal 192.168.2.x address - compat: - supports_strict_mode: true - supports_developer_role: false - supports_usage_in_streaming: false - supports_reasoning_effort: false - supports_store: false - max_tokens_field: max_tokens - requires_tool_result_name: true - requires_assistant_after_tool_result: true - dgx_spark_02_ornith_direct: - provider: dev-corp-spark02-ornith - default_provider: false - base_url: http://172.24.63.178:18005/v1 - provider_internal_base_url: http://192.168.2.4:8005/v1 - served_model: ornith:35b - runtime: dgx_spark_02_ornith_direct - route_note: direct-only Pi provider before IOP connection; current host reaches it through mac-mini port-forward, and Spark02 North was stopped for memory headroom while Gemma4 8004 remained healthy - compat: - supports_strict_mode: true - supports_developer_role: false - supports_usage_in_streaming: false - supports_reasoning_effort: false - supports_store: false - max_tokens_field: max_tokens - requires_tool_result_name: true - requires_assistant_after_tool_result: true - runtime_parameter_alignment: - alignment_policy: Pi model parameters must be kept in sync with the dev-corp Edge model alias, provider served_model values, context/output limits, Gemma parser/template policy, and provider capacity/sequence limits. Do not optimize or debug Pi behavior from the endpoint URL alone. - common_requirements: - model_alias: gemma4:26b - pi_context_window: 262144 - edge_context_window: 262144 - pi_max_tokens: 32768 - provider_default_max_tokens: 32768 - pi_temperature: 0.2 - pi_top_p: 0.95 - pi_reasoning: true - edge_reasoning_policy: bounded_thinking - edge_default_thinking_token_budget: 1024 - required_template_policy: Gemma providers keep default_chat_template_kwargs.enable_thinking=true - required_tool_call_parser: gemma4 - required_reasoning_parser: gemma4 - engine_matrix: - dgx_spark_01_vllm: - runtime_type: vllm - served_model: gemma-4-26B-A4B-it-NVFP4 - context_match: pi contextWindow 262144 maps to vLLM max_model_len 262144 - output_budget_match: pi maxTokens 32768 maps to provider default max tokens 32768 - thinking_match: pi reasoning=true and thinking_level=high map to reasoning_parser=gemma4, default_chat_template_kwargs.enable_thinking=true, and IOP thinking token budget 1024 - concurrency_match: provider capacity 4 maps to runtime max_num_seqs 4 - tool_parser_profile: gemma4 - dgx_spark_02_vllm: - runtime_type: vllm - served_model: gemma-4-26B-A4B-it-NVFP4 - context_match: pi contextWindow 262144 maps to vLLM max_model_len 262144 - output_budget_match: pi maxTokens 32768 maps to provider default max tokens 32768 - thinking_match: pi reasoning=true and thinking_level=high map to reasoning_parser=gemma4, default_chat_template_kwargs.enable_thinking=true, and IOP thinking token budget 1024 - concurrency_match: provider capacity 4 maps to runtime max_num_seqs 4 - tool_parser_profile: gemma4 - mac_studio_vllm_mlx: - runtime_type: vllm-mlx - served_model: mlx-community/gemma-4-26b-a4b-it-nvfp4 - context_match: pi contextWindow 262144 maps to vLLM-MLX max_request_tokens 262144 and max_kv_size 786432 - output_budget_match: pi maxTokens 32768 maps to provider default max tokens 32768 - thinking_match: pi reasoning=true and thinking_level=high map to reasoning_parser=gemma4, default_chat_template_kwargs.enable_thinking=true, and IOP thinking token budget 1024 - concurrency_match: provider catalog capacity 5 maps to runtime headroom max_num_seqs 6 - tool_parser_profile: gemma4 - separation_note: This profile is for dev-corp Gemma4 Pi only. Keep dev Qwen3.6 Pi settings under agent-test/dev/inventory.yaml and do not copy Qwen parser/template/runtime assumptions into this Gemma profile or Gemma parser/template values into Qwen providers. + iop_connection_status: connected_as_dev_corp_edge_provider_pool timeout_policy: openai_timeout_sec: 1800 - provider_queue_timeout_ms: 0 - provider_queue_timeout_policy: disabled_no_iop_queue_timeout + adapter_queue_timeout_ms: 1800000 + provider_catalog_queue_timeout_ms: 0 + provider_catalog_queue_timeout_policy: disabled_no_provider_admission_queue_timeout backend_request_timeout_ms: 1800000 - note: provider-pool long reasoning and long-context requests do not use an IOP queue timeout; backend/OpenAI run budgets remain 30 minutes + note: provider catalog queue timeout is disabled with queue_timeout_ms=0, while openai_compat adapter instances keep a 30 minute queue/request budget for long reasoning and long-context traffic. runtime_capacity_targets: dgx_spark: capacity: 4 context_window_max: 262144 - kv_size_tokens_effective: 524288 - kv_size_basis: requested minimum 262144x2; verify actual vLLM KV cache from startup log because gpu_memory_utilization controls available KV cache - fp4_moe_env: VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304 + typical_request_context_ratio_of_max: "0.50-0.70" + typical_request_context_scope: prompt plus generated tokens + kv_lower_bound_ratio_per_capacity_slot: "0.50" + kv_operating_target_ratio_per_capacity_slot: "0.70-0.75" + kv_lower_bound_tokens: 524288 + kv_operating_target_tokens_min: 734004 + kv_operating_target_tokens_max: 786432 + lower_bound_full_context_concurrency: 2.00 + operating_target_full_context_concurrency_min: 2.80 + operating_target_full_context_concurrency_max: 3.00 + kv_size_basis: catalog capacity 4 assumes typical requests use 50-70% of max context including generated tokens; 50% KV per slot is a lower bound, while the operating target is 70-75% of four 262144-token slots. Verify actual vLLM KV cache from startup log because gpu_memory_utilization controls available KV cache. + full_context_concurrency_note: startup full-context concurrency below 4.0x is not under-capacity by itself, but capacity 4 should prefer 2.8x-3.0x; 2.0x-2.8x requires workload-specific smoke evidence before calling it operationally suitable. + legacy_fp4_moe_env_for_spark_gemma4_restore: VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304 mac_studio: capacity: 5 context_window_max: 262144 + kv_lower_bound_ratio_per_capacity_slot: "0.50" + kv_operating_target_ratio_per_capacity_slot: "0.70-0.75" kv_size_tokens_effective: 786432 - kv_size_basis: requested 262144x3 mapped to vLLM-MLX max_kv_size + kv_size_planning_ratio_per_slot: 0.60 + kv_size_basis: requested 262144x3 mapped to vLLM-MLX max_kv_size; for catalog capacity 5 this is 60% KV per slot, above the lower bound but below the 70-75% operating target, so capacity 5 should be read as admission/test-line capacity unless workload smoke confirms the expected context mix. capacity_smoke: endpoints: - /v1/chat/completions unsupported_endpoints: /v1/responses: OpenAI-compatible provider model group raw passthrough parity 전까지 미지원 - concurrent_requests: 15 - expected_total_in_flight: 13 - expected_total_in_flight_status: public_control_plane_status_required_for_current_snapshot; legacy_verified_15_concurrency_2026_07_08 - expected_min_queued: 2 - previous_capacity_plus_one_concurrent_requests: 14 - previous_capacity_plus_one_expected_min_queued: 1 + aggregate_provider_capacity: 13 + model_scenarios: + ornith_9: + model: ornith:35b + concurrent_requests: 9 + expected_max_in_flight: 8 + queue_observation: overflow request may queue briefly; do not fail the smoke solely because polling misses the queued moment. + ornith_6: + model: ornith:35b + concurrent_requests: 6 + expected_max_in_flight: 6 + queue_observation: not_expected + gemma4_9: + model: gemma4:26b + concurrent_requests: 9 + expected_max_in_flight: 5 + queue_observation: overflow requests should queue when polling catches the capacity window. + gemma4_6: + model: gemma4:26b + concurrent_requests: 6 + expected_max_in_flight: 5 + queue_observation: overflow request may queue briefly; do not fail the smoke solely because polling misses the queued moment. prompt_policy: long_reasoning_allowed - think_policy: enabled_for_provider_pool + think_policy: per_alias_provider_defaults exact_output_match: false + capacity_interpretation: capacity smoke validates provider admission, queue behavior, health, and recovery for typical prompts; it does not require every catalog capacity slot to hold a full 262144-token request at the same time, but capacity 4 runtime suitability should prefer the 70-75% KV operating target. latest_capacity_verification: - date: "2026-07-09" + date: "2026-07-13" route: public_digitalplatform_edge host: iop.ai.kr edge_addr: iop.ai.kr:18087 - source_ref: e8c240ea23a29f1568326b6d162913863b3dca33 - default_thinking_token_budget: 1024 - control_plane_enabled: unknown - control_plane_status_url: http://iop.ai.kr:18002/edges/dev-corp-edge/status - capacity_snapshot_observed: false - capacity_snapshot_note: public Control Plane status was not accessible from the current runner; HTTP 15/15 smoke and node connection logs are current evidence, while in_flight/queued snapshot evidence remains legacy 2026-07-08 mac-mini runtime data. - runtime: - runner_checkout: /Users/fe/agent-work/iop-dev-corp - remote_log: build/dev-corp-runtime/logs/public_latest_edge_node_chat_15_20260709_181222.json + source_ref: live_dev_corp_runtime + thinking_policy: + gemma4:26b: + default_thinking_token_budget: 1024 + ornith:35b: + default_thinking_token_budget: null + control_plane_enabled: true + control_plane_status_url_remote: http://127.0.0.1:18002/edges/dev-corp-edge/status + control_plane_public_status_url: http://iop.ai.kr:18002/edges/dev-corp-edge/status + capacity_snapshot_observed: true + capacity_snapshot_note: public 18002 was not reachable from the current runner, but Edge host local Control Plane status over SSH returned provider_snapshots during the 2026-07-13 model-specific concurrency smokes. node_connection: node_edge_addr: iop.ai.kr:18087 - moved_from: - - retired reverse tunnel route - - retired mac-mini local route nodes_registered: - corp-dgx-spark-01-vllm-node - corp-dgx-spark-02-vllm-node - corp-mac-studio-mlx-vllm-node + provider_snapshot_baseline: + corp-dgx-spark-01-ornith: + capacity: 4 + health: healthy + served_models: + - ornith:35b + corp-dgx-spark-02-ornith: + capacity: 4 + health: healthy + served_models: + - ornith:35b + corp-mac-studio-mlx-vllm: + capacity: 5 + health: healthy + served_models: + - mlx-community/gemma-4-26b-a4b-it-nvfp4 chat_completions: - concurrent_requests: 15 - ok: 15 - timeout_errors: 0 - http_errors: 0 - elapsed_sec: 5.678 - request_median_sec: 2.98 - passthrough_reasoning_stream_seen: 15 - transformed_manual_id_count: 0 + ornith_9: + model: ornith:35b + concurrent_requests: 9 + ok: 9 + http_200: 9 + finish_reason: stop + provider_max: + corp-dgx-spark-01-ornith: + max_in_flight: 4 + max_queued: 0 + corp-dgx-spark-02-ornith: + max_in_flight: 4 + max_queued: 0 + final_recovery: in_flight_0_queued_0_healthy + ornith_6: + model: ornith:35b + concurrent_requests: 6 + ok: 6 + http_200: 6 + finish_reason: stop + provider_max: + corp-dgx-spark-01-ornith: + max_in_flight: 3 + max_queued: 0 + corp-dgx-spark-02-ornith: + max_in_flight: 3 + max_queued: 0 + final_recovery: in_flight_0_queued_0_healthy + gemma4_9: + model: gemma4:26b + concurrent_requests: 9 + ok: 9 + http_200: 9 + finish_reason: stop + provider_max: + corp-mac-studio-mlx-vllm: + max_in_flight: 5 + max_queued: 4 + final_recovery: in_flight_0_queued_0_healthy + gemma4_6: + model: gemma4:26b + concurrent_requests: 6 + ok: 6 + http_200: 6 + finish_reason: stop + provider_max: + corp-mac-studio-mlx-vllm: + max_in_flight: 5 + max_queued: 1 + final_recovery: in_flight_0_queued_0_healthy responses: supported: false - observed_http_status: 400 reason: /v1/responses is not supported for OpenAI-compatible provider model groups until raw passthrough parity is implemented legacy_capacity_verification_2026_07_08: date: "2026-07-08" @@ -521,8 +433,9 @@ model: ok: 15 max_total_in_flight: 13 max_total_queued: 6 - latest_runtime_update: + legacy_gemma4_runtime_update_2026_06_25: date: "2026-06-25" + status: historical_pre_2026_07_13_spark_ornith_swap reason: user requested dev-corp node capacity/context/KV alignment requested_targets: dgx_spark: @@ -537,9 +450,9 @@ model: dgx_spark: vLLM has no vLLM-MLX style max_kv_size flag; requested KV 262144x2 is validated from startup log KV cache size and max_model_len 262144 mac_studio: vLLM-MLX requested KV 262144x3 is represented as max_kv_size 786432 with max_request_tokens 262144 remediation_applied: - - DGX Spark vLLM FP4 MoE first profile required VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304 for max_num_batched_tokens 524288 - - DGX Spark 01/02 Gemma4 agent serving now uses vLLM 0.24.0 with text-only/eager profile to keep native tool-call streaming stable for Pi/Cline-style agents - - DGX Spark 01 start script now prefixes /home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin + - Historical Spark Gemma4 FP4 MoE first profile required VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304 for max_num_batched_tokens 524288 + - DGX Spark 01/02 Gemma4 agent serving used vLLM 0.24.0 with text-only/eager profile to keep native tool-call streaming stable for agent/tool-call flows; this is legacy evidence after the 2026-07-13 Spark Ornith swap + - Historical Spark Gemma4 DGX Spark 01 start script prefixed /home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin - Mac Studio vLLM-MLX pyexpat required DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib verification: last_rechecked_at: "2026-07-08" @@ -547,9 +460,9 @@ model: dgx01_health: passed dgx02_health: passed direct_health_observation: - dgx01: mac-mini http://192.168.2.2:8002 returned /health 200 and /v1/models exposed gemma-4-26B-A4B-it-NVFP4 after vLLM 0.24.0 text-only/eager restart with default_chat_template_kwargs.enable_thinking=true; direct API forced/auto/streaming tool-call smoke and local Pi TUI bash/git-push tool-call flows passed; startup log reported GPU KV cache size 1,453,705 tokens and 5.55x concurrency for 262,144-token requests - dgx02: node-local http://127.0.0.1:8004 and mac-mini http://192.168.2.4:8004 returned /health 200, /v1/models exposed gemma-4-26B-A4B-it-NVFP4 after Docker image vllm/vllm-openai:v0.24.0 text-only/eager restart with default_chat_template_kwargs.enable_thinking=true; direct API auto/streaming tool-call smoke passed; startup log reported GPU KV cache size 1,452,633 tokens and 5.54x concurrency for 262,144-token requests - mac_studio: node-local http://127.0.0.1:8004, mac-mini http://192.168.2.3:8004, and current-host http://172.24.63.178:8004 returned /health 200, /v1/models exposed mlx-community/gemma-4-26b-a4b-it-nvfp4 after vllm-mlx 0.4.0 restart with continuous batching and disable_prefix_cache; direct API non-stream/stream auto tool-call, streaming multi-turn tool-result final-answer, Pi -p tool-call, and Pi TUI initial-prompt tool-call server log completion passed + dgx01: historical pre-2026-07-13 Spark Gemma4 evidence; mac-mini http://192.168.2.2:8002 returned /health 200 and /v1/models exposed gemma-4-26B-A4B-it-NVFP4 after vLLM 0.24.0 text-only/eager restart with default_chat_template_kwargs.enable_thinking=true; direct API forced/auto/streaming tool-call smoke passed; startup log reported GPU KV cache size 1,453,705 tokens and 5.55x concurrency for 262,144-token requests + dgx02: historical pre-2026-07-13 Spark Gemma4 evidence; node-local http://127.0.0.1:8004 and mac-mini http://192.168.2.4:8004 returned /health 200, /v1/models exposed gemma-4-26B-A4B-it-NVFP4 after Docker image vllm/vllm-openai:v0.24.0 text-only/eager restart with default_chat_template_kwargs.enable_thinking=true; direct API auto/streaming tool-call smoke passed; startup log reported GPU KV cache size 1,452,633 tokens and 5.54x concurrency for 262,144-token requests + mac_studio: node-local http://127.0.0.1:8004, mac-mini http://192.168.2.3:8004, and current-host http://172.24.63.178:8004 returned /health 200, /v1/models exposed mlx-community/gemma-4-26b-a4b-it-nvfp4 after vllm-mlx 0.4.0 restart with continuous batching and disable_prefix_cache; direct API non-stream/stream auto tool-call and streaming multi-turn tool-result final-answer passed edge_openai_smoke: passed_with_control_plane_capacity_snapshot_2026_07_06 nodes: @@ -561,17 +474,18 @@ nodes: workspace: /home/digitalcommerce_dgx_spark_01 provider_pool_candidate: true provider: - id: corp-dgx-spark-01-vllm + id: corp-dgx-spark-01-ornith type: vllm - endpoint: http://192.168.2.2:8002/v1 - edge_adapter_endpoint: http://127.0.0.1:8002/v1 - health: http://192.168.2.2:8002/health - served_model: gemma-4-26B-A4B-it-NVFP4 + endpoint: http://192.168.2.2:8003/v1 + edge_adapter_endpoint: http://127.0.0.1:8003/v1 + health: http://192.168.2.2:8003/health + served_model: ornith:35b capacity: 4 - capacity_status: configured_health_passed_direct_smoke_and_edge_capacity_smoke - last_runtime_observation: upgraded on 2026-07-08 to vLLM 0.24.0 with text-only/eager Gemma4 agent profile and default_chat_template_kwargs.enable_thinking=true; mac-mini http://192.168.2.2:8002 returned /health 200 and /v1/models, direct API forced/auto/streaming tool-call smoke passed, and local Pi TUI via SSH tunnel completed bash and git push tool-call flows; startup log reported GPU KV cache size 1,453,705 tokens and 5.55x concurrency for 262,144-token requests - capacity_basis: dev-corp target baseline; vLLM 0.24.0 --max-num-seqs 4, --max-model-len 262144, --gpu-memory-utilization 0.40, text-only/eager profile; observed KV cache satisfies requested 262144x2 minimum + capacity_status: configured_health_passed_direct_and_iop_smoke_2026_07_13 + last_runtime_observation: Spark01 Gemma4 8002 stopped on 2026-07-13 and Ornith 8003 Docker runtime is connected to IOP provider pool; startup with gpu_memory_utilization 0.47 reported GPU KV cache size 783,347 tokens and 2.99x concurrency for 262,144-token requests, then /health, /v1/models, direct chat, and IOP ornith:35b smoke passed. + capacity_basis: capacity 4 uses the dev-corp capacity_planning_policy; gpu_memory_utilization 0.47 provides roughly 75% KV per slot and satisfies the 734004-786432 token operating target without requiring 4.0x full-context concurrency. queue_timeout_ms: 0 + adapter_queue_timeout_ms: 1800000 request_timeout_ms: 1800000 edge_connectivity: mode: direct_public_edge @@ -584,46 +498,28 @@ nodes: host: spark-0b30 os: Ubuntu 24.04.3 LTS / aarch64 hardware: NVIDIA DGX Spark / NVIDIA GB10 / 119GiB RAM - manager: tmux - tmux_session: vllm_server_8002 - start_script: /home/digitalcommerce_dgx_spark_01/start_vllm_8002.sh - python: /home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin/python3 - path_prefix_required: /home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin - path_prefix_reason: FlashInfer FP4 JIT invokes ninja from PATH during first compile + manager: docker + container_name: iop-vllm-ornith35b-fp8 + start_script: /home/digitalcommerce_dgx_spark_01/start_vllm_ornith35b_docker_8003.sh + image: vllm/vllm-openai:nightly-aarch64 package_baseline: - vllm: 0.24.0 - torch: 2.11.0+cu130 - transformers: 5.13.0 - flashinfer_python: 0.6.12 - huggingface_hub: 1.22.0 + vllm: 0.23.1rc1.dev1042+g8e981630c args: - env: - PATH_prefix: /home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin - VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE: "4194304" host: 0.0.0.0 - port: 8002 + port: 8003 dtype: bfloat16 - gpu_memory_utilization: 0.40 + gpu_memory_utilization: 0.47 max_model_len: 262144 max_num_seqs: 4 - enforce_eager: true - skip_mm_profiling: true - limit_mm_per_prompt: - image: 0 - video: 0 - mm_processor_cache_gb: 0 - text_only_mode: true + enable_prefix_caching: true enable_auto_tool_choice: true - tool_call_parser: gemma4 - chat_template: /home/digitalcommerce_dgx_spark_01/tool_chat_template_gemma4.jinja - reasoning_parser: gemma4 - max_num_batched_tokens: auto_2496 - max_num_batched_tokens_note: vLLM raised the default from 2048 to 2496 for the Gemma4 prefix-LM/video path; it is a scheduler iteration budget, not the total KV cache size + tool_call_parser: qwen3_xml + reasoning_parser: qwen3 + trust_remote_code: true + runner: generate context_window_max: 262144 - kv_size_tokens_effective: 1453705 - full_context_concurrency_observed: 5.55 - default_chat_template_kwargs: - enable_thinking: true + kv_size_tokens_effective: 783347 + full_context_concurrency_observed: 2.99 - id: corp-dgx-spark-02-vllm-node alias: corp-dgx-spark-02-vllm @@ -633,17 +529,18 @@ nodes: workspace: /home/dplab provider_pool_candidate: true provider: - id: corp-dgx-spark-02-vllm + id: corp-dgx-spark-02-ornith type: vllm - endpoint: http://192.168.2.4:8004/v1 - edge_adapter_endpoint: http://127.0.0.1:8004/v1 - health: http://192.168.2.4:8004/health - served_model: gemma-4-26B-A4B-it-NVFP4 + endpoint: http://192.168.2.4:8005/v1 + edge_adapter_endpoint: http://127.0.0.1:8005/v1 + health: http://192.168.2.4:8005/health + served_model: ornith:35b capacity: 4 - capacity_status: configured_health_passed_direct_smoke_and_edge_capacity_smoke - last_runtime_observation: upgraded on 2026-07-08 to Docker image vllm/vllm-openai:v0.24.0 with text-only/eager Gemma4 agent profile and default_chat_template_kwargs.enable_thinking=true; node-local and mac-mini /health passed, /v1/models exposed gemma-4-26B-A4B-it-NVFP4, and direct API auto plus streaming tool-call smoke passed; startup log reported GPU KV cache size 1,452,633 tokens and 5.54x concurrency for 262,144-token requests - capacity_basis: dev-corp target baseline; Docker publishes host 8004 to container 8004; vLLM 0.24.0 --max-num-seqs 4, --max-model-len 262144, --gpu-memory-utilization 0.40, text-only/eager profile; observed KV cache satisfies requested 262144x2 minimum + capacity_status: configured_health_passed_direct_and_iop_smoke_2026_07_13 + last_runtime_observation: Spark02 Gemma4 8004 stopped on 2026-07-13 and Ornith 8005 Docker runtime is connected to IOP provider pool; startup with gpu_memory_utilization 0.50 reported GPU KV cache size 1,074,276 tokens and 4.10x concurrency for 262,144-token requests, then /health, /v1/models, direct chat, and IOP ornith:35b smoke passed. + capacity_basis: capacity 4 uses the dev-corp capacity_planning_policy; gpu_memory_utilization 0.50 is above the 734004-786432 token operating target and provides 4.10x full-context concurrency. queue_timeout_ms: 0 + adapter_queue_timeout_ms: 1800000 request_timeout_ms: 1800000 edge_connectivity: mode: direct_public_edge @@ -657,43 +554,27 @@ nodes: os: Ubuntu 24.04.3 LTS / aarch64 hardware: NVIDIA DGX Spark / NVIDIA GB10 / 119GiB RAM manager: docker - container_name: vllm-gemma4 - start_script: /home/dplab/start_vllm_gemma4_8004.sh - env_file: /home/dplab/.config/iop-dev-corp/vllm-gemma4.env - env_file_contains_secret: true - image: vllm/vllm-openai:v0.24.0 - container_port: 8004 - host_port: 8004 + container_name: iop-vllm-ornith35b-fp8 + start_script: /home/dplab/start_vllm_ornith35b_docker_8005.sh + image: vllm/vllm-openai:nightly-aarch64 + container_port: 8000 + host_port: 8005 package_baseline: - vllm: 0.24.0 - torch: 2.11.0+cu130 - transformers: 5.12.1 - flashinfer_python: 0.6.12 - huggingface_hub: 1.21.0 + vllm: 0.23.1rc1.dev1042+g8e981630c args: - env: - VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE: "4194304" - gpu_memory_utilization: 0.40 + gpu_memory_utilization: 0.50 max_model_len: 262144 max_num_seqs: 4 - enforce_eager: true - skip_mm_profiling: true - limit_mm_per_prompt: - image: 0 - video: 0 - mm_processor_cache_gb: 0 - text_only_mode: true + dtype: bfloat16 + enable_prefix_caching: true enable_auto_tool_choice: true - tool_call_parser: gemma4 - chat_template: /vllm-workspace/examples/tool_chat_template_gemma4.jinja - reasoning_parser: gemma4 - max_num_batched_tokens: auto_2496 - max_num_batched_tokens_note: vLLM raised the default from 2048 to 2496 for the Gemma4 prefix-LM/video path; it is a scheduler iteration budget, not the total KV cache size + tool_call_parser: qwen3_xml + reasoning_parser: qwen3 + trust_remote_code: true + runner: generate context_window_max: 262144 - kv_size_tokens_effective: 1452633 - full_context_concurrency_observed: 5.54 - default_chat_template_kwargs: - enable_thinking: true + kv_size_tokens_effective: 1074276 + full_context_concurrency_observed: 4.10 - id: corp-mac-studio-mlx-vllm-node alias: corp-mac-studio-mlx-vllm @@ -716,12 +597,12 @@ nodes: served_model: mlx-community/gemma-4-26b-a4b-it-nvfp4 capacity: 5 capacity_status: configured_health_passed_direct_smoke_and_edge_capacity_smoke - last_runtime_observation: screen vllm_mlx_8004 running vllm-mlx 0.4.0 with provider catalog capacity 5, continuous batching enabled, runtime headroom max_num_seqs 6, max_request_tokens 262144, max_kv_size 786432, disable_prefix_cache, and default_chat_template_kwargs.enable_thinking=true; node-local, mac-mini, and current-host /health passed, /v1/models exposed mlx-community/gemma-4-26b-a4b-it-nvfp4, direct API non-stream/stream auto tool-call and streaming multi-turn tool-result final-answer smoke passed, Pi -p tool-call passed, and Pi TUI initial-prompt tool-call completed on the server log + last_runtime_observation: screen vllm_mlx_8004 running vllm-mlx 0.4.0 with provider catalog capacity 5, continuous batching enabled, runtime headroom max_num_seqs 6, max_request_tokens 262144, max_kv_size 786432, disable_prefix_cache, and default_chat_template_kwargs.enable_thinking=true; node-local, mac-mini, and current-host /health passed, /v1/models exposed mlx-community/gemma-4-26b-a4b-it-nvfp4, direct API non-stream/stream auto tool-call and streaming multi-turn tool-result final-answer smoke passed capacity_basis: provider catalog capacity 5; vllm-mlx 0.4.0 runtime headroom uses --max-num-seqs 6 with requested KV 262144x3 mapped to --max-kv-size 786432; continuous batching is required for this provider, while prefix cache is disabled for Gemma4 stability working_checkpoint: status: final_working_baseline_as_of_2026_07_08 do_not_change_with_spark_vllm: true - micro_tuning_policy: only in a separate experiment with an explicit rollback point; do not change Spark vLLM settings or Pi default provider/model as part of this tuning + micro_tuning_policy: only in a separate experiment with an explicit rollback point; do not change Spark Ornith vLLM settings as part of Mac Studio Gemma4 tuning required_runtime_flags: - --continuous-batching - --max-num-seqs 6 @@ -735,9 +616,10 @@ nodes: - --tool-call-parser gemma4 - --reasoning-parser gemma4 - --default-chat-template-kwargs '{"enable_thinking":true}' - residual_issue: Gemma4 thought channel delimiters can still leak into final assistant content on Pi TUI output after successful tool execution. - containment_preference: prefer a vllm-mlx Gemma-specific Pi extension/provider adapter sanitizer over further runtime option churn if the residual issue appears in assistant content + residual_issue: Gemma4 thought channel delimiters can still leak into final assistant content after successful tool execution. + containment_preference: prefer a vllm-mlx Gemma-specific Edge/provider adapter sanitizer over further runtime option churn if the residual issue appears in assistant content queue_timeout_ms: 0 + adapter_queue_timeout_ms: 1800000 request_timeout_ms: 1800000 runtime: host: dc-devui-MacStudio.local diff --git a/agent-test/dev-corp/node-smoke.md b/agent-test/dev-corp/node-smoke.md index c4e90e7..c7a51df 100644 --- a/agent-test/dev-corp/node-smoke.md +++ b/agent-test/dev-corp/node-smoke.md @@ -3,7 +3,7 @@ test_env: dev-corp test_profile: node-smoke domain: node verification_type: smoke -last_rule_updated_at: 2026-07-11 +last_rule_updated_at: 2026-07-13 --- # node-smoke dev-corp 테스트 @@ -52,26 +52,25 @@ retired mac-mini local route와 reverse tunnel route는 Edge 연결로 사용하 - DGX Spark 01 vLLM node: `corp-dgx-spark-01-vllm-node` / `corp-dgx-spark-01-vllm` - SSH/user: mac-mini에서 `ssh digitalcommerce_dgx_spark_01@192.168.2.2` - - provider endpoint: `http://192.168.2.2:8002/v1` - - Edge adapter endpoint: node-local `http://127.0.0.1:8002/v1` + - provider endpoint: `http://192.168.2.2:8003/v1` + - Edge adapter endpoint: node-local `http://127.0.0.1:8003/v1` - Edge addr: `iop.ai.kr:18087` - - served model: `gemma-4-26B-A4B-it-NVFP4` + - served model: `ornith:35b` - capacity baseline 후보: `4` - - runtime capacity/context/KV: `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`; agent/tool-call profile `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /home/digitalcommerce_dgx_spark_01/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`; 2026-07-08 startup log 기준 GPU KV cache `1,453,705` tokens, `262144` full-context concurrency `5.55x`; FP4 MoE env `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` - - start script: `/home/digitalcommerce_dgx_spark_01/start_vllm_8002.sh` - - 주의: 0.24.0 venv toolchain을 사용하므로 start script에서 `/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin`을 `PATH` 앞에 둔다. + - runtime capacity/context/KV: Docker container `iop-vllm-ornith35b-fp8`, image `vllm/vllm-openai:nightly-aarch64`, `vllm=0.23.1rc1.dev1042+g8e981630c`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.47`; agent/tool-call profile `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`; 2026-07-13 startup log 기준 GPU KV cache `783,347` tokens, `262144` full-context concurrency `2.99x` + - start script: `/home/digitalcommerce_dgx_spark_01/start_vllm_ornith35b_docker_8003.sh` - workspace: `/home/digitalcommerce_dgx_spark_01` - DGX Spark 02 vLLM node: `corp-dgx-spark-02-vllm-node` / `corp-dgx-spark-02-vllm` - SSH/user: mac-mini에서 `ssh dplab@192.168.2.4` - - provider endpoint: `http://192.168.2.4:8004/v1` - - Edge adapter endpoint: node-local `http://127.0.0.1:8004/v1` + - provider endpoint: `http://192.168.2.4:8005/v1` + - Edge adapter endpoint: node-local `http://127.0.0.1:8005/v1` - Edge addr: `iop.ai.kr:18087` - - served model: `gemma-4-26B-A4B-it-NVFP4` + - served model: `ornith:35b` - capacity baseline 후보: `4` - - runtime capacity/context/KV: image `vllm/vllm-openai:v0.24.0`, `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`; agent/tool-call profile `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--chat-template /vllm-workspace/examples/tool_chat_template_gemma4.jinja`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`; 2026-07-08 startup log 기준 GPU KV cache `1,452,633` tokens, `262144` full-context concurrency `5.54x`; FP4 MoE env `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` - - start script: `/home/dplab/start_vllm_gemma4_8004.sh` + - runtime capacity/context/KV: Docker container `iop-vllm-ornith35b-fp8`, image `vllm/vllm-openai:nightly-aarch64`, `vllm=0.23.1rc1.dev1042+g8e981630c`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.50`; agent/tool-call profile `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`; 2026-07-13 startup log 기준 GPU KV cache `1,074,276` tokens, `262144` full-context concurrency `4.10x` + - start script: `/home/dplab/start_vllm_ornith35b_docker_8005.sh` - workspace: `/home/dplab` - - 주의: Docker publish 때문에 host endpoint와 container endpoint 모두 `8004`이다. `8000`, `8001`, `8002`를 기본 endpoint로 쓰지 않는다. + - 주의: Docker publish 때문에 host endpoint는 `8005`, container endpoint는 `8000`이다. `8000`, `8001`, `8002`, `8004`를 Spark02 Ornith 기본 endpoint로 쓰지 않는다. - Mac Studio vLLM-MLX node: `corp-mac-studio-mlx-vllm-node` / `corp-mac-studio-mlx-vllm` - SSH/user: mac-mini에서 `ssh dc_dev@192.168.2.3` - provider endpoint: `http://192.168.2.3:8004/v1` @@ -91,23 +90,25 @@ Mac Studio의 secondary `http://192.168.2.3:8005/v1` endpoint는 기본 Node/pro ## 런타임 설정/검증 상태 -- DGX Spark 01에는 capacity `4`, context window `262144`, requested KV `262144x2` 이상의 기준을 반영했다. vLLM에는 vLLM-MLX식 `--max-kv-size`가 없으므로 DGX01은 `vllm=0.24.0`, `--max-num-seqs 4`, `--max-model-len 262144`, `--gpu-memory-utilization 0.40`, text-only/eager profile로 운용하고, 실제 KV cache는 startup log의 `GPU KV cache size`로 검증한다. -- DGX Spark 01은 2026-07-08 재기동 후 mac-mini 내부 endpoint `http://192.168.2.2:8002` 기준 `/health` 200, `/v1/models`, 직접 API forced/auto/streaming tool-call smoke, 로컬 Pi TUI bash/git-push tool-call 흐름을 통과했다. 같은 로그에서 GPU KV cache `1,453,705` tokens, `262144` tokens/request concurrency `5.55x`가 확인됐다. -- DGX Spark 02에는 capacity `4`, context window `262144`, requested KV `262144x2` 이상의 기준을 반영했다. Docker `vllm-gemma4`는 host/container `8004`, image `vllm/vllm-openai:v0.24.0`, text-only/eager profile 기준으로 동작하며, node-local과 mac-mini 경유 `/health`, `/v1/models`, 직접 API auto/streaming tool-call smoke를 통과했다. -- DGX Spark에서 explicit `--max-num-batched-tokens 524288`를 사용하는 경우 first profile 중 FP4 MoE 커널 한계에 걸릴 수 있어 `VLLM_MAX_TOKENS_PER_EXPERT_FP4_MOE=4194304` 보정이 필요하다. -- DGX Spark 01은 0.24.0 venv toolchain을 사용하므로 `/home/digitalcommerce_dgx_spark_01/vllm_env_0_24_0/bin` PATH prefix가 필요하다. -- Mac Studio에는 `vllm-mlx=0.4.0`, provider catalog capacity `5`, context window `262144`, requested KV `262144x3` 기준을 continuous batching 유지, runtime headroom `--max-num-seqs 6`, `--max-request-tokens 262144`, `--max-kv-size 786432`, `--disable-prefix-cache`로 반영했고 `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer, Pi `-p` tool-call, Pi TUI 초기 프롬프트 tool-call 로그 종료를 확인했다. -- Gemma provider-pool은 `default_thinking_token_budget: 1024` 기준으로 thinking을 기본 활성화한다. vLLM과 vLLM-MLX provider 모두 Edge/Node adapter 요청에서 `chat_template_kwargs.enable_thinking=true`가 적용되는 방향으로 검증한다. -- Gemma4 agent/tool-call compatibility profile은 DGX Spark 01/02 vLLM에서 `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, Gemma4 tool chat template, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`, `--enforce-eager`, `--skip-mm-profiling`, `--limit-mm-per-prompt '{"image": 0, "video": 0}'`, `--mm-processor-cache-gb 0`을 함께 둔다. Mac Studio vLLM-MLX는 별도 chat template override 없이 `--continuous-batching`, `--disable-prefix-cache`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. Qwen provider는 dev-runtime 문서의 Qwen 전용 parser/template 값을 따른다. -- Mac Studio vLLM-MLX의 위 값은 2026-07-08 기준 구동 가능한 최종 체크포인트다. 잔여 이슈로 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있으며, 이 경우 runtime option 미세 조정보다 vLLM-MLX Gemma provider 전용 Pi extension/provider adapter sanitizer를 우선 검토한다. 추가 튜닝은 Spark vLLM 설정과 분리된 별도 실험으로만 수행한다. -- Gemma provider를 Pi/Cline형 agent/tool-call 용도로 검증할 때는 일반 chat smoke와 별도로 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 확인한다. raw `<|tool_call>`/`<|"|>` marker나 thought channel text가 assistant content로 새면 provider parser/template profile 또는 Edge relay 경계 문제로 판정한다. -- Gemma provider-pool의 provider queue timeout은 두지 않는다. config 값은 `queue_timeout_ms=0`이며, backend request timeout은 30분 기준인 `request_timeout_ms=1800000`으로 맞춘다. -- 2026-07-08 재확인 기준 DGX Spark 02는 mac-mini에서 SSH, provider `/health`, `/v1/models`가 회복됐고 직접 API auto/streaming tool-call smoke를 통과했다. 이때의 `/v1/responses` capacity 결과는 mac-mini provider-pool runtime 기준 legacy evidence이며, 2026-07-09 public Edge 표준 smoke는 `/v1/chat/completions` 15개 동시 요청이다. +- capacity `4`는 `262144` max context 요청 4개가 항상 100% context를 채운다는 보장이 아니다. dev-corp 운영 기준은 일반 호출이 prompt+generated KV 기준으로 max context의 `50-70%`를 사용한다는 가정이다. +- `context_window_max=262144`, `capacity=4`에서 KV `524,288` tokens / full-context concurrency `2.0x`는 lower bound이고, 운영 target은 KV `734,004-786,432` tokens / full-context concurrency `2.8x-3.0x`이다. 이 metric이 catalog capacity `4`보다 작다는 이유만으로 under-capacity로 판정하지 않되, `2.0x-2.8x`는 workload-specific smoke 없이는 운영 적합으로 보지 않는다. +- capacity smoke는 provider admission, queue behavior, health, completion 후 `in_flight=0`/`queued=0` 회복을 검증한다. 모든 capacity slot이 동시에 `262144` tokens를 100% 채울 수 있는지 검증하는 테스트가 아니다. +- DGX Spark 01에는 Ornith `8003` 기준 capacity `4`, context window `262144`, `--gpu-memory-utilization 0.47`을 반영했다. vLLM에는 vLLM-MLX식 `--max-kv-size`가 없으므로 실제 KV cache는 startup log의 `GPU KV cache size`로 검증한다. +- DGX Spark 01은 2026-07-13 재기동 후 `http://192.168.2.2:8003` 기준 `/health` 200, `/v1/models`, 직접 API, IOP `ornith:35b` smoke를 통과했다. 같은 로그에서 GPU KV cache `783,347` tokens, `262144` tokens/request concurrency `2.99x`가 확인됐다. +- DGX Spark 02에는 Ornith `8005` 기준 capacity `4`, context window `262144`, `--gpu-memory-utilization 0.50`을 반영했다. Docker `iop-vllm-ornith35b-fp8`는 host `8005` -> container `8000` 기준으로 동작하며, `/health`, `/v1/models`, 직접 API, IOP `ornith:35b` smoke를 통과했다. +- Spark의 Gemma4 `8002`/`8004` runtime은 2026-07-13 Ornith IOP provider 전환을 위해 내린 상태로 본다. Gemma4 provider pool은 Mac Studio `192.168.2.3:8004`만 기본 대상으로 둔다. +- Mac Studio에는 `vllm-mlx=0.4.0`, provider catalog capacity `5`, context window `262144`, requested KV `262144x3` 기준을 continuous batching 유지, runtime headroom `--max-num-seqs 6`, `--max-request-tokens 262144`, `--max-kv-size 786432`, `--disable-prefix-cache`로 반영했고 `/health`, `/v1/models`, 직접 API non-stream/stream auto tool-call, streaming multi-turn tool-result final answer를 확인했다. +- Gemma provider-pool은 Mac Studio vLLM-MLX provider에서 `default_thinking_token_budget: 1024` 기준으로 thinking을 기본 활성화한다. Edge/Node adapter 요청에서 `chat_template_kwargs.enable_thinking=true`가 적용되는 방향으로 검증한다. +- Spark Ornith provider는 `--enable-auto-tool-choice`, `--tool-call-parser qwen3_xml`, `--reasoning-parser qwen3`, `--trust-remote-code`, `--runner generate`를 둔다. Gemma4 provider는 Mac Studio vLLM-MLX `8004`만 기본 대상으로 하며 별도 chat template override 없이 `--continuous-batching`, `--disable-prefix-cache`, `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`를 둔다. Qwen provider는 dev-runtime 문서의 Qwen 전용 parser/template 값을 따른다. +- Mac Studio vLLM-MLX의 위 값은 구동 가능한 최종 체크포인트다. 잔여 이슈로 Gemma4 thought channel delimiter가 최종 content에 누수될 수 있으며, 이 경우 runtime option 미세 조정보다 Edge/provider adapter sanitizer를 우선 검토한다. 추가 튜닝은 Spark vLLM 설정과 분리된 별도 실험으로만 수행한다. +- Gemma provider를 agent/tool-call 용도로 검증할 때는 일반 chat smoke와 별도로 forced tool call, auto tool call, streaming `delta.tool_calls`, multi-turn tool result 후 최종 답변을 확인한다. raw `<|tool_call>`/`<|"|>` marker나 thought channel text가 assistant content로 새면 provider parser/template profile 또는 Edge relay 경계 문제로 판정한다. +- provider catalog의 admission queue timeout은 두지 않는다. provider catalog `queue_timeout_ms=0`이고, Node `openai_compat_instances` adapter queue/request budget은 30분 기준인 `queue_timeout_ms=1800000`, `request_timeout_ms=1800000`으로 맞춘다. +- 2026-07-08 재확인 기준 DGX Spark 02는 mac-mini에서 SSH, provider `/health`, `/v1/models`가 회복됐고 직접 API auto/streaming tool-call smoke를 통과했다. 이때의 `/v1/responses` capacity 결과와 2026-07-09 `/v1/chat/completions` 15개 aggregate concurrency 결과는 legacy evidence이며, current public Edge 표준 smoke는 2026-07-13 기준 model-specific `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이다. ## 2026-07-09 연결/용량 검증 상태 - DGX Spark 01, DGX Spark 02, Mac Studio Node는 각 host의 `~/iop-dev-corp-field/node.yaml`에서 `edge_addr: "iop.ai.kr:18087"`로 실행된다. -- 2026-07-09 재연결 후 세 Node 모두 `registered with edge`와 `connected to edge` 로그를 남겼고 public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions` 15개 동시 요청이 15/15 성공했다. +- 2026-07-13 live status 기준 세 Node 모두 connected이며 provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. Public `http://digitalplatform.iop.ai.kr:18086/v1/chat/completions`에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. - `/v1/responses`는 OpenAI-compatible provider model group raw passthrough parity 전까지 미지원이므로 provider-pool capacity 성공 기준에서 제외한다. ## 명령 @@ -117,14 +118,14 @@ Mac Studio의 secondary `http://192.168.2.3:8005/v1` endpoint는 기본 Node/pro - unit: `go test ./apps/node/...` - smoke: `./scripts/e2e-smoke.sh`는 기본 포트 임시 설정을 쓰는 보조 smoke이므로 dev-corp 포트 override 필요 여부를 먼저 확인한다. - e2e: `make test-e2e` -- provider-health: mac-mini에서 `curl -fsS http://192.168.2.2:8002/health`, `curl -fsS http://192.168.2.4:8004/health`, `curl -fsS http://192.168.2.3:8004/health` +- provider-health: mac-mini에서 `curl -fsS http://192.168.2.2:8003/health`, `curl -fsS http://192.168.2.4:8005/health`, `curl -fsS http://192.168.2.3:8004/health` - full-cycle: repo 내부 edge-node 진단과 사용자 실행 cycle 수동 검증 ## 필수 검증 - 변경한 node 패키지 또는 `go test ./apps/node/...`를 실행한다. - 실행 요청, stream, cancel, status, session, adapter registry 경로를 바꾼 경우 repo 내부 edge-node 진단과 full-cycle 실제 구동 기준을 함께 적용한다. -- vLLM/OpenAI-compatible adapter 설정을 바꾼 경우 mac-mini에서 provider `/health`와 `/v1/models`를 먼저 확인하고, 이후 Edge OpenAI-compatible 경로에서 model alias 후보 `gemma4:26b` 또는 작업에서 확정한 alias가 노출되는지 확인한다. +- vLLM/OpenAI-compatible adapter 설정을 바꾼 경우 mac-mini에서 provider `/health`와 `/v1/models`를 먼저 확인하고, 이후 Edge OpenAI-compatible 경로에서 model alias 후보 `gemma4:26b`, `ornith:35b` 또는 작업에서 확정한 alias가 노출되는지 확인한다. - dev-corp Edge runtime으로 연결하는 경우 Node가 `iop.ai.kr:18087` native provider-pool TCP를 사용하고 mac-mini local route, reverse tunnel route, local/test/dev baseline으로 붙지 않는지 확인한다. - Node bootstrap UX는 Edge가 출력한 완성 명령을 사용하고, 사용자에게 수동 `node.yaml` 편집이나 named env parameter를 기본 경로로 요구하지 않는다. @@ -145,8 +146,8 @@ Mac Studio의 secondary `http://192.168.2.3:8005/v1` endpoint는 기본 Node/pro ## 기준 출력 예시 ```text -curl -fsS http://192.168.2.2:8002/health -curl -fsS http://192.168.2.4:8004/health +curl -fsS http://192.168.2.2:8003/health +curl -fsS http://192.168.2.4:8005/health curl -fsS http://192.168.2.3:8004/health ``` diff --git a/agent-test/dev-corp/platform-common-smoke.md b/agent-test/dev-corp/platform-common-smoke.md index 777ffcb..5d05aab 100644 --- a/agent-test/dev-corp/platform-common-smoke.md +++ b/agent-test/dev-corp/platform-common-smoke.md @@ -54,7 +54,7 @@ last_rule_updated_at: 2026-07-11 - protobuf 원본 변경 시 `make proto`로 Go 생성물을 갱신하고 생성물 diff를 확인한다. - config 계약 변경 시 `packages/go/config` struct/default와 `configs/*.yaml` 예시가 일치하는지 확인한다. - dev-corp env/compose 계약 변경 시 `.env.dev-corp.example`, `docker-compose.yml` 또는 compose override, `agent-test/dev-corp/rules.md`의 포트가 서로 일치하는지 확인한다. -- provider config 변경 시 IOP model alias 후보 `gemma4:26b` 또는 작업에서 확정한 alias와 각 provider `served_model` 값이 `agent-test/dev-corp/inventory.yaml`과 맞는지 확인한다. +- provider config 변경 시 IOP model alias 후보 `gemma4:26b`, `ornith:35b` 또는 작업에서 확정한 alias와 각 provider `served_model` 값이 `agent-test/dev-corp/inventory.yaml`과 맞는지 확인한다. - Mac Studio vLLM-MLX provider config는 catalog `type: openai_compat`를 사용하고, 실제 runtime 구분은 `agent-test/dev-corp/inventory.yaml`의 `runtime_type: vllm-mlx`로 추적한다. ## 보조 검증 diff --git a/agent-test/dev-corp/rules.md b/agent-test/dev-corp/rules.md index b13944d..0edbdc5 100644 --- a/agent-test/dev-corp/rules.md +++ b/agent-test/dev-corp/rules.md @@ -1,6 +1,6 @@ --- test_env: dev-corp -last_rule_updated_at: 2026-07-11 +last_rule_updated_at: 2026-07-13 --- # dev-corp 테스트 규칙 @@ -24,7 +24,7 @@ last_rule_updated_at: 2026-07-11 - dev-corp Edge의 기본 배포/검증 통로는 `iop.ai.kr`이다. artifact/bootstrap, Edge OpenAI-compatible, Edge-Node TCP는 같은 host의 dev-corp 포트 `18085/18086/18087`을 사용한다. - mac-mini는 source sync/build/provider 점검 경유지로만 사용한다. dev-corp Edge 주소, Node `edge_addr`, OpenAI-compatible smoke 대상, bootstrap 기본 URL은 public domain 값으로만 둔다. - mac-mini local endpoint로 Edge를 배포/검증하지 않는다. 사용자가 “mac-mini local Edge로 검증” 또는 같은 의미의 명시 요청을 한 경우에만 별도 local-runner 비교로 진행한다. -- provider direct 확인은 기존처럼 mac-mini에서 내부 provider endpoint `192.168.2.2:8002`, `192.168.2.4:8004`, `192.168.2.3:8004`를 확인한다. +- provider direct 확인은 mac-mini에서 Spark01 Ornith `192.168.2.2:8003`, Spark02 Ornith `192.168.2.4:8005`, Mac Studio Gemma4 `192.168.2.3:8004`를 확인한다. ## 기본 환경 @@ -76,8 +76,8 @@ dev-corp native/provider-pool profile은 compose Edge-Node TCP `19006`이 아니 - plan 작성 시 필수 검증이 현재 checkout을 벗어나 mac-mini runner, field/bootstrap, 외부 provider, Docker/code-server, emulator/device, 공유 장기 runtime을 사용하면 먼저 테스트 환경 프리플라이트를 계획에 기록한다. - 테스트 환경 프리플라이트에는 runner, repo root/workdir, branch/HEAD/dirty 상태, local 변경과 원격 source 동기화 여부, binary/artifact 경로와 필요한 help/version 출력, config path, runtime identity, port/process 상태, 외부 host, OS/arch 가정을 포함한다. - mac-mini에 `/Users/fe/agent-work/iop-dev-corp` checkout이 없으면 배포/검증을 시작하지 말고 checkout 생성과 source sync를 setup blocker로 보고한다. -- provider pool 검증 전 mac-mini에서 내부 provider endpoint `192.168.2.2:8002`, `192.168.2.4:8004`, `192.168.2.3:8004`의 `/health`와 `/v1/models`를 먼저 확인하고, 각 Node의 `edge_addr`가 `iop.ai.kr:18087`인지 확인한다. -- `gemma4:26b` alias와 총 capacity `13`은 `agent-test/dev-corp/inventory.yaml`의 최신 검증 상태를 기준으로 판단한다. 새 배포에서 Edge config 반영과 capacity smoke가 통과하기 전에는 새 결과를 확정값으로 보고하지 않는다. +- provider pool 검증 전 mac-mini에서 내부 provider endpoint `192.168.2.2:8003`, `192.168.2.4:8005`, `192.168.2.3:8004`의 `/health`와 `/v1/models`를 먼저 확인하고, 각 Node의 `edge_addr`가 `iop.ai.kr:18087`인지 확인한다. +- 현재 dev-corp model/provider mapping은 `gemma4:26b` -> Mac Studio capacity `5`, `ornith:35b` -> Spark01/02 합산 capacity `8`이다. 새 배포에서 Edge config 반영과 model-specific capacity smoke가 통과하기 전에는 새 결과를 확정값으로 보고하지 않는다. - 프리플라이트에서 dirty/divergent checkout 또는 stale artifact가 확인되면 dev-corp 배포에서는 먼저 원격 checkout을 clean sync하고 dev-corp runtime 바이너리를 rebuild한다. 잘못된 identity, missing command, closed port, host OS 불일치, source 미동기화가 확인되면 plan은 setup/sync/rebuild 단계를 만들거나 blocker로 보고한다. ## 노드/Provider 인벤토리 위치 diff --git a/agent-test/dev-corp/testing-smoke.md b/agent-test/dev-corp/testing-smoke.md index 333d84f..6168759 100644 --- a/agent-test/dev-corp/testing-smoke.md +++ b/agent-test/dev-corp/testing-smoke.md @@ -3,7 +3,7 @@ test_env: dev-corp test_profile: testing-smoke domain: testing verification_type: smoke -last_rule_updated_at: 2026-07-11 +last_rule_updated_at: 2026-07-13 --- # testing-smoke dev-corp 테스트 @@ -50,7 +50,7 @@ last_rule_updated_at: 2026-07-11 - compose-smoke: mac-mini 환경에서 `IOP_EDGE_NODE_TOKEN`을 안전하게 주입한 뒤 `docker compose --env-file .env.dev-corp.example up -d postgres redis control-plane edge web` - compose-health: `curl -fsS http://127.0.0.1:18002/healthz` - control-plane-status: mac-mini에서 `curl -fsS http://127.0.0.1:18002/edges/dev-corp-edge/status` -- provider-health: mac-mini에서 `curl -fsS http://192.168.2.2:8002/health`, `curl -fsS http://192.168.2.4:8004/health`, `curl -fsS http://192.168.2.3:8004/health` +- provider-health: mac-mini에서 `curl -fsS http://192.168.2.2:8003/health`, `curl -fsS http://192.168.2.4:8005/health`, `curl -fsS http://192.168.2.3:8004/health` - e2e: `make test-e2e` - model: `./scripts/e2e-openai-ollama.sh` 또는 dev-corp OpenAI-compatible smoke - full-cycle: `make pack-node-target`, repo 내부 edge-node 진단, field bootstrap UX, 실제 provider pool 검증 @@ -86,7 +86,9 @@ last_rule_updated_at: 2026-07-11 ```text docker compose --env-file .env.dev-corp.example config curl -fsS http://127.0.0.1:18002/healthz -curl -fsS http://192.168.2.2:8002/v1/models +curl -fsS http://192.168.2.2:8003/v1/models +curl -fsS http://192.168.2.4:8005/v1/models +curl -fsS http://192.168.2.3:8004/v1/models ``` ## 차단 기준 diff --git a/docs/dev-corp-openai-compatible-call-guide.md b/docs/dev-corp-openai-compatible-call-guide.md deleted file mode 100644 index 7b05c6a..0000000 --- a/docs/dev-corp-openai-compatible-call-guide.md +++ /dev/null @@ -1,75 +0,0 @@ -# dev-corp OpenAI-Compatible Call Guide - -dev-corp `gemma4:26b` 모델을 OpenAI-compatible 방식으로 직접 호출할 때 필요한 최소 설정이다. - -## 기본값 - -| 항목 | 값 | -| --- | --- | -| Base URL | `http://digitalplatform.iop.ai.kr:18086/v1` | -| Chat endpoint | `POST /v1/chat/completions` | -| Models endpoint | `GET /v1/models` | -| Model | `gemma4:26b` | -| Auth header | `Authorization: Bearer ` | - -`/v1/responses`가 아니라 `/v1/chat/completions`를 사용한다. - -## 권장 요청 - -기본 권장 호출은 `stream:true`다. `think`, `reasoning_effort`, `thinking_token_budget`은 보내지 않는다. -반복 출력 loop를 피하려면 최소 sampling parameter로 `temperature: 0.2`, `top_p: 0.95`를 함께 보낸다. - -```bash -curl -N http://digitalplatform.iop.ai.kr:18086/v1/chat/completions \ - -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer ' \ - -d '{ - "model": "gemma4:26b", - "messages": [ - { - "role": "user", - "content": "간단히 응답해줘." - } - ], - "temperature": 0.2, - "top_p": 0.95, - "stream": true - }' -``` - -Streaming을 처리하지 않는 client에서는 선택적으로 `stream:false`를 사용할 수 있다. - -```bash -curl -fsS http://digitalplatform.iop.ai.kr:18086/v1/chat/completions \ - -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer ' \ - -d '{"model":"gemma4:26b","messages":[{"role":"user","content":"ok만 응답해줘."}],"temperature":0.2,"top_p":0.95,"stream":false}' -``` - -## 파라미터 - -| 파라미터 | 권장 | -| --- | --- | -| `model` | `gemma4:26b` | -| `stream` | 기본 `true`, 필요하면 `false` | -| `temperature` | 최소 기준 `0.2` | -| `top_p` | 최소 기준 `0.95` | -| `think` | 생략 | -| `reasoning_effort` | 생략 | -| `thinking_token_budget` | 생략 | -| `include_reasoning` | 숨김 보장용으로 쓰지 않음 | - -## Repetition loop 조정 - -dev-corp `gemma4:26b` OpenAI-compatible 호출에서는 반복 출력 loop를 피하기 위한 최소 기준으로 `temperature: 0.2`, `top_p: 0.95`를 설정한다. 두 값을 생략해 provider 기본값에 맡기지 않는다. - -그래도 repetition loop가 발생하면 한 번에 여러 값을 크게 바꾸지 말고, `temperature`는 조금씩 올리고 `top_p`는 조금씩 낮추는 방향으로 조정한다. - -## Reasoning 표시 옵션 - -응답에 reasoning field가 포함될 수 있다. 표시하지 않는 UX가 필요하면 호출하는 client에서 아래 field를 렌더링 대상에서 제외하는 방식으로 처리할 수 있다. - -- non-stream: `choices[].message.reasoning_content`, `choices[].message.reasoning`, `choices[].message.reasoning_text` -- stream: `choices[].delta.reasoning_content`, `choices[].delta.reasoning`, `choices[].delta.reasoning_text` - -`include_reasoning=false`만으로 reasoning 표시 여부가 항상 제어된다고 가정하지 않는다. diff --git a/docs/edge-local-dev-guide.md b/docs/edge-local-dev-guide.md index f0fe85e..f644e76 100644 --- a/docs/edge-local-dev-guide.md +++ b/docs/edge-local-dev-guide.md @@ -135,14 +135,18 @@ http://:18081/v1 `/v1/chat/completions` 요청은 `think`, `reasoning_effort`, `thinking_token_budget`, `include_reasoning`으로 thinking/reasoning 동작과 응답 노출을 제어할 수 있다. 단, provider-pool pure `passthrough`는 provider body 보존이 우선이므로 `include_reasoning=false`만으로 IOP-side reasoning 제거를 보장하지 않는다. -- dev-corp `gemma4:26b` provider-pool 안정 smoke: `think`, `reasoning_effort`, `thinking_token_budget`을 생략하고 현재 provider/vLLM 기본값을 유지한다. +- 현재 dev-corp provider-pool device mapping은 `gemma4:26b` -> Mac Studio provider capacity `5`, `ornith:35b` -> DGX Spark 01/02 provider 합산 capacity `8`이다. 세부 endpoint와 runtime args는 `agent-test/dev-corp/inventory.yaml`을 기준으로 한다. +- dev-corp provider-pool 안정 smoke: `think`, `reasoning_effort`, `thinking_token_budget`을 생략하고 현재 provider 기본값을 유지한다. +- 현재 dev-corp public capacity smoke 표준은 public OpenAI-compatible base `http://digitalplatform.iop.ai.kr:18086/v1`의 `/chat/completions`에서 `ornith:35b` 9/6 동시 요청과 `gemma4:26b` 9/6 동시 요청을 각각 확인하는 방식이다. - 일반 표준 caller의 `stream=false` 측정은 `/v1/chat/completions`에서 요청 파라미터만으로 확인한다. -- `include_reasoning=false`는 non-provider normalized route의 hide 동작 기준이다. dev-corp `gemma4:26b` provider-pool pure `passthrough`에서는 client가 reasoning field를 선택적으로 무시/제거한다. -- `think=false` 또는 `reasoning_effort=none`은 hide-only 옵션이 아니라 thinking disable 요청이다. dev-corp `gemma4:26b` 기본 안정 smoke에서는 쓰지 않는다. -- 세부 표와 금지/허용 범위는 `agent-contract/outer/openai-compatible-api.md`의 dev-corp `gemma4:26b` provider-pool passthrough 파라미터 범위를 기준으로 한다. +- `include_reasoning=false`는 non-provider normalized route의 hide 동작 기준이다. dev-corp provider-pool pure `passthrough`에서는 client가 reasoning field를 선택적으로 무시/제거한다. +- `think=false` 또는 `reasoning_effort=none`은 hide-only 옵션이 아니라 thinking disable 요청이다. dev-corp 기본 안정 smoke에서는 쓰지 않는다. +- Gemma4 passthrough 파라미터의 세부 표와 금지/허용 범위는 `agent-contract/outer/openai-compatible-api.md`의 dev-corp `gemma4:26b` provider-pool passthrough 파라미터 범위를 기준으로 한다. 예시 (dev-corp `gemma4:26b` provider-pool non-stream 측정, think 생략): +아래 `18081` 포트는 local Edge 예시다. dev-corp public smoke에서는 base URL을 `http://digitalplatform.iop.ai.kr:18086/v1`로 바꾼다. + ```bash curl -fsS http://:18081/v1/chat/completions \ -H 'Content-Type: application/json' \ @@ -160,7 +164,7 @@ curl -fsS http://:18081/v1/chat/completions \ ## 8. Raw text tool-call boundary smoke -Pi/Cline형 긴 agent prompt와 `tools[]` 요청은 provider가 native `tool_calls` 대신 assistant content에 raw 블록을 담아 응답할 수 있다. 계약 기준은 `agent-contract/outer/openai-compatible-api.md`의 Chat Completions raw text tool-call 정규화 정책이다. +긴 agent prompt와 `tools[]` 요청은 provider가 native `tool_calls` 대신 assistant content에 raw 블록을 담아 응답할 수 있다. 계약 기준은 `agent-contract/outer/openai-compatible-api.md`의 Chat Completions raw text tool-call 정규화 정책이다. 요청 payload는 tracked 문서에 secret 없이 남기고, token은 원격 환경 변수에서 주입한다. 실제 token 원문을 명령/로그/보고에 남기지 않는다. diff --git a/docs/openai-compatible-api-contract.md b/docs/openai-compatible-api-contract.md index 2f078d7..fc59306 100644 --- a/docs/openai-compatible-api-contract.md +++ b/docs/openai-compatible-api-contract.md @@ -10,7 +10,7 @@ - provider-pool model group route는 caller가 `metadata.iop_response_mode`를 명시하면 값과 무관하게 거부하고, 생략 시 provider-original `passthrough`로 동작한다. - direct legacy provider route는 `passthrough+sideband` extension selector를 지원한다. `passthrough+sideband`와 `transformed`는 IOP 확장/변환 응답이며 provider-original byte identity로 취급하지 않는다. - dev-corp `gemma4:26b` provider-pool에서 `think`/`stream`/`include_reasoning` 요청 파라미터만 바꿔 측정하는 범위는 계약 원문의 `dev-corp gemma4:26b provider-pool passthrough 파라미터 범위` 표를 기준으로 한다. -- dev-corp `iop.ai.kr` 직접 호출 가이드는 [dev-corp-openai-compatible-call-guide.md](./dev-corp-openai-compatible-call-guide.md)를 기준으로 한다. +- dev-corp Ollama `gemma4:26b` 이미지 입력 호출 가이드는 [dev-corp-ollama-gemma4-image-call-guide.md](./dev-corp-ollama-gemma4-image-call-guide.md)를 기준으로 한다. - dev-corp Pi coding agent 설정 가이드는 [dev-corp-pi-settings-guide.md](./dev-corp-pi-settings-guide.md)를 기준으로 한다. 에이전트 작업에서는 [agent-contract/index.md](../agent-contract/index.md)의 라우팅 규칙을 먼저 따른다.