NAME

Langertha::ModelProbe - Reads model-scoped capability facts from a provider's own model metadata

VERSION

version 0.503

SYNOPSIS

# Normally reached through the engine (ADR 0032):
my $learned = await $engine->probe_model_capabilities_f;
# { 'google/gemma-4-26b-a4b' => { image_input => 1 }, ... }

# The inbound door itself, for a metadata document already in hand:
my $facts = Langertha::ModelProbe->extract( lmstudio => $data, \@models );

DESCRIPTION

The inbound door for model metadata: it reads what a provider's own metadata endpoint says about a model and turns it into capability facts in the Langertha::Role::Capabilities vocabulary. It is keyed by a per-concern format tag, the engine's model_metadata_format (ADR 0032), the same way the tool value objects are keyed by tool_wire_format (ADR 0001):

  • openrouter - GET /models, data[].architecture.input_modalities (image in the list means the model sees images). Facts are keyed by id and canonical_slug.

  • mistral - GET /v1/models, data[].capabilities.vision. Facts are keyed by id and by each entry of aliases; an entry's own id wins over another entry's alias.

  • lmstudio - LM Studio's native GET /api/v1/models, models[].capabilities.vision. Facts are keyed by key and by the id of each loaded_instances entry. Entries without capabilities (embedding models) give no fact.

  • tsystems - T-Systems AI Foundation Services GET /v2/models, data[].meta_data.input_modalities, a nullable array of strings; image in it, matched case-insensitively because the spelling is not documented, means the model sees images. Facts are keyed by id. An entry without meta_data or with a missing or null input_modalities gives no fact. Shaped from the provider's public OpenAPI document only: no key exists to verify it live.

  • ollama - POST /api/show with { model }, one request per model; the capabilities array (vision in it means the model sees images). A server too old to report capabilities gives no fact.

  • llamacpp - GET /props, modalities.vision. llama.cpp serves one model whatever id the request names, so the fact is keyed by every model id the probe was asked about. A server without modalities gives no fact.

Only capabilities the metadata states outright are read, and in this version that is image_input alone ("probed_capabilities"). A document that does not carry the field yields no fact for that model, never a false one.

This class has no instances; all methods are class methods. It does no network I/O: the engine sends the request ("probe_model_capabilities_f" in Langertha::Role::Capabilities).

probed_capabilities

my @caps = Langertha::ModelProbe->probed_capabilities;   # ('image_input')

The capability names a probe can learn. Everything else stays with the static layers of "engine_capabilities" in Langertha::Role::Capabilities.

is_known_format

Langertha::ModelProbe->is_known_format('ollama');   # 1

http_method

my $method = Langertha::ModelProbe->http_method('ollama');   # 'POST'

per_model

True when the format answers for one model per request (ollama: the request body names the model); false when one request answers for the whole server.

is_catalogue

Langertha::ModelProbe->is_catalogue('openrouter');   # 1
Langertha::ModelProbe->is_catalogue('llamacpp');     # 0

True when one document names every model it describes (openrouter, mistral, lmstudio, tsystems), so a single probe can learn the whole catalogue (models => 'all'). False for ollama (one model per request) and llamacpp (the document does not name its model).

extract

my $facts = Langertha::ModelProbe->extract( $format, $data, \@models );

Reads a decoded metadata document and returns { $model_id => { image_input => 0|1 } }. \@models are the ids the probe asked about: the ollama and llamacpp documents do not name the model, so their fact is keyed by these. Croaks on an unknown format; a document of an unexpected shape gives an empty HashRef.

server_root_url

Langertha::ModelProbe->server_root_url('http://localhost:11434/v1');
# http://localhost:11434

Strips a trailing /v1 (and slash) from an OpenAI-compatible base URL, for the self-hosted servers whose metadata lives beside /v1 (Ollama /api/show, LM Studio /api/v1/models, llama.cpp /props).

lookup_ids

my @ids = Langertha::ModelProbe->lookup_ids( ollama => 'llava' );
# ('llava', 'llava:latest')

The store keys, in order, under which a fact for $model may have been learned: the exact id first, then the format's equivalent spelling. For ollama a missing tag is :latest (llava and llava:latest find each other). For openrouter a routing variant suffix (openai/gpt-4o:online, :free, :nitro, ...) falls back to the base id when the variant itself was not listed. Other formats match exactly. A non-string or empty id gives an empty list.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.