누적된 잠금·승인·증거 체인이 구현과 완료를 반복 차단해 작업 비용을 키웠다. 보안·데이터 손상·명시적 외부 의존성만 차단 조건으로 남기고 로드맵과 스킬의 기본 흐름을 단순화한다.
176 lines
15 KiB
Markdown
176 lines
15 KiB
Markdown
---
|
|
test_env: dev-corp
|
|
test_profile: node-smoke
|
|
domain: node
|
|
verification_type: smoke
|
|
last_rule_updated_at: 2026-07-13
|
|
---
|
|
|
|
# node-smoke dev-corp 테스트
|
|
|
|
## 읽기 조건
|
|
|
|
- `apps/node/**` 변경 또는 dev-corp node 실행, adapter, transport, router, store 검증 판단이 필요한 경우
|
|
|
|
## 적용 범위
|
|
|
|
- `apps/node/cmd/node/**`
|
|
- `apps/node/internal/bootstrap/**`
|
|
- `apps/node/internal/node/**`
|
|
- `apps/node/internal/runtime/**`
|
|
- `apps/node/internal/router/**`
|
|
- `apps/node/internal/transport/**`
|
|
- `apps/node/internal/adapters/**`
|
|
- `apps/node/internal/store/**`
|
|
- dev-corp Linux ARM64/macOS Node bootstrap과 provider endpoint 연결
|
|
|
|
## 분류
|
|
|
|
- domain: node
|
|
- verification_type: smoke
|
|
- scope: dev-corp node 실행 파이프라인과 Edge 연결 baseline
|
|
|
|
## 환경
|
|
|
|
- host: local checkout. provider evidence가 필요하면 mac-mini `ssh fe@172.24.63.178`을 사용한다.
|
|
- Edge runtime evidence: public `iop.ai.kr`를 기준으로 한다.
|
|
- port: compose Edge-Node TCP transport `19006`, native provider-pool Edge-Node TCP 후보 `18087`
|
|
- runtime: Go `1.24`
|
|
- package manager: Go modules / Makefile
|
|
- docker: unit/smoke quick check는 Docker를 요구하지 않는다. compose dev-corp 검증은 mac-mini에서 수행한다.
|
|
- external service: dev-corp Edge runtime 후보는 `iop.ai.kr:18087`이다. mac-mini local endpoint와 reverse tunnel은 dev-corp Edge 경로로 사용하지 않는다.
|
|
- model endpoint: dev-corp OpenAI-compatible base URL 기본 후보 `https://digitalplatform.iop.ai.kr/v1`; direct Edge listener 확인이 필요할 때만 `http://digitalplatform.iop.ai.kr:18086/v1`
|
|
- credential: token/secret/API key 원문은 문서에 기록하지 않는다.
|
|
|
|
## dev-corp Node 접속 기준
|
|
|
|
dev-corp의 실제 3-node 연결을 점검할 때는 각 provider host의 `~/iop-dev-corp-field/node.yaml`을 확인하고, `transport.edge_addr`가 `iop.ai.kr:18087`인지 검증한다.
|
|
|
|
mac-mini `ssh fe@172.24.63.178`의 `/Users/fe/agent-work/iop-dev-corp` checkout은 provider SSH runner로만 사용한다.
|
|
|
|
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:8003/v1`
|
|
- Edge adapter endpoint: node-local `http://127.0.0.1:8003/v1`
|
|
- Edge addr: `iop.ai.kr:18087`
|
|
- served model: `ornith:35b`
|
|
- capacity baseline 후보: `4`
|
|
- 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:8005/v1`
|
|
- Edge adapter endpoint: node-local `http://127.0.0.1:8005/v1`
|
|
- Edge addr: `iop.ai.kr:18087`
|
|
- served model: `ornith:35b`
|
|
- capacity baseline 후보: `4`
|
|
- 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는 `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`
|
|
- Edge adapter endpoint: node-local `http://127.0.0.1:8004/v1`
|
|
- Edge addr: `iop.ai.kr:18087`
|
|
- Edge provider catalog type: `openai_compat`; provider runtime type remains `vllm-mlx`.
|
|
- served model: `mlx-community/gemma-4-26b-a4b-it-nvfp4`
|
|
- capacity baseline 후보: `5` (provider catalog capacity; current runtime headroom `--max-num-seqs 6`)
|
|
- runtime capacity/context/KV: `vllm-mlx=0.4.0`, python `/Users/dc_dev/vllm-env-0.4.0/bin/python`, `--continuous-batching`, `--max-num-seqs 6`, `--prefill-batch-size 6`, `--completion-batch-size 6`, `--chunked-prefill-tokens 1024`, `--disable-prefix-cache`, `--max-request-tokens 262144`, requested KV `262144x3` mapped to `--max-kv-size 786432`; agent/tool-call profile `--enable-auto-tool-choice`, `--tool-call-parser gemma4`, `--reasoning-parser gemma4`, `--default-chat-template-kwargs '{"enable_thinking":true}'`
|
|
- start script: `/Users/dc_dev/iop-dev-corp-field/start_vllm_mlx_8004.sh`
|
|
- workspace: `/Users/dc_dev`
|
|
- process manager: 2026-06-25 기준 detached `screen` session `vllm_mlx_8004`; 이 host는 Python `pyexpat` 로딩에 `DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib`가 필요하다.
|
|
|
|
DGX Spark nodes는 Linux/ARM64 bootstrap을 기본으로 한다. Mac Studio node는 macOS bootstrap을 기본으로 한다. Windows native bootstrap은 dev-corp provider pool 기본 대상이 아니다.
|
|
|
|
Mac Studio의 secondary `http://192.168.2.3:8005/v1` endpoint는 기본 Node/provider pool 검증 대상이 아니다. 별도 alias/capacity 정책이 확정된 후 추가한다.
|
|
|
|
## 런타임 설정/검증 상태
|
|
|
|
- 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-13 live status 기준 세 Node 모두 connected이며 provider snapshot은 Spark01 Ornith capacity `4`, Spark02 Ornith capacity `4`, Mac Studio Gemma4 capacity `5`이다. Public OpenAI-compatible route에서 `ornith:35b` 9/6, `gemma4:26b` 9/6 동시 요청이 모두 성공했고 완료 후 `in_flight=0`, `queued=0`, `healthy`로 회복했다. 사용자-facing 기본 base URL은 `https://digitalplatform.iop.ai.kr/v1`이다.
|
|
- Provider-pool passthrough 계약은 selected provider가 지원하는 OpenAI-compatible 표준 field와 provider extension field를 보존한다. `/v1/responses`는 capacity 성공 기준이 아니라 provider-dependent passthrough/relay 검증으로 분리한다. Provider가 지원하면 raw passthrough 성공을 확인하고, provider가 미지원하면 provider status/body가 IOP 변환 없이 relay되는지 확인한다.
|
|
|
|
## 명령
|
|
|
|
- setup:
|
|
- lint:
|
|
- 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: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`, `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를 기본 경로로 요구하지 않는다.
|
|
|
|
## 보조 검증
|
|
|
|
- `./scripts/e2e-smoke.sh`는 mock adapter 기반 보조 smoke로 사용한다.
|
|
- `make test-e2e`는 보조 smoke이며 full-cycle 실제 구동을 대체하지 않는다.
|
|
|
|
## 판정 기준
|
|
|
|
- node 등록 후 edge console에서 node가 조회된다.
|
|
- 같은 session에서 메시지 2회가 start, 기대 payload를 포함한 `[node-*-message]`, 같은 run의 complete 순서로 edge 화면에 도착한다.
|
|
- node 로컬 `[node-message]` payload 라인 목록과 edge `[node-*-message]` payload 라인 목록이 run별로 내용/순서까지 동일해야 한다.
|
|
- edge complete는 같은 run의 마지막 `[node-*-message]` 이후에만 정상이다.
|
|
- command 결과가 `[node-*-<command>]` 또는 명확한 성공/unsupported/error 출력으로 edge 화면에 표시된다.
|
|
- provider nodes는 mac-mini에서 내부 endpoint로 `/health`와 `/v1/models`가 성공해야 한다.
|
|
|
|
## 기준 출력 예시
|
|
|
|
```text
|
|
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
|
|
```
|
|
|
|
## 차단 기준
|
|
|
|
- mac-mini 또는 내부 provider node SSH 접근이 불가능하다.
|
|
- dev-corp Edge-Node TCP 후보 port 접근이 불가능하다.
|
|
- 필수 provider endpoint가 닫혀 있거나 `/v1/models`가 기대 모델을 노출하지 않는다.
|
|
- DGX Spark 02가 provider port down과 SSH banner exchange timeout을 동시에 보인다.
|
|
- Mac Studio vLLM-MLX node를 재시작해야 하는데 `8004` runtime의 `screen` session 또는 `DYLD_LIBRARY_PATH=/opt/homebrew/opt/expat/lib` 적용 여부를 확인할 수 없다.
|
|
- 외부 CLI profile 검증에 필요한 CLI 설치, 계정, provider 상태가 없다.
|
|
|
|
## 보고 항목
|
|
|
|
- 실행한 명령:
|
|
- 성공한 검증:
|
|
- 실패/차단된 검증:
|
|
- 생략 사유:
|
|
- 남은 위험:
|
|
|
|
## 금지 사항
|
|
|
|
- 사용자 실행 파이프라인 변경을 unit test만으로 완료 처리하지 않는다.
|
|
- `proto/gen/iop/*.pb.go` 생성 파일을 직접 수정하지 않는다.
|
|
- 사용자가 명시적으로 요청하지 않았는데 mac-mini 내부 경로를 Edge runtime 또는 Node `edge_addr` 기본값으로 승격하지 않는다.
|
|
- secret, token, API key 원문은 tracked 파일에 기록하지 않는다.
|