| import requests |
| import json |
| from typing import List, Dict, Optional |
|
|
|
|
| class ResponseWrapper: |
| def __init__(self, response_data): |
| """ |
| Wrap the response data to support both dict-like and attribute-like access |
| |
| :param response_data: The raw response dictionary from OpenRouter |
| """ |
| self._data = response_data |
| |
| def __getattr__(self, name): |
| """ |
| Allow attribute-style access to the response data |
| |
| :param name: Attribute name to access |
| :return: Corresponding value from the response data |
| """ |
| if name in self._data: |
| value = self._data[name] |
| return self._wrap(value) |
| raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") |
| |
| def __getitem__(self, key): |
| """ |
| Allow dictionary-style access to the response data |
| |
| :param key: Key to access |
| :return: Corresponding value from the response data |
| """ |
| value = self._data[key] |
| return self._wrap(value) |
| |
| def _wrap(self, value): |
| """ |
| Recursively wrap dictionaries and lists to support attribute access |
| |
| :param value: Value to wrap |
| :return: Wrapped value |
| """ |
| if isinstance(value, dict): |
| return ResponseWrapper(value) |
| elif isinstance(value, list): |
| return [self._wrap(item) for item in value] |
| return value |
|
|
| def __iter__(self): |
| """ |
| Allow iteration over the wrapped dictionary |
| """ |
| return iter(self._data) |
|
|
| def get(self, key, default=None): |
| """ |
| Provide a get method similar to dictionary |
| """ |
| return self._wrap(self._data.get(key, default)) |
|
|
| def keys(self): |
| """ |
| Return dictionary keys |
| """ |
| return self._data.keys() |
|
|
| def items(self): |
| """ |
| Return dictionary items |
| """ |
| return [(k, self._wrap(v)) for k, v in self._data.items()] |
|
|
| def __str__(self): |
| """ |
| Return a JSON string representation of the response data |
| |
| :return: JSON-formatted string of the response |
| """ |
| return json.dumps(self._data, indent=2) |
|
|
| def __repr__(self): |
| """ |
| Return a string representation for debugging |
| |
| :return: Representation of the ResponseWrapper |
| """ |
| return f"ResponseWrapper({json.dumps(self._data, indent=2)})" |
|
|
|
|
| class OpenRouter: |
| def __init__(self, api_key: str, base_url: str = "https://openrouter.ai/api/v1"): |
| """ |
| Initialize OpenRouter client |
| |
| :param api_key: API key for OpenRouter |
| :param base_url: Base URL for OpenRouter API (default is standard endpoint) |
| """ |
| self.api_key = api_key |
| self.base_url = base_url |
| self.chat = self.ChatNamespace(self) |
|
|
| class ChatNamespace: |
| def __init__(self, client): |
| self._client = client |
| self.completions = self.CompletionsNamespace(client) |
|
|
| class CompletionsNamespace: |
| def __init__(self, client): |
| self._client = client |
|
|
| def create( |
| self, |
| model: str, |
| messages: List[Dict[str, str]], |
| temperature: float = 0.7, |
| max_tokens: Optional[int] = None, |
| **kwargs |
| ): |
| """ |
| Create a chat completion request |
| |
| :param model: Model to use |
| :param messages: List of message dictionaries |
| :param temperature: Sampling temperature |
| :param max_tokens: Maximum number of tokens to generate |
| :return: Wrapped response object |
| """ |
| headers = { |
| "Authorization": f"Bearer {self._client.api_key}", |
| "Content-Type": "application/json", |
| "HTTP-Referer": kwargs.get("http_referer", "https://your-app-domain.com"), |
| "X-Title": kwargs.get("x_title", "AI Ad Generator") |
| } |
| |
| payload = { |
| "model": model, |
| "messages": messages, |
| "temperature": temperature, |
| } |
|
|
| if model.startswith("deepseek"): |
| payload["provider"] = { |
| "order": [ |
| "DeepSeek", |
| "DeepInfra", |
| "Fireworks", |
| ], |
| "allow_fallbacks": False |
| } |
| |
| if max_tokens is not None: |
| payload["max_tokens"] = max_tokens |
| |
| |
| payload.update({k: v for k, v in kwargs.items() |
| if k not in ["http_referer", "x_title"]}) |
| |
| try: |
| response = requests.post( |
| f"{self._client.base_url}/chat/completions", |
| headers=headers, |
| data=json.dumps(payload) |
| ) |
| |
| response.raise_for_status() |
| |
| |
| return ResponseWrapper(response.json()) |
| |
| except requests.RequestException as e: |
| raise Exception(f"OpenRouter API request failed: {e}") |