Private/Translation/Invoke-OpenRouterTranslation.ps1
|
function Invoke-OpenRouterTranslation { <# .SYNOPSIS Calls the OpenRouter Chat Completions API with retry and exponential backoff. .DESCRIPTION OpenRouter's chat endpoint is OpenAI-Chat-Completions-compatible, so the request/response shape mirrors Invoke-OpenAITranslation. Additionally sends OpenRouter's optional attribution headers (HTTP-Referer, X-Title) so usage shows up correctly attributed on https://openrouter.ai. .OUTPUTS PSCustomObject: Content, InputTokens, OutputTokens, FinishReason, Model, RetryCount #> [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [string] $SystemPrompt, [Parameter(Mandatory)] [string] $UserContent, [Parameter(Mandatory)] [TranslationProvider] $Provider, [Parameter(Mandatory)] [SecureString] $ApiKey, [int] $MaxRetries = 3, # When supplied, the call is attempted over the streaming path first so the # caller can report progress while the model is still writing; any streaming # failure falls back to the buffered request below. [scriptblock] $StreamCallback ) $plainKey = [System.Net.NetworkCredential]::new('', $ApiKey).Password $body = @{ model = $Provider.Model temperature = [double]$Provider.Temperature max_tokens = $Provider.MaxOutputTokens messages = @( @{ role = 'system'; content = $SystemPrompt } @{ role = 'user'; content = $UserContent } ) } $headers = @{ 'Authorization' = "Bearer $plainKey" 'HTTP-Referer' = 'https://github.com/imanedr/SubtitleTools' 'X-Title' = 'SubtitleTools' } if ($StreamCallback) { $streamed = Invoke-TranslationStreamAttempt -Uri "$($Provider.BaseUrl)/chat/completions" -Headers $headers -Body $body ` -Shape 'OpenAI' -ProviderLabel 'OpenRouter' -Model $Provider.Model ` -StreamCallback $StreamCallback -JsonDepth 5 if ($streamed) { return $streamed } } $result = Invoke-TranslationApiRequest -Uri "$($Provider.BaseUrl)/chat/completions" -Method Post ` -Body $body -Headers $headers -ProviderLabel 'OpenRouter' -MaxRetries $MaxRetries -JsonDepth 5 if (-not $result.Success) { return [PSCustomObject]@{ Content = $result.ErrorMessage InputTokens = 0 OutputTokens = 0 FinishReason = 'error' Model = $Provider.Model RetryCount = $result.RetryCount } } $response = $result.Response $choice = $response.choices[0] return [PSCustomObject]@{ Content = $choice.message.content InputTokens = $response.usage.prompt_tokens OutputTokens = $response.usage.completion_tokens FinishReason = $choice.finish_reason Model = $response.model RetryCount = $result.RetryCount } } |