### Initializing OpenRouterClient (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# code shows two ways to instantiate the OpenRouterClient: a basic setup with just an API key, and an advanced setup allowing custom configuration of base URL, timeout, retry settings, and max retry attempts. ```csharp using OpenRouter.Core; // Basic client with API key var client = new OpenRouterClient("YOUR_API_KEY"); // Client with custom configuration var client = new OpenRouterClient("YOUR_API_KEY", options =>{ options.BaseUrl = "https://openrouter.ai/api/v1"; options.Timeout = TimeSpan.FromSeconds(30); options.EnableRetry = true; options.MaxRetryAttempts = 3; }); ``` -------------------------------- ### Creating and Using OpenRouterClient (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This snippet demonstrates the minimal setup for the OpenRouter .NET client. It initializes OpenRouterClient with an API key, sends a basic chat completion request using a fluent API, and prints the first choice content from the response. It highlights the core steps for making an API call. ```C# using OpenRouter.Core; // Create client with API key var client = new OpenRouterClient("your-api-key-here"); // Make a simple chat completion request var response = await client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddUserMessage("Hello, world!") .SendAsync(); Console.WriteLine(response.FirstChoiceContent); ``` -------------------------------- ### Example OpenRouter Configuration in appsettings.json Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This JSON snippet provides an example structure for the `OpenRouter` section within an `appsettings.json` file. It defines various configuration parameters such as `ApiKey`, `BaseUrl`, `Timeout`, `EnableRetry`, and `MaxRetryAttempts`, which can be used to configure the OpenRouter client via dependency injection. ```JSON // appsettings.json { "OpenRouter": { "ApiKey": "your_api_key_here", "BaseUrl": "https://openrouter.ai/api/v1", "Timeout": "00:00:30", "EnableRetry": true, "MaxRetryAttempts": 3 } } ``` -------------------------------- ### Cloning OpenRouter Repository (Bash) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This command clones the OpenRouter .NET library repository from GitHub, allowing local access to the source code for development or direct project referencing. ```bash git clone https://github.com/xyOz-dev/OpenRouter.git ``` -------------------------------- ### Performing Simple Chat Completion (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# example shows how to perform a basic chat completion request using the OpenRouterClient. It sends a user message to the 'gpt-3.5-turbo' model and prints the response content, model, and token usage, including error handling for API exceptions. ```csharp using OpenRouter.Core; var client = new OpenRouterClient("YOUR_API_KEY"); try { var response = await client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddUserMessage("What is the capital of France?") .SendAsync(); Console.WriteLine($"Response: {response.FirstChoiceContent}"); Console.WriteLine($"Model: {response.Model}"); Console.WriteLine($"Usage: {response.Usage?.TotalTokens} tokens"); } catch (OpenRouterException ex) { Console.WriteLine($"API Error: {ex.Message}"); } ``` -------------------------------- ### Configuring OpenRouterClient Options (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This snippet shows common variations for configuring the OpenRouterClient. It demonstrates setting request timeout, enabling retries, and specifying maximum retry attempts. It also illustrates how to retrieve the API key from an environment variable for secure and flexible configuration. ```C# // With timeout configuration var client = new OpenRouterClient("your-api-key", options => { options.RequestTimeout = TimeSpan.FromSeconds(60); options.EnableRetry = true; options.MaxRetryAttempts = 3; }); // Using environment variable var apiKey = Environment.GetEnvironmentVariable("OPENROUTER_API_KEY") ?? throw new InvalidOperationException("API key not found"); var client = new OpenRouterClient(apiKey); ``` -------------------------------- ### Injecting IOpenRouterClient into an ASP.NET Core Controller Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# snippet demonstrates how to inject the `IOpenRouterClient` into an ASP.NET Core controller's constructor using dependency injection. It then shows an example of using the injected client to create a chat completion, add a user message, and send the request, including basic error handling for `OpenRouterException`. ```C# [ApiController] [Route("api/[controller]")] public class ChatController : ControllerBase { private readonly IOpenRouterClient _openRouterClient; public ChatController(IOpenRouterClient openRouterClient) { _openRouterClient = openRouterClient; } [HttpPost("complete")] public async Task Complete([FromBody] string prompt) { try { var response = await _openRouterClient.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddUserMessage(prompt) .SendAsync(); return Ok(new { content = response.FirstChoiceContent }); } catch (OpenRouterException ex) { return BadRequest(new { error = ex.Message }); } } } ``` -------------------------------- ### Configuring Advanced OpenRouterOptions (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# code demonstrates how to create and configure an OpenRouterOptions object with various advanced settings like API key, base URL, timeouts, retry logic, logging, and API key validation, then uses these options to initialize the OpenRouterClient. ```csharp var options = new OpenRouterOptions { ApiKey = "YOUR_API_KEY", BaseUrl = "https://openrouter.ai/api/v1", Timeout = TimeSpan.FromSeconds(30), RequestTimeout = TimeSpan.FromSeconds(120), MaxRetryAttempts = 3, RetryDelay = TimeSpan.FromSeconds(1), EnableRetry = true, EnableLogging = true, LogLevel = LogLevel.Information, ValidateApiKey = true, ThrowOnApiErrors = true }; var client = new OpenRouterClient( new OpenRouterHttpClient(new HttpClient(), new BearerTokenProvider(options.ApiKey, options.ValidateApiKey), options, null), options); ``` -------------------------------- ### Setting OpenRouter API Key Environment Variable (Bash/Cmd/PowerShell) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md These commands demonstrate how to set the OPENROUTER_API_KEY environment variable across different operating systems (Windows Command Prompt, PowerShell, macOS/Linux), which is the recommended secure method for API key configuration. ```bash # Windows (Command Prompt) set OPENROUTER_API_KEY=your_api_key_here # Windows (PowerShell) $env:OPENROUTER_API_KEY="your_api_key_here" # macOS/Linux export OPENROUTER_API_KEY="your_api_key_here" ``` -------------------------------- ### Configuring OpenRouter Options in appsettings.json (JSON) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This JSON snippet illustrates how to configure OpenRouter API key and client options within an appsettings.json file, commonly used in ASP.NET Core applications for centralized configuration management. ```json { "OpenRouter": { "ApiKey": "your_api_key_here", "BaseUrl": "https://openrouter.ai/api/v1", "Timeout": "00:00:30", "EnableRetry": true, "MaxRetryAttempts": 3 } } ``` -------------------------------- ### Adding Project Reference to .csproj (XML) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This XML snippet demonstrates how to add a project reference to the OpenRouter library within a .NET project's .csproj file, enabling the consuming project to use the library's functionalities. ```xml ``` -------------------------------- ### Consuming OpenRouter Options and Client in a C# Service Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This C# class ConfigurableService illustrates how to inject and utilize OpenRouterOptions (via IOptions) and IOpenRouterClient within a service. It demonstrates accessing configured default model, temperature, and max tokens from _options to create a chat completion request using the _client, showcasing practical application of bound configuration settings. ```csharp public class ConfigurableService { private readonly OpenRouterOptions _options; private readonly IOpenRouterClient _client; public ConfigurableService(IOptions options, IOpenRouterClient client) { _options = options.Value; _client = client; } public async Task GetResponseAsync(string prompt) { var response = await _client.Chat .CreateChatCompletion(_options.DefaultModel ?? "gpt-3.5-turbo") .AddUserMessage(prompt) .WithTemperature(_options.DefaultTemperature ?? 0.7) .WithMaxTokens(_options.DefaultMaxTokens ?? 150) .SendAsync(); return response.FirstChoiceContent; } } ``` -------------------------------- ### Convenience Constructor for OpenRouterClient in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/client.md This C# convenience constructor for `OpenRouterClient` simplifies initialization by accepting an API key directly, along with optional configuration and logging parameters, making it easier to get started. ```C# public OpenRouterClient( string apiKey, Action? configure = null, ILogger? logger = null) ``` -------------------------------- ### Processing Multiple Chat Completion Choices (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This snippet illustrates how to iterate through multiple choices in a ChatCompletionResponse if the model provides them. It shows how to access the content and finish reason for each choice. Additionally, it demonstrates checking the completion status of the first choice to determine if the response was fully generated. ```C# // Process multiple choices if available foreach (var choice in response.Choices) { Console.WriteLine($"Choice {choice.Index}: {choice.Message?.Content}"); Console.WriteLine($"Finish Reason: {choice.FinishReason}"); } // Check completion status var firstChoice = response.Choices.FirstOrDefault(); if (firstChoice?.IsCompleted == true) { Console.WriteLine("Response completed successfully"); } ``` -------------------------------- ### OpenRouter Client Configuration in appsettings.json Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This JSON snippet illustrates a complete `appsettings.json` configuration for the OpenRouter client, covering API key, base URL, timeouts, retry settings, logging levels, and default model parameters. It provides a structured way to manage OpenRouter client settings across different application environments. ```json { "OpenRouter": { "ApiKey": "your-api-key-here", "BaseUrl": "https://openrouter.ai/api/v1", "RequestTimeout": "00:02:00", "EnableRetry": true, "MaxRetryAttempts": 3, "RetryDelay": "00:00:01", "EnableLogging": true, "LogLevel": "Information", "ValidateApiKey": true, "ThrowOnApiErrors": true, "DefaultModel": "gpt-3.5-turbo", "DefaultTemperature": 0.7, "DefaultMaxTokens": 150 }, "Logging": { "LogLevel": { "Default": "Information", "OpenRouter": "Debug", "Microsoft.AspNetCore": "Warning" } } } ``` -------------------------------- ### Implementing Chat Completion Controller with OpenRouter in ASP.NET Core Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This C# controller demonstrates how to use the injected `IOpenRouterClient` to create chat completions. It handles incoming chat requests, constructs the OpenRouter API call with user messages, model, temperature, and max tokens, and includes robust error handling for both OpenRouter-specific and general exceptions, returning appropriate HTTP responses. ```C# // Controllers/ChatController.cs using Microsoft.AspNetCore.Mvc; using OpenRouter.Core; [ApiController] [Route("api/[controller]")] public class ChatController : ControllerBase { private readonly IOpenRouterClient _openRouterClient; private readonly ILogger _logger; public ChatController(IOpenRouterClient openRouterClient, ILogger logger) { _openRouterClient = openRouterClient; _logger = logger; } [HttpPost("complete")] public async Task Complete([FromBody] ChatRequest request) { try { _logger.LogInformation("Processing chat completion request"); var response = await _openRouterClient.Chat .CreateChatCompletion(request.Model ?? "gpt-3.5-turbo") .AddUserMessage(request.Message) .WithTemperature(request.Temperature ?? 0.7) .WithMaxTokens(request.MaxTokens ?? 150) .SendAsync(); return Ok(new ChatApiResponse { Content = response.FirstChoiceContent, Model = response.Model, TokensUsed = response.Usage?.TotalTokens ?? 0 }); } catch (OpenRouterException ex) { _logger.LogError(ex, "OpenRouter API error"); return BadRequest(new { error = ex.Message, type = ex.ErrorType }); } catch (Exception ex) { _logger.LogError(ex, "Unexpected error"); return StatusCode(500, new { error = "Internal server error" }); } } } public class ChatRequest { public required string Message { get; set; } public string? Model { get; set; } public double? Temperature { get; set; } public int? MaxTokens { get; set; } } public class ChatApiResponse { public required string Content { get; set; } public required string Model { get; set; } public int TokensUsed { get; set; } } ``` -------------------------------- ### Configuring OpenRouter Services in ASP.NET Core Program.cs Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This snippet demonstrates how to register and configure OpenRouter services within an ASP.NET Core application's `Program.cs` file using `AddOpenRouter()`. It sets up the API key, base URL, retry logic, and request timeouts, integrating OpenRouter into the dependency injection container for application-wide use. ```C# // Program.cs using OpenRouter.Extensions; var builder = WebApplication.CreateBuilder(args); // Add OpenRouter services builder.Services.AddOpenRouter(options => { options.ApiKey = builder.Configuration["OpenRouter:ApiKey"]!; options.BaseUrl = "https://openrouter.ai/api/v1"; options.EnableRetry = true; options.MaxRetryAttempts = 3; options.RetryDelay = TimeSpan.FromSeconds(1); options.RequestTimeout = TimeSpan.FromSeconds(120); }); // Add other services builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Handling Chat Completion Responses and Errors (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This example demonstrates a complete chat completion request with robust response handling and error checking. It sends a message to a specified model, accesses various response details like ID, model, and creation time, retrieves the content, and checks token usage. It also includes a try-catch block to gracefully handle OpenRouterException for API-specific errors. ```C# using OpenRouter.Core; using OpenRouter.Models.Responses; var client = new OpenRouterClient("your-api-key"); try { var response = await client.Chat .CreateChatCompletion("anthropic/claude-3-haiku") .AddSystemMessage("You are a helpful programming assistant.") .AddUserMessage("Explain what async/await means in C#") .WithTemperature(0.7) .WithMaxTokens(200) .SendAsync(); // Access response details Console.WriteLine($"Response ID: {response.Id}"); Console.WriteLine($"Model Used: {response.Model}"); Console.WriteLine($"Created: {response.CreatedAt:yyyy-MM-dd HH:mm:ss}"); // Get the response content var content = response.FirstChoiceContent; Console.WriteLine($"Response: {content}"); // Check token usage if (response.Usage != null) { Console.WriteLine($"Tokens used: {response.Usage.TotalTokens}"); Console.WriteLine($" - Prompt: {response.Usage.PromptTokens}"); Console.WriteLine($" - Completion: {response.Usage.CompletionTokens}"); } } catch (OpenRouterException ex) { Console.WriteLine($"API Error: {ex.Message}"); Console.WriteLine($"Error Type: {ex.ErrorType}"); Console.WriteLine($"Status Code: {ex.StatusCode}"); } ``` -------------------------------- ### Defining Environment-Specific OpenRouter Configuration in JSON Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This snippet illustrates how to define environment-specific settings for OpenRouter within appsettings.Development.json and appsettings.Production.json. It shows different logging levels, request timeouts, and retry attempts tailored for development and production environments, enabling flexible application behavior based on deployment context. ```json // appsettings.Development.json { "OpenRouter": { "EnableLogging": true, "LogLevel": "Debug", "RequestTimeout": "00:05:00" } } // appsettings.Production.json { "OpenRouter": { "EnableLogging": false, "LogLevel": "Warning", "RequestTimeout": "00:01:30", "MaxRetryAttempts": 5 } } ``` -------------------------------- ### Configuring Model Behavior with System Messages (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/chat-examples.md This snippet demonstrates how to use system messages with the OpenRouter .NET library to configure the behavior of an AI assistant. It shows the creation of a SpecializedAssistant class that incorporates a system prompt to guide the model's responses, enabling role-specific AI assistants. ```C# using OpenRouter.Core; public class SpecializedAssistant { private readonly IOpenRouterClient _client; private readonly string _systemPrompt; public SpecializedAssistant(IOpenRouterClient client, string systemPrompt) { _client = client; _systemPrompt = systemPrompt; } public async Task GetResponseAsync(string userQuery) { var response = await _client.Chat .CreateChatCompletion("anthropic/claude-3-haiku") .AddSystemMessage(_systemPrompt) .AddUserMessage(userQuery) .WithTemperature(0.3) // Lower temperature for consistent behavior .SendAsync(); return response.FirstChoiceContent; } } // Specialized assistants var codeAssistant = new SpecializedAssistant(client, "You are an expert C# programmer. Provide clean, maintainable code examples with explanations."); var customerService = new SpecializedAssistant(client, "You are a friendly customer service representative. Be helpful, polite, and solution-oriented."); var technicalWriter = new SpecializedAssistant(client, "You are a technical documentation expert. Write clear, concise documentation with proper formatting."); // Usage var codeExample = await codeAssistant.GetResponseAsync("Show me how to implement the repository pattern"); var serviceResponse = await customerService.GetResponseAsync("I'm having trouble with my order"); var documentation = await technicalWriter.GetResponseAsync("Document this API endpoint"); ``` -------------------------------- ### Setting Up OpenRouter Development Environment (Bash) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/README.md This Bash script outlines the steps to set up the OpenRouter development environment. It clones the repository, navigates into the directory, restores NuGet packages, builds the project, and finally runs all tests to verify the setup. ```Bash git clone https://github.com/xyOz-dev/OpenRouter.git cd OpenRouter dotnet restore dotnet build dotnet test ``` -------------------------------- ### Implementing Robust Error Handling with OpenRouter Client in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This C# snippet demonstrates a comprehensive try-catch pattern for handling various OpenRouter API exceptions, including authentication, rate limiting, model, and network errors. It incorporates retry logic with exponential backoff for transient issues and specific exception types for clearer error management, ensuring application resilience. ```csharp using OpenRouter.Core; using OpenRouter.Core.Exceptions; public class ChatService { private readonly IOpenRouterClient _client; private readonly ILogger _logger; public ChatService(IOpenRouterClient client, ILogger logger) { _client = client; _logger = logger; } public async Task GetCompletionAsync(string prompt, string model = "gpt-3.5-turbo") { const int maxRetries = 3; var retryCount = 0; while (retryCount < maxRetries) { try { _logger.LogInformation("Attempting chat completion (attempt {Attempt})", retryCount + 1); var response = await _client.Chat .CreateChatCompletion(model) .AddUserMessage(prompt) .WithTimeout(TimeSpan.FromSeconds(30)) .SendAsync(); _logger.LogInformation("Chat completion successful"); return response.FirstChoiceContent; } catch (OpenRouterAuthenticationException ex) { _logger.LogError(ex, "Authentication failed - check API key"); throw new InvalidOperationException("Invalid API credentials", ex); } catch (OpenRouterRateLimitException ex) { _logger.LogWarning("Rate limit exceeded, waiting {Delay}ms", ex.RetryAfterMs); if (ex.RetryAfterMs > 0) { await Task.Delay(TimeSpan.FromMilliseconds(ex.RetryAfterMs)); } retryCount++; continue; } catch (OpenRouterModelException ex) { _logger.LogError(ex, "Model error: {Message}", ex.Message); throw new ArgumentException($"Model '{model}' error: {ex.Message}", ex); } catch (OpenRouterNetworkException ex) { _logger.LogWarning(ex, "Network error on attempt {Attempt}", retryCount + 1); retryCount++; if (retryCount >= maxRetries) { _logger.LogError("Max retries exceeded for network errors"); throw new ServiceUnavailableException("OpenRouter service is unavailable", ex); } await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retryCount))); // Exponential backoff continue; } catch (OpenRouterException ex) { _logger.LogError(ex, "OpenRouter API error: {ErrorType}", ex.ErrorType); throw new ApplicationException($"API error: {ex.Message}", ex); } catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) { _logger.LogWarning("Request timeout on attempt {Attempt}", retryCount + 1); retryCount++; if (retryCount >= maxRetries) { throw new TimeoutException("Request timed out after multiple attempts", ex); } continue; } catch (Exception ex) { _logger.LogError(ex, "Unexpected error during chat completion"); throw new ApplicationException("An unexpected error occurred", ex); } } throw new ApplicationException("Failed to complete request after all retries"); } } public class ServiceUnavailableException : Exception { public ServiceUnavailableException(string message, Exception innerException) : base(message, innerException) { } } ``` -------------------------------- ### Binding OpenRouter Configuration and Adding Validation in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/quick-start.md This C# snippet demonstrates how to bind the 'OpenRouter' section from IConfiguration to OpenRouterOptions using builder.Services.Configure and builder.Services.AddOpenRouter. It includes logic to override settings with environment variables, perform custom validation for the API key, and integrate data annotation validation with ValidateDataAnnotations() and ValidateOnStart() for robust configuration management. ```csharp var builder = WebApplication.CreateBuilder(args); // Bind configuration to options builder.Services.Configure( builder.Configuration.GetSection("OpenRouter")); // Register with configuration validation builder.Services.AddOpenRouter(options => { builder.Configuration.GetSection("OpenRouter").Bind(options); // Override with environment variables if present options.ApiKey = Environment.GetEnvironmentVariable("OPENROUTER_API_KEY") ?? options.ApiKey; // Validate required settings if (string.IsNullOrEmpty(options.ApiKey)) { throw new InvalidOperationException("OpenRouter API key is required"); } }); // Add options validation builder.Services.AddOptions() .Configure((options, config) => { config.GetSection("OpenRouter").Bind(options); }) .ValidateDataAnnotations() .ValidateOnStart(); ``` -------------------------------- ### Retrieving API Key from Environment Variable (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# snippet retrieves the OpenRouter API key from the OPENROUTER_API_KEY environment variable, ensuring secure access and throwing an InvalidOperationException if the variable is not found. ```csharp var apiKey = Environment.GetEnvironmentVariable("OPENROUTER_API_KEY") ?? throw new InvalidOperationException("OPENROUTER_API_KEY not found"); var client = new OpenRouterClient(apiKey); ``` -------------------------------- ### Example Message Creation Patterns (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/models.md This C# example demonstrates various patterns for creating `Message` objects using the static factory methods. It shows how to create simple text messages for system and user roles, a multi-modal user message with text and an image, and a tool response message. ```C# // Simple text messages var systemMsg = Message.System("You are a helpful assistant."); var userMsg = Message.User("Hello, how are you?"); // Multi-modal message with image var multiModalMsg = Message.User(new[] { MessageContent.CreateText("What do you see in this image?"), MessageContent.Image("https://example.com/image.jpg", "high") }); // Tool response message var toolMsg = Message.Tool("Weather is 72°F", "call_weather_123"); ``` -------------------------------- ### Implementing Tool Calling with OpenRouter Chat API in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/chat-examples.md This C# class `WeatherAssistant` demonstrates how to integrate tool calling with the OpenRouter chat completion API. It defines a `get_current_weather` function tool, sends user messages to the AI, processes tool calls by invoking a `WeatherService`, and then sends the tool results back to the AI to get a final conversational response. It showcases the full lifecycle of a tool-augmented chat interaction. ```C# using OpenRouter.Core; using OpenRouter.Models.Common; using System.Text.Json; public class WeatherAssistant { private readonly IOpenRouterClient _client; private readonly WeatherService _weatherService; public WeatherAssistant(IOpenRouterClient client, WeatherService weatherService) { _client = client; _weatherService = weatherService; } public async Task GetWeatherResponseAsync(string userMessage) { // Define available tools var tools = new[] { new ToolDefinition { Type = "function", Function = new FunctionDefinition { Name = "get_current_weather", Description = "Get the current weather in a given location", Parameters = JsonSerializer.Deserialize(""" { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit" } }, "required": ["location"] } """) } } }; var response = await _client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddSystemMessage("You are a helpful weather assistant. Use the provided tools to get current weather information.") .AddUserMessage(userMessage) .WithTools(tools) .WithToolChoice("auto") .SendAsync(); var choice = response.Choices.FirstOrDefault(); if (choice?.Message?.ToolCalls?.Any() == true) { var toolResults = new List(); // Execute tool calls foreach (var toolCall in choice.Message.ToolCalls) { if (toolCall.Function?.Name == "get_current_weather") { var args = JsonSerializer.Deserialize(toolCall.Function.Arguments); var weather = await _weatherService.GetWeatherAsync(args.Location, args.Unit ?? "celsius"); toolResults.Add(new Message { Role = "tool", ToolCallId = toolCall.Id, Content = JsonSerializer.Serialize(weather) }); } } // Get final response with tool results var finalResponse = await _client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddSystemMessage("You are a helpful weather assistant.") .AddUserMessage(userMessage) .AddMessage(choice.Message) // Original assistant response with tool calls .WithMessages(toolResults.ToArray()) // Tool results .SendAsync(); return finalResponse.FirstChoiceContent; } return response.FirstChoiceContent; } } public class WeatherRequest { public string Location { get; set; } = string.Empty; public string? Unit { get; set; } } public class WeatherService { public async Task GetWeatherAsync(string location, string unit) { // Mock implementation await Task.Delay(100); return new { location, temperature = unit == "fahrenheit" ? 72 : 22, unit, description = "Sunny", humidity = 45 }; } } ``` -------------------------------- ### Processing ChatCompletionResponse (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# snippet demonstrates how to access and process various properties of the ChatCompletionResponse object after a chat completion request. It iterates through choices, checks completion status, and extracts detailed usage information like prompt, completion, and total tokens. ```csharp var response = await client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddUserMessage("Tell me a joke") .SendAsync(); // Access response properties Console.WriteLine($"Response ID: {response.Id}"); Console.WriteLine($"Created: {response.CreatedAt}"); Console.WriteLine($"Model: {response.Model}"); // Access choices foreach (var choice in response.Choices) { Console.WriteLine($"Choice {choice.Index}: {choice.Message?.Content}"); Console.WriteLine($"Finish Reason: {choice.FinishReason}"); // Check completion status if (choice.IsCompleted) { Console.WriteLine("Response completed successfully"); } } // Usage information if (response.Usage != null) { Console.WriteLine($"Prompt tokens: {response.Usage.PromptTokens}"); Console.WriteLine($"Completion tokens: {response.Usage.CompletionTokens}"); Console.WriteLine($"Total tokens: {response.Usage.TotalTokens}"); } ``` -------------------------------- ### Installing OpenRouter .NET via NuGet - PowerShell Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/index.md This PowerShell command installs the OpenRouter .NET library as a NuGet package using the Package Manager Console, making it available for use in your project. ```powershell Install-Package OpenRouter ``` -------------------------------- ### Configuring OpenRouter Client from appsettings.json in ASP.NET Core Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# snippet illustrates how to bind OpenRouter client options from the `appsettings.json` configuration file to the `AddOpenRouter` service registration. It leverages `builder.Configuration.GetSection("OpenRouter").Bind(options)` to automatically map configuration values to the client options, promoting externalized configuration. ```C# // Program.cs builder.Services.AddOpenRouter(options => builder.Configuration.GetSection("OpenRouter").Bind(options)); ``` -------------------------------- ### Initializing OpenRouterClient in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/client.md These C# examples demonstrate how to initialize the `OpenRouterClient` using both simple API key provision and advanced configuration with options like timeout and retry attempts. ```C# // Simple initialization var client = new OpenRouterClient("your-api-key"); // With configuration var client = new OpenRouterClient("your-api-key", options => { options.Timeout = TimeSpan.FromSeconds(60); options.MaxRetryAttempts = 3; }); ``` -------------------------------- ### Installing OpenRouter .NET Library via Git Clone Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/README.md This snippet demonstrates how to install the OpenRouter .NET library by cloning its GitHub repository. This method is suitable for developers who want to work directly with the source code or contribute to the project. ```bash git clone https://github.com/xyOz-dev/OpenRouter.git ``` -------------------------------- ### Registering OpenRouter Client with Dependency Injection in ASP.NET Core Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/getting-started.md This C# snippet demonstrates how to register the OpenRouter client with the ASP.NET Core built-in dependency injection container. It shows two methods: basic registration using an API key directly, and a more flexible approach using a configuration options lambda, allowing settings like ApiKey, BaseUrl, EnableRetry, and MaxRetryAttempts to be defined programmatically. ```C# using OpenRouter.Extensions; var builder = WebApplication.CreateBuilder(args); // Basic registration with API key builder.Services.AddOpenRouter("YOUR_API_KEY"); // Or with configuration builder.Services.AddOpenRouter(options => { options.ApiKey = builder.Configuration["OpenRouter:ApiKey"]!; options.BaseUrl = "https://openrouter.ai/api/v1"; options.EnableRetry = true; options.MaxRetryAttempts = 3; }); var app = builder.Build(); ``` -------------------------------- ### Example Chat Completion Request Initialization (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/models.md This C# example demonstrates how to initialize a `ChatCompletionRequest` object. It sets the model to 'gpt-4', defines system and user messages, and configures generation parameters like `Temperature` and `MaxTokens` for a typical chat interaction. ```C# var request = new ChatCompletionRequest { Model = "gpt-4", Messages = new[] { Message.System("You are a helpful assistant."), Message.User("Explain quantum computing") }, Temperature = 0.7, MaxTokens = 1000 }; ``` -------------------------------- ### Managing Multi-Turn Conversations with OpenRouter (C#) Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/chat-examples.md This example provides a ConversationManager class in C# to handle multi-turn conversations by maintaining a history of messages. It demonstrates how to send user messages, receive assistant responses, and update the conversation history, essential for stateful chatbots. ```C# using OpenRouter.Core; using OpenRouter.Models.Common; public class ConversationManager { private readonly IOpenRouterClient _client; private readonly List _conversationHistory; public ConversationManager(IOpenRouterClient client) { _client = client; _conversationHistory = new List(); } public async Task SendMessageAsync(string userMessage, string model = "anthropic/claude-3-haiku") { // Add user message to history _conversationHistory.Add(new Message { Role = "user", Content = userMessage }); var response = await _client.Chat .CreateChatCompletion(model) .WithMessages(_conversationHistory.ToArray()) .WithTemperature(0.7) .SendAsync(); var assistantMessage = response.FirstChoiceContent; // Add assistant response to history _conversationHistory.Add(new Message { Role = "assistant", Content = assistantMessage }); return assistantMessage; } public void ClearHistory() => _conversationHistory.Clear(); public int GetHistoryLength() => _conversationHistory.Count; } // Usage example var conversationManager = new ConversationManager(client); var response1 = await conversationManager.SendMessageAsync("My name is Alice"); Console.WriteLine(response1); // "Nice to meet you, Alice!" var response2 = await conversationManager.SendMessageAsync("What's my name?"); Console.WriteLine(response2); // "Your name is Alice." ``` -------------------------------- ### Creating UsageConfig Instance with Default Method in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/models.md Provides a factory method to create a default `UsageConfig` instance, simplifying the setup for common usage tracking preferences. ```C# static UsageConfig Default(); ``` -------------------------------- ### Generating Structured JSON Output with OpenRouter in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/chat-examples.md This snippet defines a `StructuredOutputService` class that uses the OpenRouter API to generate structured JSON responses based on a provided prompt and JSON schema. It demonstrates how to configure the AI model for consistent output and deserialize the JSON response into a C# object. It also includes example data models (`PersonInfo`, `ProductReview`) and a usage example showing how to extract information about a person. ```C# using OpenRouter.Core; using System.Text.Json; public class StructuredOutputService { private readonly IOpenRouterClient _client; public StructuredOutputService(IOpenRouterClient client) { _client = client; } public async Task GetStructuredResponseAsync(string prompt, string jsonSchema) { var systemPrompt = """ You are an expert data extraction assistant. Extract information from the user's input and respond with valid JSON that matches this schema: {jsonSchema} Respond only with valid JSON, no additional text. """; var response = await _client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddSystemMessage(systemPrompt) .AddUserMessage(prompt) .WithTemperature(0.1) // Low temperature for consistency .WithMaxTokens(500) .SendAsync(); var jsonContent = response.FirstChoiceContent; return JsonSerializer.Deserialize(jsonContent)!; } } // Usage examples public class PersonInfo { public string Name { get; set; } = string.Empty; public int Age { get; set; } public string Email { get; set; } = string.Empty; public string[] Skills { get; set; } = Array.Empty(); } public class ProductReview { public string ProductName { get; set; } = string.Empty; public int Rating { get; set; } public string[] PositiveAspects { get; set; } = Array.Empty(); public string[] NegativeAspects { get; set; } = Array.Empty(); public string Summary { get; set; } = string.Empty; } // Usage var service = new StructuredOutputService(client); var personSchema = """ { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer"}, "email": {"type": "string"}, "skills": {"type": "array", "items": {"type": "string"}} }, "required": ["name", "age", "email"] } """; var person = await service.GetStructuredResponseAsync( "Extract info: John Doe is 30 years old, email john@example.com, knows C# and Python", personSchema ); Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); ``` -------------------------------- ### Building Adaptive Chat Completion Requests in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/chat-examples.md This example illustrates how to dynamically construct chat completion requests based on runtime conditions using the IChatRequestBuilder. It showcases conditional logic for adding system messages, incorporating conversation history, adjusting parameters based on content type (e.g., creative, technical), applying user-specific settings (e.g., premium user benefits), and implementing safety constraints. This approach enables flexible and context-aware AI interactions. ```C# using OpenRouter.Core; public class AdaptiveChatService { private readonly IOpenRouterClient _client; public AdaptiveChatService(IOpenRouterClient client) { _client = client; } public async Task GetAdaptiveResponseAsync( string message, ChatContext context) { var builder = _client.Chat.CreateChatCompletion(context.Model); // Conditional system message if (!string.IsNullOrEmpty(context.SystemPrompt)) { builder = builder.AddSystemMessage(context.SystemPrompt); } // Add conversation history if available if (context.ConversationHistory?.Any() == true) { builder = builder.WithMessages(context.ConversationHistory); } builder = builder.AddUserMessage(message); // Conditional parameters based on content type builder = context.ContentType switch { ContentType.Creative => builder .WithTemperature(0.9) .WithTopP(0.95) .WithFrequencyPenalty(0.6), ContentType.Technical => builder .WithTemperature(0.1) .WithTopP(0.9) .WithMaxTokens(800), ContentType.Conversational => builder .WithTemperature(0.7) .WithTopK(40) .WithPresencePenalty(0.3), _ => builder.WithTemperature(0.5) }; // User-specific adjustments if (context.User?.IsPremium == true) { builder = builder.WithMaxTokens(1000); } // Safety constraints for sensitive content if (context.RequiresModeration) { builder = builder .WithTemperature(0.3) .WithStop(new[] { "[INAPPROPRIATE]", "[HARMFUL]" }); } var response = await builder.SendAsync(); return response.FirstChoiceContent; } } public class ChatContext { public string Model { get; set; } = "gpt-3.5-turbo"; public string? SystemPrompt { get; set; } public Message[]? ConversationHistory { get; set; } public ContentType ContentType { get; set; } = ContentType.Conversational; public User? User { get; set; } public bool RequiresModeration { get; set; } } public enum ContentType { Conversational, Technical, Creative, Educational } public class User { public bool IsPremium { get; set; } public string? PreferredModel { get; set; } } ``` -------------------------------- ### Performing Basic Chat Completion with OpenRouter .NET - C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/index.md This C# example demonstrates how to initialize the OpenRouter client with an API key and perform a simple chat completion request using the 'gpt-3.5-turbo' model. It shows how to add a user message and print the content of the first response choice. ```csharp // Simple client initialization var client = new OpenRouterClient("YOUR_API_KEY"); // Your first chat completion var response = await client.Chat .CreateChatCompletion("gpt-3.5-turbo") .AddUserMessage("Hello, world!") .SendAsync(); Console.WriteLine(response.FirstChoiceContent); ``` -------------------------------- ### Implementing Streaming Chat Client in JavaScript Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/examples/streaming-examples.md This JavaScript class, `StreamingChatClient`, facilitates real-time communication with a streaming API using Server-Sent Events (SSE). It sends a POST request with chat parameters and processes the incoming stream of data, yielding content and completion events. The usage example demonstrates how to instantiate the client and display streaming responses dynamically in a web page. ```javascript // Frontend JavaScript for consuming the streaming API class StreamingChatClient { constructor(baseUrl) { this.baseUrl = baseUrl; } async streamChat(message, options = {}) { const requestBody = { message: message, model: options.model || 'gpt-3.5-turbo', systemMessage: options.systemMessage, temperature: options.temperature || 0.7, maxTokens: options.maxTokens || 500 }; const response = await fetch(`${this.baseUrl}/api/streamingchat/stream`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); return { async *[Symbol.asyncIterator]() { try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { try { const data = JSON.parse(line.slice(6)); yield data; if (data.type === 'completion') { return; } } catch (e) { console.warn('Failed to parse SSE data:', line); } } else if (line.startsWith('error: ')) { throw new Error(line.slice(7)); } else if (line === 'event: stream-end') { return; } } } } finally { reader.releaseLock(); } } }; } } // Usage example const client = new StreamingChatClient('https://localhost:5001'); async function displayStreamingResponse(message) { const responseDiv = document.getElementById('response'); responseDiv.innerHTML = ''; try { const stream = await client.streamChat(message); for await (const chunk of stream) { if (chunk.type === 'content') { responseDiv.innerHTML += chunk.content; } else if (chunk.type === 'completion') { console.log('Stream completed:', chunk.finishReason); } } } catch (error) { responseDiv.innerHTML = `Error: ${error.message}`; } } ``` -------------------------------- ### Configuring Production-Ready OpenRouter Client in C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/authentication.md This C# example illustrates a robust, production-ready configuration for the OpenRouter client using dependency injection. It retrieves the API key from environment variables, enables validation, error throwing, and retry mechanisms with specific delays and attempts. ```C# // Production configuration with comprehensive error handling services.AddOpenRouter(options => { options.ApiKey = Environment.GetEnvironmentVariable("OPENROUTER_API_KEY") ?? throw new InvalidOperationException("OPENROUTER_API_KEY not configured"); options.ValidateApiKey = true; options.ThrowOnApiErrors = true; options.EnableRetry = true; options.MaxRetryAttempts = 3; options.RetryDelay = TimeSpan.FromSeconds(1); }); ``` -------------------------------- ### Using OpenRouter Credits Service - C# Source: https://github.com/xyoz-dev/logiq.openrouter/blob/master/docs/api-reference/services.md This C# example demonstrates how to interact with the ICreditsService to manage credit balances and payments. It shows how to check the current credit balance, retrieve detailed usage statistics, and initiate a Coinbase payment for purchasing additional credits, specifying the amount and currency. ```csharp // Check current credits var credits = await client.Credits.GetCreditsAsync(); Console.WriteLine($"Available credits: {credits.Credits}"); // Get usage statistics var usage = await client.Credits.GetUsageAsync(); // Create payment for additional credits var paymentRequest = new CoinbasePaymentRequest { Amount = 10.00m, Currency = "USD" }; var payment = await client.Credits.CreateCoinbasePaymentAsync(paymentRequest); ```