import { ConfigService } from "@nestjs/config"; import { ZodType } from "zod"; import { BaseConfigInterface } from "../../../config/interfaces"; import { ModelService } from "../../llm/services/model.service"; /** * Error thrown when vision model's content moderation blocks an image analysis request. * This typically happens when the image content triggers safety filters. */ export declare class ContentModerationError extends Error { constructor(message: string); } /** * Parameters for Vision LLM service calls */ interface VisionCallParams { image: string; systemPrompt: string; outputSchema: ZodType; temperature?: number; } export declare class VisionLLMService { private readonly modelService; private readonly config; private readonly MAX_RETRIES; private readonly INITIAL_DELAY_MS; private readonly CALL_TIMEOUT_MS; constructor(modelService: ModelService, config: ConfigService); /** * Checks if an error is a rate limit (429) error */ private isRateLimitError; /** * Sleep for specified milliseconds */ private sleep; /** * Wrap a promise with a timeout */ private withTimeout; /** * Puts the vision candidate that just rate-limited into its cooldown window, * so the next resolution reaches for the next link of the chain instead. * * Best-effort in every direction — no candidate-aware `ModelService`, an empty * chain, or a throwing registry all leave the retry exactly as it was. * Failover bookkeeping must never turn a retryable 429 into a hard failure. */ private markCandidateFailure; /** * Execute a function with exponential backoff retry on rate limit errors. * * `fn` receives the ATTEMPT INDEX so it can rebuild its model against the * n-th connection of the vision chain — that is what makes a 429 move to a * different provider rather than knocking on the same closed door. With no * DB-backed connections every index resolves the same `.env` connection, i.e. * today's behaviour. */ private withRetry; /** * Fetches an image from a URL and converts it to a base64 data URL. * Required because OpenRouter cannot access local/private URLs. */ private fetchImageAsBase64; /** * Checks if the configured vision model is a Gemini model. * Gemini models require schema sanitization (removal of $schema, $defs, etc.) */ private isGeminiVisionModel; /** * Checks if the configured vision model is an Azure OpenAI model. * Azure benefits from pre-converted JSON Schema to avoid Zod-to-OpenAI conversion issues. */ private isAzureVisionModel; /** * Checks if the configured vision model is a GPT-5 model. * GPT-5 models use OpenAI's Responses API and reject legacy parameters * like temperature != 1. */ private isGPT5VisionModel; /** * Fallback method to call the LLM without structured output. * Used when structured output parsing fails. * * @template T - The expected output type * @param params - Call parameters * @param message - The HumanMessage to send * @returns Promise with parsed response and raw content */ private callWithoutStructuredOutput; /** * Builds the structured-output vision model for ONE attempt, from the * `candidateIndex`-th link of the vision fallback chain. * * Extracted from {@link call} so each retry can rebuild against a different * connection; the provider-shaped schema handling (Gemini sanitization, * pre-converted JSON Schema for Azure/GPT-5, raw Zod elsewhere) is unchanged. */ private buildStructuredVisionModel; /** * Calls the LLM with an image for vision analysis using structured output. * * This method follows the same pattern as LLMService: * 1. Gets the base model from ModelService * 2. Wraps it with withStructuredOutput for schema enforcement (with Gemini sanitization if needed) * 3. Creates a multimodal HumanMessage with text and image * 4. Invokes the structured LLM directly * 5. Falls back to non-structured call if parsing fails * 6. Returns parsed response with token usage metadata * * @template T - The expected output type (inferred from outputSchema) * @param params - Call parameters * @param params.image - URL of the image to analyze (will be converted to base64) * @param params.systemPrompt - System prompt for the vision analysis * @param params.outputSchema - Zod schema defining expected LLM response structure * @param params.temperature - Optional temperature override (default: 0.1) * @returns Promise resolving to parsed output + token usage metadata * @throws {Error} If LLM call fails or returns invalid structured output */ call(params: VisionCallParams): Promise; } export {}; //# sourceMappingURL=vision.llm.service.d.ts.map