feat: pluggable image-to-text service with OpenAI vision backend#1038
Merged
cybermaggedon merged 1 commit intoJul 12, 2026
Merged
Conversation
Contributor License Agreement ✅All contributors have signed the CLA. Thank you! |
sunnyadn
force-pushed
the
feat/image-to-text
branch
from
July 11, 2026 10:41
062f719 to
a2e8300
Compare
cybermaggedon
self-requested a review
July 12, 2026 11:14
cybermaggedon
approved these changes
Jul 12, 2026
cybermaggedon
left a comment
Contributor
There was a problem hiding this comment.
🤯 exemplary work 🤯! Uses all the existing code-base patterns, and extends to add patterns for a new processing class
Contributor
|
Released in v2.7.5 |
Contributor
|
Super piece of work, thanks so much @sunnyadn |
cybermaggedon
pushed a commit
to trustgraph-ai/trustgraph-templates
that referenced
this pull request
Jul 12, 2026
Templates-side wiring for the image-to-text service added in trustgraph-ai/trustgraph#1038. Mirrors the keyword-index component surface (#297): optional component deploying the processor from the standard flow image, plus inert flow-blueprint wiring imported by the document-store flow module.
Contributor
|
Confirmed working end-to-end. I used Gemma4 26B A4B hosted in llama.cpp... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #879
Implements the full vertical from the issue spec: schema,
ImageToTextServicebase class, OpenAI vision backend, gateway endpoint, client API, andtg-describe-imageCLI. Targets release/v2.7.What's included
schema/services/image_to_text.py):ImageToTextRequest {image, mime_type, prompt, system}/ImageToTextResponse {error, description, in_token, out_token, model}, dataclass style matchingllm.py. Theimagefield carries base64 ASCII asstr: the pub/sub wire is JSON on all three backends, so raw binary can't ride abytesfield, and base64 is what the vision API consumes anyway. No queue-name constants: flow-scoped services get queues from blueprintinterfacesat runtime, same as text-completion.base/image_to_text_service.py): mirrorsLlmService(ConsumerSpec/ProducerSpec,ParameterSpec("model"), duration/model metrics,TooManyRequestsre-raise, structuredimage-to-text-errorfallback). Subclasses implementdescribe_image(image, mime_type, prompt, system, model) -> ImageDescriptionResult. No streaming machinery: the issue lists streaming as future work.model/image_to_text/openai/): data-URI content block, prompt defaults to "Describe this image", rate-limit mapping copied from the text-completion openai backend. Default model isgpt-5-mini(vision-capable, cheapest current tier) instead of the issue'sgpt-4oexample; overridable via-m, config, or the per-flowmodelparameter. No temperature parameter: the gpt-5 family rejects non-default temperature, so the backend never sends one.ImageToTextRequestor, dispatcher-table entry. No new route file: the generic/service/{kind}route covers it. Registered as its own IAM capabilityimage-to-text(reranker precedent), so text-only roles don't silently gain image calls.image_to_text()on all four surfaces (sync/async REST + sync/async websocket) plusImageToTextResultinapi/types.py. Clients accept raw bytes and do the base64 encoding. One deliberate divergence from the text_completion siblings: the websocket methods check the response body for an error dict and raise. The mux delivers ServiceRequestor errors inside theresponsefield, so without this check a backend failure would come back as an empty description instead of an exception.tg-describe-image(name from the issue):--image photo.jpgworks as written; mime type is guessed from the filename, overridable with--mime-type.mime_type,in_token): there is no key-conversion layer in the gateway, so the kebab-case in the sibling text-completion spec doesn't match what its translator actually emits. Can align with the sibling instead if you prefer spec-internal consistency.Testing
gateway-error: Timeoutat the 30s gateway timeout, no hang. A flow without the interface returnsThis kind not supported by flowimmediately.Out of scope
Per the issue's future-work list: additional backends (claude/vertexai/local), ingestion-pipeline integration, streaming, image embeddings. Also deliberately untouched: rev_gateway and MCP exposure (reranker precedent), metering wiring (blueprint-level choice).