|
| 1 | +# Model Definition GraphQL 활용 개선 |
| 2 | + |
| 3 | +**Epic**: [FR-2588](https://lablup.atlassian.net/browse/FR-2588) |
| 4 | + |
| 5 | +## 개요 |
| 6 | + |
| 7 | +모델 서비스 상세 페이지(EndpointDetailPage)에 현재 리비전의 model definition 정보를 표시하고, |
| 8 | +custom 런타임 편집 시 vfolder 파일 파싱 대신 GraphQL `currentRevision.modelDefinition` 쿼리를 |
| 9 | +사용하도록 개선한다. 또한 편집(Update) 시 model-definition.yaml 덮어쓰기 전 확인 모달을 추가한다. |
| 10 | + |
| 11 | +## 문제 정의 |
| 12 | + |
| 13 | +1. **Model Definition 정보 미표시**: 모델 서비스 상세 페이지의 Service Info 카드에 현재 배포된 |
| 14 | + model definition 정보(모델명, 모델 경로, 서비스 설정)가 표시되지 않아, 운영자가 현재 서비스의 |
| 15 | + 구성을 확인하려면 별도로 vfolder 파일을 직접 열어봐야 한다. |
| 16 | + |
| 17 | +2. **vfolder 파일 파싱 의존성**: custom 런타임 편집 모드에서 기존 설정값을 로드할 때 vfolder의 |
| 18 | + model-definition.yaml 파일을 직접 다운로드하여 YAML 파싱하는 방식을 사용한다. 이는 불필요한 |
| 19 | + 네트워크 요청이며, 서버가 이미 `currentRevision.modelDefinition`으로 정규화된 데이터를 |
| 20 | + 제공하므로 GraphQL 쿼리를 활용하는 것이 더 안정적이다. |
| 21 | + |
| 22 | +3. **Update 시 덮어쓰기 경고 미표시**: 서비스 생성(Create) 시에는 기존 model-definition.yaml이 |
| 23 | + 있으면 덮어쓰기 확인 모달(`modal.confirm`)이 표시되지만, 편집(Update) 시에는 확인 없이 |
| 24 | + 즉시 파일을 덮어쓴다. 의도치 않은 설정 변경을 방지해야 한다. |
| 25 | + |
| 26 | +## 현재 상태 (As-Is) |
| 27 | + |
| 28 | +### EndpointDetailPage Service Info |
| 29 | +- 파일: `react/src/pages/EndpointDetailPage.tsx` |
| 30 | +- `Descriptions` 컴포넌트의 `items` 배열에 서비스 이름, 상태, 런타임 변형, 엔드포인트 등이 표시됨 |
| 31 | +- `currentRevision.modelDefinition` 관련 정보는 표시되지 않음 |
| 32 | +- GraphQL 쿼리에 `deploymentId` 변수가 이미 존재하며 `toGlobalId('ModelDeployment', serviceId)` 패턴으로 deployment를 조회 가능 |
| 33 | + |
| 34 | +### Custom 런타임 편집 모드 데이터 로드 |
| 35 | +- 파일: `react/src/components/ServiceLauncherPageContent.tsx` |
| 36 | +- `loadModelDefinitionForEdit` 함수가 vfolder에서 model-definition.yaml을 다운로드 |
| 37 | +- `baiClient.vfolder.request_download_token` → `fetch(downloadUrl)` → YAML 파싱 → form 필드 설정 |
| 38 | +- YAML 파싱 실패 시 기본값 유지 |
| 39 | + |
| 40 | +### Update 시 덮어쓰기 흐름 |
| 41 | +- 파일: `react/src/components/ServiceLauncherPageContent.tsx` |
| 42 | +- 편집 모드에서 command 모드일 때 즉시 업로드 (확인 없음) |
| 43 | +- 생성 모드에만 `modal.confirm`으로 덮어쓰기 확인이 있음 |
| 44 | + |
| 45 | +## GraphQL 스키마 참조 |
| 46 | + |
| 47 | +```graphql |
| 48 | +type ModelDeployment implements Node { |
| 49 | + id: ID! |
| 50 | + currentRevision: ModelRevision |
| 51 | +} |
| 52 | + |
| 53 | +type ModelRevision implements Node { |
| 54 | + modelDefinition: ModelDefinition |
| 55 | +} |
| 56 | + |
| 57 | +type ModelDefinition { |
| 58 | + models: [ModelConfig!]! |
| 59 | +} |
| 60 | + |
| 61 | +type ModelConfig { |
| 62 | + name: String! |
| 63 | + modelPath: String! |
| 64 | + service: ModelServiceConfig |
| 65 | + metadata: ModelMetadata |
| 66 | +} |
| 67 | + |
| 68 | +type ModelServiceConfig { |
| 69 | + preStartActions: [PreStartAction!]! |
| 70 | + startCommand: JSON! |
| 71 | + shell: String! |
| 72 | + port: Int! |
| 73 | + healthCheck: ModelHealthCheck |
| 74 | +} |
| 75 | + |
| 76 | +type ModelHealthCheck { |
| 77 | + interval: Float! |
| 78 | + path: String! |
| 79 | + maxRetries: Int! |
| 80 | + maxWaitTime: Float! |
| 81 | + expectedStatusCode: Int! |
| 82 | + initialDelay: Float! |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +## 요구사항 |
| 87 | + |
| 88 | +### 필수 (Must Have) |
| 89 | + |
| 90 | +#### 1. EndpointDetailPage에 Model Definition 정보 표시 |
| 91 | +- [ ] EndpointDetailPage의 GraphQL 쿼리에 `ModelDeployment` 노드 쿼리를 추가하여 `currentRevision.modelDefinition` 데이터를 조회 |
| 92 | +- [ ] Service Info 카드의 `Descriptions` items 배열에 model definition 관련 항목 추가 |
| 93 | +- [ ] 표시할 필드 (ModelConfig 기준): |
| 94 | + - `name` — 모델 이름 |
| 95 | + - `modelPath` — 모델 경로 |
| 96 | + - `service.startCommand` — 시작 명령어 |
| 97 | + - `service.port` — 서비스 포트 |
| 98 | + - `service.healthCheck.path` — 헬스체크 경로 |
| 99 | + - `service.healthCheck.initialDelay` — 초기 지연 시간 |
| 100 | + - `service.healthCheck.maxRetries` — 최대 재시도 횟수 |
| 101 | +- [ ] `metadata` 필드는 표시하지 않음 |
| 102 | +- [ ] `models` 배열이 비어있거나 `currentRevision`이 null인 경우 해당 항목을 표시하지 않거나 "-" 등의 빈 상태 표시 |
| 103 | + |
| 104 | +#### 2. Custom 런타임 편집 시 GraphQL 데이터 활용 |
| 105 | +- [ ] `loadModelDefinitionForEdit` 함수의 vfolder 파일 다운로드/YAML 파싱 방식을 `currentRevision.modelDefinition` GraphQL 쿼리 결과로 대체 |
| 106 | +- [ ] `ModelConfig.service` 필드에서 `startCommand`, `port`, `healthCheck` 등을 form 필드에 매핑 |
| 107 | +- [ ] GraphQL 데이터가 없는 경우(구 버전 서비스 등) 기존 vfolder 파싱 방식을 fallback으로 유지 |
| 108 | +- [ ] 불필요한 네트워크 요청(vfolder download token + file fetch) 제거 |
| 109 | + |
| 110 | +#### 3. Update 시 model-definition.yaml 덮어쓰기 확인 모달 |
| 111 | +- [ ] 편집(Update) 모드에서 command 모드로 저장 시, model-definition.yaml 업로드 전에 `modal.confirm`으로 덮어쓰기 확인 표시 |
| 112 | +- [ ] 생성 모드에서 이미 사용 중인 것과 동일한 UX 패턴 적용 |
| 113 | +- [ ] 사용자가 취소하면 저장 프로세스를 중단 |
| 114 | +- [ ] 확인 모달은 항상 표시 |
| 115 | + |
| 116 | +### 있으면 좋은 것 (Nice to Have) |
| 117 | +- [ ] `models` 배열에 여러 모델이 있는 경우 각 모델별로 접기/펼치기 가능한 UI 제공 |
| 118 | +- [ ] model definition 정보 영역을 별도 카드나 섹션으로 분리하여 가독성 향상 |
| 119 | + |
| 120 | +## 사용자 시나리오 |
| 121 | + |
| 122 | +- 운영자로서, 모델 서비스 상세 페이지에서 현재 배포된 모델의 시작 명령어, 포트, 헬스체크 설정을 확인할 수 있어서, 서비스 문제 발생 시 설정을 빠르게 확인할 수 있다. |
| 123 | +- 운영자로서, custom 런타임 서비스를 편집할 때 기존 설정값이 GraphQL에서 안정적으로 로드되어, vfolder 파일 접근 실패에 의존하지 않고 정확한 값을 확인하고 수정할 수 있다. |
| 124 | +- 운영자로서, 서비스 편집 시 model-definition.yaml 파일을 덮어쓰기 전에 확인 대화상자를 통해 의도하지 않은 설정 변경을 방지할 수 있다. |
| 125 | + |
| 126 | +## 인수 조건 |
| 127 | + |
| 128 | +### Model Definition 표시 |
| 129 | +- [ ] EndpointDetailPage의 Service Info 카드에 model definition 정보가 Descriptions 항목으로 표시된다 |
| 130 | +- [ ] `currentRevision`이 null인 서비스에서는 model definition 항목이 표시되지 않거나 빈 상태("-")로 표시된다 |
| 131 | +- [ ] `metadata` 필드는 UI에 노출되지 않는다 |
| 132 | + |
| 133 | +### GraphQL 데이터 로드 |
| 134 | +- [ ] custom 런타임 편집 모드 진입 시 GraphQL `currentRevision.modelDefinition`에서 데이터를 가져와 form 필드가 올바르게 채워진다 |
| 135 | +- [ ] GraphQL에 `modelDefinition`이 없는 경우 기존 vfolder 파싱 fallback이 동작한다 |
| 136 | +- [ ] 편집 폼의 startCommand, port, healthCheck path, initialDelay, maxRetries 필드에 기존 값이 정확히 표시된다 |
| 137 | + |
| 138 | +### 덮어쓰기 확인 모달 |
| 139 | +- [ ] 편집 모드에서 command 모드로 저장 시 확인 모달이 표시된다 |
| 140 | +- [ ] 확인 클릭 시 정상적으로 저장이 진행된다 |
| 141 | +- [ ] 취소 클릭 시 저장이 중단되고 폼 상태가 유지된다 |
| 142 | +- [ ] 생성 모드의 기존 덮어쓰기 확인 동작이 변경되지 않는다 |
| 143 | + |
| 144 | +## 범위 밖 (Out of Scope) |
| 145 | + |
| 146 | +- vLLM/SGLang 런타임의 model definition 편집 개선 (custom 런타임만 해당) |
| 147 | +- model definition 편집을 위한 전용 모달이나 페이지 제작 |
| 148 | +- `ModelMetadata` 필드의 UI 표시 |
| 149 | +- `preStartActions` 필드의 UI 표시 및 편집 |
| 150 | +- revision 목록 조회 및 과거 revision의 model definition 비교 |
| 151 | +- model-definition.yaml 파일의 직접 편집 (코드 에디터 등) |
| 152 | + |
| 153 | +## 관련 파일 |
| 154 | + |
| 155 | +- `react/src/pages/EndpointDetailPage.tsx` — Service Info Descriptions 항목 추가, GraphQL 쿼리에 ModelDeployment.currentRevision.modelDefinition 추가 |
| 156 | +- `react/src/components/ServiceLauncherPageContent.tsx` — `loadModelDefinitionForEdit` 함수 수정 (GraphQL 활용), Update 시 modal.confirm 추가 |
| 157 | +- `data/schema.graphql` — ModelDeployment, ModelRevision, ModelDefinition, ModelServiceConfig 타입 참조 |
| 158 | + |
| 159 | +## 관련 이슈 |
| 160 | + |
| 161 | +- FR-2581: 엔드포인트 목록 및 상세 페이지에 런타임 변형 표시 (상위 이슈) |
0 commit comments