mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-15 01:54:43 +00:00
Update generate pipeline to add OpenAI api as an additional backend (for comparison testing), add brewery coordinates (#244)
* add brewery coordinates * Add openai mode * Add coordinates to schema * Fix C++ review findings in pipeline: k-prefixed enum values, include ordering, populated validation error messages, conventional const notation, and endl replaced with newline
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
@@ -37,13 +38,20 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
"Number of layers to offload to GPU");
|
||||
};
|
||||
|
||||
// --mocked and --model are mutually exclusive; validation is enforced below
|
||||
// rather than at registration to produce a clear diagnostic message.
|
||||
// --mocked, --model, and --openai are mutually exclusive; validation is
|
||||
// enforced below rather than at registration to produce a clear
|
||||
// diagnostic message.
|
||||
auto add_generator_options = [&]() -> void {
|
||||
opt("mocked", prog_opts::bool_switch(),
|
||||
"Use mocked generator for brewery/user data");
|
||||
opt("model,m", prog_opts::value<std::string>()->default_value(""),
|
||||
"Path to LLM model (gguf)");
|
||||
opt("openai", prog_opts::bool_switch(),
|
||||
"Use the OpenAI API (Chat Completions) for brewery/user data. "
|
||||
"Requires the OPENAI_API_KEY environment variable.");
|
||||
opt("openai-model",
|
||||
prog_opts::value<std::string>()->default_value("gpt-4o-mini"),
|
||||
"OpenAI model ID used when --openai is set");
|
||||
};
|
||||
|
||||
auto add_pipeline_options = [&]() -> void {
|
||||
@@ -109,14 +117,19 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
|
||||
const bool use_mocked = var_map["mocked"].as<bool>();
|
||||
const std::string model_path = var_map["model"].as<std::string>();
|
||||
const bool use_openai = var_map["openai"].as<bool>();
|
||||
const int n_gpu_layers = var_map["n-gpu-layers"].as<int>();
|
||||
|
||||
// Enforce mutual exclusivity before any further configuration is
|
||||
// applied.
|
||||
if (use_mocked && !model_path.empty()) {
|
||||
const int selected_generator_count =
|
||||
(use_mocked ? 1 : 0) + (!model_path.empty() ? 1 : 0) +
|
||||
(use_openai ? 1 : 0);
|
||||
|
||||
if (selected_generator_count > 1) {
|
||||
const std::string msg =
|
||||
"Invalid arguments: --mocked and --model are mutually "
|
||||
"exclusive";
|
||||
"Invalid arguments: --mocked, --model, and --openai are "
|
||||
"mutually exclusive";
|
||||
if (logger) {
|
||||
logger->Log(LogDTO{.level = LogLevel::Error,
|
||||
.phase = PipelinePhase::Startup,
|
||||
@@ -127,10 +140,10 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!use_mocked && model_path.empty()) {
|
||||
if (selected_generator_count == 0) {
|
||||
const std::string msg =
|
||||
"Invalid arguments: either --mocked or --model must be "
|
||||
"specified";
|
||||
"Invalid arguments: exactly one of --mocked, --model, or "
|
||||
"--openai must be specified";
|
||||
if (logger) {
|
||||
logger->Log(LogDTO{.level = LogLevel::Error,
|
||||
.phase = PipelinePhase::Startup,
|
||||
@@ -141,8 +154,9 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Prompt directory is only meaningful for live inference — the mock
|
||||
// generator has no use for it and should not require it to be present.
|
||||
// Prompt directory is only meaningful for live inference (Llama or
|
||||
// OpenAI) — the mock generator has no use for it and should not
|
||||
// require it to be present.
|
||||
if (!use_mocked && options.pipeline.prompt_dir.empty()) {
|
||||
const std::string msg =
|
||||
"Invalid arguments: --prompt-dir is required when not using "
|
||||
@@ -157,8 +171,29 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
options.generator.use_mocked = use_mocked;
|
||||
if (use_openai) {
|
||||
const char* api_key_env = std::getenv("OPENAI_API_KEY");
|
||||
if (api_key_env == nullptr || api_key_env[0] == '\0') {
|
||||
const std::string msg =
|
||||
"Invalid arguments: the OPENAI_API_KEY environment "
|
||||
"variable must be set when using --openai";
|
||||
if (logger) {
|
||||
logger->Log({.level = LogLevel::Error,
|
||||
.phase = PipelinePhase::Startup,
|
||||
.message = msg});
|
||||
} else {
|
||||
std::cerr << msg << '\n';
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
options.generator.openai_api_key = api_key_env;
|
||||
}
|
||||
|
||||
options.generator.mode = use_mocked ? GeneratorMode::kMock
|
||||
: use_openai ? GeneratorMode::kOpenAI
|
||||
: GeneratorMode::kLlama;
|
||||
options.generator.model_path = model_path;
|
||||
options.generator.openai_model = var_map["openai-model"].as<std::string>();
|
||||
|
||||
// Only populate sampling config when the user explicitly overrides at
|
||||
// least one value. Leaving it as std::nullopt lets LlamaGenerator fall
|
||||
@@ -172,10 +207,11 @@ std::optional<ApplicationOptions> ParseArguments(
|
||||
|
||||
if (user_provided_sampling) {
|
||||
// Warn but do not fail — the run is still valid, the flags are just
|
||||
// silently irrelevant when no model is loaded.
|
||||
if (use_mocked) {
|
||||
// silently irrelevant when no local model is loaded.
|
||||
if (options.generator.mode != GeneratorMode::kLlama) {
|
||||
const std::string msg =
|
||||
"Sampling parameters are ignored when using --mocked";
|
||||
"Sampling parameters are ignored unless using --model "
|
||||
"(Llama)";
|
||||
if (logger) {
|
||||
logger->Log(LogDTO{.level = LogLevel::Warn,
|
||||
.phase = PipelinePhase::Startup,
|
||||
|
||||
Reference in New Issue
Block a user