Files

101 lines
3.7 KiB
Python

"""OpenAI-only LLM adapter for Mem0 OSS mode."""
from __future__ import annotations
import logging
import os
from typing import Dict, List, Optional, Union
from mem0.configs.llms.base import BaseLlmConfig
from mem0.configs.llms.openai import OpenAIConfig
from mem0.llms.base import LLMBase
from mem0.llms.openai import OpenAILLM
class DirectOpenAILLM(OpenAILLM):
"""Use OpenAI credentials and requests regardless of router environment."""
def __init__(
self,
config: Optional[Union[BaseLlmConfig, OpenAIConfig, Dict]] = None,
):
if config is None:
config = OpenAIConfig()
elif isinstance(config, dict):
config = OpenAIConfig(**config)
elif isinstance(config, BaseLlmConfig) and not isinstance(config, OpenAIConfig):
config = OpenAIConfig(
model=config.model,
temperature=config.temperature,
api_key=config.api_key,
max_tokens=config.max_tokens,
top_p=config.top_p,
top_k=config.top_k,
enable_vision=config.enable_vision,
vision_details=config.vision_details,
reasoning_effort=getattr(config, "reasoning_effort", None),
http_client_proxies=config.http_client_proxies,
is_reasoning_model=getattr(config, "is_reasoning_model", None),
)
if not config.model:
config.model = "gpt-5-mini"
# Older, partial, and manually edited configs may predate the setup
# marker. Keep the exact default model safe at runtime without
# overriding an explicit user choice or changing the persisted config.
if config.model == "gpt-5-mini" and config.is_reasoning_model is None:
config.is_reasoning_model = True
# Bypass OpenAILLM.__init__: it intentionally selects OpenRouter when
# OPENROUTER_API_KEY is present. LLMBase still owns validation and
# supported-parameter filtering for parity with Mem0's implementation.
LLMBase.__init__(self, config)
api_key = self.config.api_key or os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError(
"OpenAI API key is required for the Hermes Mem0 OSS provider"
)
base_url = (
self.config.openai_base_url
or os.getenv("OPENAI_BASE_URL")
or "https://api.openai.com/v1"
)
from openai import OpenAI
self.client = OpenAI(api_key=api_key, base_url=base_url)
def generate_response(
self,
messages: List[Dict[str, str]],
response_format=None,
tools: Optional[List[Dict]] = None,
tool_choice: str = "auto",
**kwargs,
):
params = self._get_supported_params(messages=messages, **kwargs)
params.update({"model": self.config.model, "messages": messages})
# OpenRouter-only fields are deliberately not added here. ``store`` is
# opt-in so OpenAI-compatible endpoints do not receive unknown fields.
if self.config.store is not None:
params["store"] = self.config.store
if response_format:
params["response_format"] = response_format
if tools:
params["tools"] = tools
params["tool_choice"] = tool_choice
response = self.client.chat.completions.create(**params)
parsed_response = self._parse_response(response, tools)
if self.config.response_callback:
try:
self.config.response_callback(self, response, params)
except Exception:
logging.error("Error running Mem0 OpenAI response callback")
return parsed_response