Source code for lexilux.chat.params

"""
Chat API parameter configuration classes.

Provides dataclass-based parameter configuration for OpenAI-compatible chat completions,
with support for standard parameters and custom extensions.
"""

from __future__ import annotations

from collections.abc import Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from lexilux.chat.tools import Tool, ToolChoice


[docs] @dataclass class ChatParams: """ Standard parameters for chat completion requests. This class defines the most commonly used parameters for OpenAI-compatible chat completion APIs. All parameters are optional and have sensible defaults. Attributes: temperature: What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. Default: 0.7 top_p: An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. Range: 0.0 to 1.0. Default: 1.0 max_tokens: The maximum number of tokens to generate in the chat completion. The total length of input tokens and generated tokens is limited by the model's context length. Default: None (no limit, up to model's maximum) stop: Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. Can be a single string or a list of strings. Default: None presence_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. Default: 0.0 frequency_penalty: Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. Default: 0.0 logit_bias: Modify the likelihood of specified tokens appearing in the completion. Accepts a dictionary mapping token IDs (integers) to an associated bias value from -100 to 100. Values around -100 should decrease the likelihood of the token appearing, while values around 100 should increase it. Default: None (empty dict) user: A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. This is useful for tracking and rate limiting. Default: None n: How many chat completion choices to generate for each input message. Note: Most implementations return only the first choice. This parameter is included for compatibility but may not be fully supported by all providers. Default: 1 tools: List of tools (functions) that the model may call. Enables function calling capabilities. When provided, the model can decide to call these functions instead of or in addition to generating text. Default: None (no tools) tool_choice: Controls when the model uses tools. Can be "auto" (model decides), "required" (must call tools), a specific tool name, or a ToolChoice object. Default: None (auto mode) parallel_tool_calls: Whether to enable parallel function calling. When True, the model may call multiple functions in a single turn. Default: None (provider default) extra: Additional custom parameters for OpenAI-compatible servers that may accept non-standard parameters. These will be merged into the request payload. Common use cases: - Provider-specific experimental features - Custom provider options not in OpenAI standard - Specialized model behaviors (e.g., response format, seed) For parameter name mapping, use param_aliases instead of extra when the provider uses standard OpenAI-compatible parameters with different keys. Default: None (empty dict) param_aliases: Parameter name mapping for edge cases where providers use different names for standard OpenAI parameters. Most providers won't need this feature. Maps standard OpenAI parameter names to provider-specific names. Applied after standard parameter processing but before extra merging. Example (rare cases): >>> params = ChatParams( ... temperature=0.7, ... param_aliases={"temperature": "temp"} ... ) # Sends: {"temp": 0.7} instead of {"temperature": 0.7} Default: None (no mapping needed for standard providers) Examples: Basic usage with defaults: >>> params = ChatParams() >>> # temperature=0.7, top_p=1.0, etc. Custom temperature and max_tokens: >>> params = ChatParams(temperature=0.5, max_tokens=100) With stop sequences: >>> params = ChatParams(stop=["\\n\\n", "Human:"]) With penalties: >>> params = ChatParams( ... presence_penalty=0.6, ... frequency_penalty=0.3 ... ) With tools: >>> from lexilux.chat.tools import FunctionTool >>> params = ChatParams( ... tools=[ ... FunctionTool( ... name="get_weather", ... description="Get current weather", ... parameters={"type": "object", "properties": {...}} ... ) ... ] ... ) With custom provider features: >>> params = ChatParams( ... temperature=0.8, ... extra={ ... "response_format": {"type": "json_object"}, ... "seed": 12345, ... "logprobs": True, ... "top_logprobs": 5 ... } ... ) With parameter aliases (rare cases): >>> params = ChatParams( ... temperature=0.7, ... param_aliases={"temperature": "temp"} ... ) """ temperature: float = 0.7 top_p: float = 1.0 max_tokens: int | None = None stop: str | Sequence[str] | None = None presence_penalty: float = 0.0 frequency_penalty: float = 0.0 logit_bias: dict[int, float] | None = None user: str | None = None n: int = 1 # Tool calling parameters tools: list[Tool] | None = None tool_choice: str | ToolChoice | None = None parallel_tool_calls: bool | None = None # Reasoning mode (extended thinking) reasoning: bool | dict[str, Any] | None = None # Extra parameters extra: dict[str, Any] | None = None # ✅ NEW: Parameter alias mapping param_aliases: dict[str, str] | None = None
[docs] def to_dict(self, exclude_none: bool = True) -> dict[str, Any]: """ Convert parameters to dictionary for API request. Args: exclude_none: Whether to exclude None values from the output. Default: True Returns: Dictionary of parameters ready for API request. Examples: Basic usage: >>> params = ChatParams(temperature=0.5, max_tokens=100) >>> params.to_dict() {'temperature': 0.5, 'top_p': 1.0, 'max_tokens': 100, ...} With parameter aliases: >>> params = ChatParams( ... temperature=0.8, ... param_aliases={"temperature": "temp"} # Some providers use "temp" ... ) >>> params.to_dict() {'temp': 0.8, 'top_p': 1.0, ...} """ result: dict[str, Any] = {} # Add standard parameters if not exclude_none or self.temperature is not None: result["temperature"] = self.temperature if not exclude_none or self.top_p is not None: result["top_p"] = self.top_p if not exclude_none or self.max_tokens is not None: result["max_tokens"] = self.max_tokens if not exclude_none or self.stop is not None: if self.stop is not None: if isinstance(self.stop, str): result["stop"] = [self.stop] else: result["stop"] = list(self.stop) if not exclude_none or self.presence_penalty != 0.0: result["presence_penalty"] = self.presence_penalty if not exclude_none or self.frequency_penalty != 0.0: result["frequency_penalty"] = self.frequency_penalty if not exclude_none or self.logit_bias is not None: if self.logit_bias is not None: result["logit_bias"] = self.logit_bias if not exclude_none or self.user is not None: if self.user is not None: result["user"] = self.user if not exclude_none or self.n != 1: result["n"] = self.n # Add tools parameters if not exclude_none or self.tools is not None: if self.tools is not None: result["tools"] = [tool.to_dict() for tool in self.tools] if not exclude_none or self.tool_choice is not None: if self.tool_choice is not None: if isinstance(self.tool_choice, str): result["tool_choice"] = self.tool_choice else: result["tool_choice"] = self.tool_choice.to_dict() if not exclude_none or self.parallel_tool_calls is not None: if self.parallel_tool_calls is not None: result["parallel_tool_calls"] = self.parallel_tool_calls # ✅ NEW: Apply parameter aliases if self.param_aliases: aliased_params = {} for standard_key, provider_key in self.param_aliases.items(): if standard_key in result: # Move parameter to provider-specific key aliased_params[provider_key] = result[standard_key] del result[standard_key] result.update(aliased_params) # Merge extra parameters (lowest priority) if self.extra: result.update(self.extra) return result