diff --git a/agent/memory/embedding.py b/agent/memory/embedding.py index db182f12..ea8c7538 100644 --- a/agent/memory/embedding.py +++ b/agent/memory/embedding.py @@ -138,24 +138,24 @@ def create_embedding_provider( ) -> EmbeddingProvider: """ Factory function to create embedding provider - - Only supports OpenAI embedding via REST API. + + Supports "openai" and "linkai" providers (both use OpenAI-compatible REST API). If initialization fails, caller should fall back to keyword-only search. - + Args: - provider: Provider name (only "openai" is supported) + provider: Provider name ("openai" or "linkai") model: Model name (default: text-embedding-3-small) - api_key: OpenAI API key (required) - api_base: API base URL (default: https://api.openai.com/v1) + api_key: API key (required) + api_base: API base URL Returns: EmbeddingProvider instance Raises: - ValueError: If provider is not "openai" or api_key is missing + ValueError: If provider is unsupported or api_key is missing """ - if provider != "openai": - raise ValueError(f"Only 'openai' provider is supported, got: {provider}") + if provider not in ("openai", "linkai"): + raise ValueError(f"Unsupported embedding provider: {provider}. Use 'openai' or 'linkai'.") model = model or "text-embedding-3-small" return OpenAIEmbeddingProvider(model=model, api_key=api_key, api_base=api_base) diff --git a/agent/memory/manager.py b/agent/memory/manager.py index e0f39f99..00e4c960 100644 --- a/agent/memory/manager.py +++ b/agent/memory/manager.py @@ -50,28 +50,44 @@ class MemoryManager: overlap_tokens=self.config.chunk_overlap_tokens ) - # Initialize embedding provider (optional) + # Initialize embedding provider (optional, prefer OpenAI, fallback to LinkAI) self.embedding_provider = None if embedding_provider: self.embedding_provider = embedding_provider else: - # Try to create embedding provider, but allow failure + # Try OpenAI first try: - # Get API key from environment or config api_key = os.environ.get('OPENAI_API_KEY') api_base = os.environ.get('OPENAI_API_BASE') - - self.embedding_provider = create_embedding_provider( - provider=self.config.embedding_provider, - model=self.config.embedding_model, - api_key=api_key, - api_base=api_base - ) + if api_key: + self.embedding_provider = create_embedding_provider( + provider="openai", + model=self.config.embedding_model, + api_key=api_key, + api_base=api_base + ) except Exception as e: - # Embedding provider failed, but that's OK - # We can still use keyword search and file operations from common.log import logger - logger.warning(f"[MemoryManager] Embedding provider initialization failed: {e}") + logger.warning(f"[MemoryManager] OpenAI embedding failed: {e}") + + # Fallback to LinkAI + if self.embedding_provider is None: + try: + linkai_key = os.environ.get('LINKAI_API_KEY') + linkai_base = os.environ.get('LINKAI_API_BASE', 'https://api.link-ai.tech') + if linkai_key: + self.embedding_provider = create_embedding_provider( + provider="linkai", + model=self.config.embedding_model, + api_key=linkai_key, + api_base=f"{linkai_base}/v1" + ) + except Exception as e: + from common.log import logger + logger.warning(f"[MemoryManager] LinkAI embedding failed: {e}") + + if self.embedding_provider is None: + from common.log import logger logger.info(f"[MemoryManager] Memory will work with keyword search only (no vector search)") # Initialize memory flush manager diff --git a/bridge/agent_initializer.py b/bridge/agent_initializer.py index b866f201..e7fa99f0 100644 --- a/bridge/agent_initializer.py +++ b/bridge/agent_initializer.py @@ -272,12 +272,11 @@ class AgentInitializer: from agent.tools import MemorySearchTool, MemoryGetTool from config import conf - # Get OpenAI config + # Initialize embedding provider (prefer OpenAI, fallback to LinkAI) + embedding_provider = None + openai_api_key = conf().get("open_ai_api_key", "") openai_api_base = conf().get("open_ai_api_base", "") - - # Initialize embedding provider - embedding_provider = None if openai_api_key and openai_api_key not in ["", "YOUR API KEY", "YOUR_API_KEY"]: try: embedding_provider = create_embedding_provider( @@ -290,6 +289,22 @@ class AgentInitializer: logger.info("[AgentInitializer] OpenAI embedding initialized") except Exception as e: logger.warning(f"[AgentInitializer] OpenAI embedding failed: {e}") + + if embedding_provider is None: + linkai_api_key = conf().get("linkai_api_key", "") or os.environ.get("LINKAI_API_KEY", "") + linkai_api_base = conf().get("linkai_api_base", "https://api.link-ai.tech") + if linkai_api_key and linkai_api_key not in ["", "YOUR API KEY", "YOUR_API_KEY"]: + try: + embedding_provider = create_embedding_provider( + provider="linkai", + model="text-embedding-3-small", + api_key=linkai_api_key, + api_base=f"{linkai_api_base}/v1" + ) + if session_id is None: + logger.info("[AgentInitializer] LinkAI embedding initialized (fallback)") + except Exception as e: + logger.warning(f"[AgentInitializer] LinkAI embedding failed: {e}") # Create memory manager memory_config = MemoryConfig(workspace_root=workspace_root)