Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 5050bc3

Browse files
committed
fix: emit error if engine is not ready
1 parent 70af60e commit 5050bc3

File tree

8 files changed

+70
-35
lines changed

8 files changed

+70
-35
lines changed

engine/cli/commands/engine_get_cmd.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#include "engine_get_cmd.h"
2+
#include <json/reader.h>
3+
#include <json/value.h>
24
#include <iostream>
35

46
#include "httplib.h"
5-
#include "json/json.h"
67
#include "server_start_cmd.h"
78
#include "utils/logging_utils.h"
89

@@ -29,7 +30,6 @@ void EngineGetCmd::Exec(const std::string& host, int port,
2930
auto res = cli.Get("/v1/engines/" + engine_name);
3031
if (res) {
3132
if (res->status == httplib::StatusCode::OK_200) {
32-
// CLI_LOG(res->body);
3333
Json::Value v;
3434
Json::Reader reader;
3535
reader.parse(res->body, v);
@@ -39,7 +39,8 @@ void EngineGetCmd::Exec(const std::string& host, int port,
3939
v["status"].asString()});
4040

4141
} else {
42-
CLI_LOG_ERROR("Failed to get engine list with status code: " << res->status);
42+
CLI_LOG_ERROR(
43+
"Failed to get engine list with status code: " << res->status);
4344
return;
4445
}
4546
} else {

engine/controllers/models.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ void Models::GetModel(const HttpRequestPtr& req,
162162
config::YamlHandler yaml_handler;
163163
auto model_entry = modellist_handler.GetModelInfo(model_id);
164164
if (model_entry.has_error()) {
165-
// CLI_LOG("Error: " + model_entry.error());
166165
ret["id"] = model_id;
167166
ret["object"] = "model";
168167
ret["result"] = "Fail to get model information";
@@ -348,6 +347,34 @@ void Models::StartModel(
348347
auto model_handle = (*(req->getJsonObject())).get("model", "").asString();
349348
auto custom_prompt_template =
350349
(*(req->getJsonObject())).get("prompt_template", "").asString();
350+
auto model_entry = model_service_->GetDownloadedModel(model_handle);
351+
if (!model_entry.has_value()) {
352+
Json::Value ret;
353+
ret["message"] = "Cannot find model: " + model_handle;
354+
auto resp = cortex_utils::CreateCortexHttpJsonResponse(ret);
355+
resp->setStatusCode(drogon::k400BadRequest);
356+
callback(resp);
357+
return;
358+
}
359+
auto engine_name = model_entry.value().engine;
360+
auto engine_entry = engine_service_->GetEngineInfo(engine_name);
361+
if (engine_entry.has_error()) {
362+
Json::Value ret;
363+
ret["message"] = "Cannot find engine: " + engine_name;
364+
auto resp = cortex_utils::CreateCortexHttpJsonResponse(ret);
365+
resp->setStatusCode(drogon::k400BadRequest);
366+
callback(resp);
367+
return;
368+
}
369+
if (engine_entry->status != "Ready") {
370+
Json::Value ret;
371+
ret["message"] = "Engine is not ready! Please install first!";
372+
auto resp = cortex_utils::CreateCortexHttpJsonResponse(ret);
373+
resp->setStatusCode(drogon::k400BadRequest);
374+
callback(resp);
375+
return;
376+
}
377+
351378
auto result = model_service_->StartModel(
352379
config.apiServerHost, std::stoi(config.apiServerPort), model_handle,
353380
custom_prompt_template);

engine/controllers/models.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <drogon/HttpController.h>
44
#include <trantor/utils/Logger.h>
5+
#include "services/engine_service.h"
56
#include "services/model_service.h"
67

78
using namespace drogon;
@@ -32,8 +33,9 @@ class Models : public drogon::HttpController<Models, false> {
3233
ADD_METHOD_TO(Models::GetModelStatus, "/v1/models/status/{1}", Get);
3334
METHOD_LIST_END
3435

35-
explicit Models(std::shared_ptr<ModelService> model_service)
36-
: model_service_{model_service} {}
36+
explicit Models(std::shared_ptr<ModelService> model_service,
37+
std::shared_ptr<EngineService> engine_service)
38+
: model_service_{model_service}, engine_service_{engine_service} {}
3739

3840
void PullModel(const HttpRequestPtr& req,
3941
std::function<void(const HttpResponsePtr&)>&& callback);
@@ -69,4 +71,5 @@ class Models : public drogon::HttpController<Models, false> {
6971

7072
private:
7173
std::shared_ptr<ModelService> model_service_;
74+
std::shared_ptr<EngineService> engine_service_;
7275
};

engine/database/models.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#pragma once
22

3+
#include <SQLiteCpp/Database.h>
34
#include <trantor/utils/Logger.h>
45
#include <string>
56
#include <vector>
6-
#include "SQLiteCpp/SQLiteCpp.h"
77
#include "utils/result.hpp"
88

99
namespace cortex::db {
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import pytest
22
import requests
3-
from test_runner import popen
4-
from test_runner import start_server, stop_server, run
3+
from test_runner import run, start_server, stop_server
54

65

76
class TestApiModelStart:
@@ -14,14 +13,18 @@ def setup_and_teardown(self):
1413
raise Exception("Failed to start server")
1514
run("Install Engine", ["engines", "install", "llama-cpp"], timeout=None)
1615
run("Delete model", ["models", "delete", "tinyllama:gguf"])
17-
run("Pull model", ["pull", "tinyllama:gguf"], timeout=None,)
16+
run(
17+
"Pull model",
18+
["pull", "tinyllama:gguf"],
19+
timeout=None,
20+
)
1821

1922
yield
2023

2124
# Teardown
2225
stop_server()
2326

2427
def test_models_start_should_be_successful(self):
25-
json_body = {'model': 'tinyllama:gguf'}
26-
response = requests.post("http://localhost:3928/models/start", json = json_body)
28+
json_body = {"model": "tinyllama:gguf"}
29+
response = requests.post("http://localhost:3928/models/start", json=json_body)
2730
assert response.status_code == 200, f"status_code: {response.status_code}"
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22
import requests
3-
from test_runner import start_server, stop_server
3+
from test_runner import run, start_server, stop_server
44

55

66
class TestApiModelStop:
@@ -12,14 +12,15 @@ def setup_and_teardown(self):
1212
if not success:
1313
raise Exception("Failed to start server")
1414

15+
run("Install Engine", ["engines", "install", "llama-cpp"], timeout=None)
1516
yield
1617

1718
# Teardown
1819
stop_server()
1920

2021
def test_models_stop_should_be_successful(self):
21-
json_body = {'model': 'tinyllama:gguf'}
22-
response = requests.post("http://localhost:3928/models/start", json = json_body)
22+
json_body = {"model": "tinyllama:gguf"}
23+
response = requests.post("http://localhost:3928/models/start", json=json_body)
2324
assert response.status_code == 200, f"status_code: {response.status_code}"
24-
response = requests.post("http://localhost:3928/models/stop", json = json_body)
25+
response = requests.post("http://localhost:3928/models/stop", json=json_body)
2526
assert response.status_code == 200, f"status_code: {response.status_code}"

engine/main.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void RunServer(std::optional<int> port) {
9595

9696
// initialize custom controllers
9797
auto engine_ctl = std::make_shared<Engines>(engine_service);
98-
auto model_ctl = std::make_shared<Models>(model_service);
98+
auto model_ctl = std::make_shared<Models>(model_service, engine_service);
9999
auto event_ctl = std::make_shared<Events>(event_queue_ptr);
100100
auto pm_ctl = std::make_shared<ProcessManager>();
101101

engine/services/model_service.cc

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,28 +198,28 @@ cpp::result<std::string, std::string> ModelService::HandleCortexsoModel(
198198

199199
std::optional<config::ModelConfig> ModelService::GetDownloadedModel(
200200
const std::string& modelId) const {
201-
auto models_path = file_manager_utils::GetModelsContainerPath();
202-
if (!std::filesystem::exists(models_path) ||
203-
!std::filesystem::is_directory(models_path)) {
201+
202+
cortex::db::Models modellist_handler;
203+
config::YamlHandler yaml_handler;
204+
auto model_entry = modellist_handler.GetModelInfo(modelId);
205+
if (!model_entry.has_value()) {
204206
return std::nullopt;
205207
}
206208

207-
for (const auto& entry : std::filesystem::directory_iterator(models_path)) {
208-
if (entry.is_regular_file() &&
209-
entry.path().filename().string() == modelId &&
210-
entry.path().extension() == ".yaml") {
211-
try {
212-
config::YamlHandler handler;
213-
handler.ModelConfigFromFile(entry.path().string());
214-
auto model_conf = handler.GetModelConfig();
215-
return model_conf;
216-
} catch (const std::exception& e) {
217-
LOG_ERROR << "Error reading yaml file '" << entry.path().string()
218-
<< "': " << e.what();
219-
}
220-
}
209+
try {
210+
config::YamlHandler yaml_handler;
211+
namespace fs = std::filesystem;
212+
namespace fmu = file_manager_utils;
213+
yaml_handler.ModelConfigFromFile(
214+
fmu::ToAbsoluteCortexDataPath(
215+
fs::path(model_entry.value().path_to_model_yaml))
216+
.string());
217+
return yaml_handler.GetModelConfig();
218+
} catch (const std::exception& e) {
219+
LOG_ERROR << "Error reading yaml file '" << model_entry->path_to_model_yaml
220+
<< "': " << e.what();
221+
return std::nullopt;
221222
}
222-
return std::nullopt;
223223
}
224224

225225
cpp::result<DownloadTask, std::string> ModelService::HandleDownloadUrlAsync(

0 commit comments

Comments
 (0)