GenAI 모델 배포
| 필드 | 값 |
|---|---|
| 범주 | GenAI |
| 난이도 | 초급 |
| 예상 소요 시간 | 15-20 minutes |
| 레이블 | genai, server, llm, vlm, asr, http |
대부분의 애플리케이션의 경우 GenAIServer와 OpenAI 호환 POST /v1/chat/completions 엔드포인트로 시작합니다. 임베디드 애플리케이션 로직이 동일한 프로세스에서 모델 호출을 소유해야 하는 경우 직접 model.run(request) 호출을 사용합니다.
전체 엔드포인트 및 요청 계약은 GenAI 서버 참조를 참조하십시오.
둘러보기
서버 구성
호스트와 포트를 선택합니다. 기본 호스트는 0.0.0.0이며, 이는 Modalix 장치에 연결할 수 있는 다른 시스템의 연결을 허용합니다.
genai::GenAIServerOptions options;
options.host = args.host;
options.port = args.port;
genai::GenAIServer server(options);
모델 디렉터리 등록
배포된 각 모델 디렉터리를 배포된 이름과 함께 추가합니다. 이 튜토리얼에서는 llm, vlm 및 asr을 등록합니다. 배포된 이름은 클라이언트가 model 필드에 보내는 이름입니다.
if (!args.llm.empty()) {
server.add_model(args.llm, "llm");
}
if (!args.vlm.empty()) {
server.add_model(args.vlm, "vlm");
}
if (!args.asr.empty()) {
server.add_model(args.asr, "asr");
}
std::cout << "registered models:";
for (const auto& name : server.model_names()) {
std::cout << " " << name;
}
std::cout << "\n";
서비스 시작
차단되는 전경 프로세스의 경우 serve()를 호출하고, 애플리케이션이 프로세스의 나머지 수명 주기를 소유하는 경우 start()를 호출합니다.
서버가 시작된 후 GET /v1/models를 사용하여 등록된 모델 이름을 확인합니다.
curl http://<modalix-ip>:9998/v1/models
응답에는 이 튜토리얼에서 등록된 배포된 이름인 llm, vlm 및 asr이 포함되어야 합니다.
std::cout << "serving on http://" << options.host << ":" << options.port << "\n";
std::cout << "try: curl http://<modalix-ip>:" << options.port << "/v1/models\n";
server.serve();
실행
Modalix DevKit에서 Hugging Face에서 LLM, VLM 및 ASR 모델을 LLiMa CLI를 사용하여 다운로드합니다.
llima pull Qwen3-4B-Instruct-2507-GPTQ-a16w4
llima pull Qwen3-VL-4B-Instruct-GPTQ-a16w4
llima pull whisper-small-a16w8
Modalix에서 세 개의 DevKit 로컬 모델 디렉터리가 모두 있는 상태로 서버를 시작합니다.
C++ (prebuilt):
./lib/sima-neat/tutorials/tutorial_021_serve_genai_models \
--llm /media/nvme/llima/models/Qwen3-4B-Instruct-2507-GPTQ-a16w4 \
--vlm /media/nvme/llima/models/Qwen3-VL-4B-Instruct-GPTQ-a16w4 \
--asr /media/nvme/llima/models/whisper-small-a16w8
C++ (build from source):
./build.sh --target tutorial_021_serve_genai_models
./build/tutorials-standalone/tutorial_021_serve_genai_models \
--llm /media/nvme/llima/models/Qwen3-4B-Instruct-2507-GPTQ-a16w4 \
--vlm /media/nvme/llima/models/Qwen3-VL-4B-Instruct-GPTQ-a16w4 \
--asr /media/nvme/llima/models/whisper-small-a16w8
개발 중에 하위 집합만 배포하려는 경우 --vlm 또는 --asr을 제거합니다.
서버가 실행 중인 후에는 먼저 모든 배포된 이름이 등록되었는지 확인합니다.
curl http://<modalix-ip>:9998/v1/models
그런 다음 클라이언트에서 엔드포인트를 호출합니다. <modalix-ip>를 Modalix 장치의 IP 주소 또는 호스트 이름으로 바꿉니다.
아래의 요청 클라이언트는 Python requests를 사용하여 응답을 스트리밍하고, 서버 측 TTFT와 평균, 최소 및 최대 토큰당 TPS를 보고할 때 출력합니다.
LLM에 대한 텍스트 요청
python3 share/sima-neat/tutorials/021_serve_genai_models/request_chat_completion_text.py \
--server-ip <modalix-ip> \
--model llm \
"Give me three tips for designing a small REST API."
LLM에 대한 도구 호출 요청
OpenAI와 호환되는 POST /v1/chat/completions 엔드포인트와 Ollama와 호환되는 POST /api/chat 엔드포인트는 tools 배열에서 함수 정의를 허용합니다. 각 항목에는 type: "function", function 객체 및 비어 있지 않은 문자열 function.name이 있어야 합니다. 함수 설명과 JSON 스키마 매개변수는 function 객체 내에 포함될 수 있습니다.
curl http://<modalix-ip>:9998/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llm",
"messages": [
{"role": "user", "content": "What is the weather in Paris?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}
],
"tool_choice": "auto",
"stream": false
}'
tool_choice를 "auto"로 설정하여 모델이 선언된 도구를 선택하도록 하거나, "none"으로 설정하여 도구 프롬프트 및 구문 분석을 비활성화합니다. tool_choice를 생략하거나 null로 설정하면 tools가 비어 있지 않은 경우 "auto"와 동일하게 작동합니다. 잘못된 형식의 도구 정의, 배열이 아닌 tools 및 지원되지 않는 tool_choice 값 또는 유형은 HTTP 400 오류와 함께 invalid_request_error를 반환합니다. 동일한 도구 정의 및 도구 선택 검증은 추론이 시작되기 전에 직접 GenerationRequest 호출에도 적용됩니다.