Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions sdk_v2/cpp/src/inferencing/generative/genai_model_instance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ OgaModel& GenAIModelInstance::GetOgaModel() {
return *oga_model_;
}

std::string GenAIModelInstance::GetTag(const char* tag_name) const {
if (!oga_model_) {
return {};
}
OgaString tag = oga_model_->GetTag(tag_name);
const char* p = tag;
return p ? std::string(p) : std::string();
}

OgaTokenizer& GenAIModelInstance::GetOgaTokenizer() {
if (!tokenizer_) {
FL_THROW(FOUNDRY_LOCAL_ERROR_INTERNAL, "OGA tokenizer is null");
Expand Down
5 changes: 5 additions & 0 deletions sdk_v2/cpp/src/inferencing/generative/genai_model_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class GenAIModelInstance {
ExecutionProvider EP() const { return ep_; }
bool IsMultiModal() const;

/// Query a tag from the GenAI model (reads genai_config.json with model-family fallback).
/// Returns the tag value or empty string if not found. Supported keys:
/// "tool_call_start", "tool_call_end", "reasoning_start", "reasoning_end".
std::string GetTag(const char* tag_name) const;

/// Access the underlying OGA objects (for future chat generation work).
OgaModel& GetOgaModel();
OgaTokenizer& GetOgaTokenizer();
Expand Down
31 changes: 31 additions & 0 deletions sdk_v2/cpp/src/model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,37 @@ void Model::Load(ExecutionProvider ep) {
if (result.status == ModelLoadManager::LoadStatus::kModelNotFound) {
FL_THROW(FOUNDRY_LOCAL_ERROR_INTERNAL, "model not found at path: " + local_path_);
}

// Enrich ModelInfo with metadata from the loaded GenAI model (genai_config.json + fallback map).
// This makes tool/reasoning tags available via ModelInfo regardless of whether they came from
// catalog metadata, so downstream code doesn't need to know about multiple metadata sources.
if (result.model && result.status == ModelLoadManager::LoadStatus::kSuccess) {
auto enrich = [&](const char* tag_name, const char* prop_key) {
std::string val = result.model->GetTag(tag_name);
if (!val.empty() && !info_.GetPropertyStr(prop_key)) {
info_.string_properties[prop_key] = std::move(val);
}
};

enrich("tool_call_start", FOUNDRY_LOCAL_MODEL_PROP_TOOL_CALL_START_STR);
enrich("tool_call_end", FOUNDRY_LOCAL_MODEL_PROP_TOOL_CALL_END_STR);
enrich("reasoning_start", FOUNDRY_LOCAL_MODEL_PROP_REASONING_START_STR);
enrich("reasoning_end", FOUNDRY_LOCAL_MODEL_PROP_REASONING_END_STR);

// Infer support flags from the presence of start tokens
if (!info_.GetPropertyInt(FOUNDRY_LOCAL_MODEL_PROP_SUPPORTS_TOOL_CALLING_INT)) {
const auto* tc = info_.GetPropertyStr(FOUNDRY_LOCAL_MODEL_PROP_TOOL_CALL_START_STR);
if (tc && !tc->empty()) {
info_.int_properties[FOUNDRY_LOCAL_MODEL_PROP_SUPPORTS_TOOL_CALLING_INT] = 1;
}
}
if (!info_.GetPropertyInt(FOUNDRY_LOCAL_MODEL_PROP_SUPPORTS_REASONING_INT)) {
const auto* rs = info_.GetPropertyStr(FOUNDRY_LOCAL_MODEL_PROP_REASONING_START_STR);
if (rs && !rs->empty()) {
info_.int_properties[FOUNDRY_LOCAL_MODEL_PROP_SUPPORTS_REASONING_INT] = 1;
}
}
}
}

void Model::Unload() {
Expand Down
Loading