fe691066dd
Add full Google AI (Gemini) support for Graphiti memory system: Backend: - Add google-generativeai dependency to requirements.txt - Create GoogleEmbedder class with text-embedding-004 default model - Create GoogleLLMClient class with gemini-2.0-flash default model - Add GOOGLE to LLMProvider and EmbedderProvider enums - Add google_api_key, google_llm_model, google_embedding_model config - Update factory to create Google LLM client and embedder - Add validation for Google provider configuration Frontend: - Add 'google' to GraphitiLLMProvider and GraphitiEmbeddingProvider types - Add Google AI option to LLM provider dropdown in Setup Wizard - Add Google AI option to embedding provider dropdown - Add Google API key input field with link to Google AI Studio - Update MemoryBackendSection and SecuritySettings components - Update env-handlers to save GOOGLE_API_KEY, GOOGLE_LLM_MODEL, and GOOGLE_EMBEDDING_MODEL to .env files This allows users to use Google's Gemini models for both LLM operations (graph extraction, search, reasoning) and embeddings in Graphiti memory.
176 lines
5.0 KiB
Python
176 lines
5.0 KiB
Python
"""
|
|
Google AI LLM Provider
|
|
======================
|
|
|
|
Google Gemini LLM client implementation for Graphiti.
|
|
Uses the google-generativeai SDK.
|
|
"""
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
if TYPE_CHECKING:
|
|
from graphiti_config import GraphitiConfig
|
|
|
|
from ..exceptions import ProviderError, ProviderNotInstalled
|
|
|
|
|
|
# Default model for Google LLM
|
|
DEFAULT_GOOGLE_LLM_MODEL = "gemini-2.0-flash"
|
|
|
|
|
|
class GoogleLLMClient:
|
|
"""
|
|
Google AI LLM Client using the Gemini API.
|
|
|
|
Implements the LLMClient interface expected by graphiti-core.
|
|
"""
|
|
|
|
def __init__(self, api_key: str, model: str = DEFAULT_GOOGLE_LLM_MODEL):
|
|
"""
|
|
Initialize the Google LLM client.
|
|
|
|
Args:
|
|
api_key: Google AI API key
|
|
model: Model name (default: gemini-2.0-flash)
|
|
"""
|
|
try:
|
|
import google.generativeai as genai
|
|
except ImportError as e:
|
|
raise ProviderNotInstalled(
|
|
f"Google LLM requires google-generativeai. "
|
|
f"Install with: pip install google-generativeai\n"
|
|
f"Error: {e}"
|
|
)
|
|
|
|
self.api_key = api_key
|
|
self.model = model
|
|
|
|
# Configure the Google AI client
|
|
genai.configure(api_key=api_key)
|
|
self._genai = genai
|
|
self._model = genai.GenerativeModel(model)
|
|
|
|
async def generate_response(
|
|
self,
|
|
messages: list[dict[str, Any]],
|
|
response_model: Any = None,
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""
|
|
Generate a response from the LLM.
|
|
|
|
Args:
|
|
messages: List of message dicts with 'role' and 'content'
|
|
response_model: Optional Pydantic model for structured output
|
|
**kwargs: Additional arguments
|
|
|
|
Returns:
|
|
Generated response (string or structured object)
|
|
"""
|
|
import asyncio
|
|
|
|
# Convert messages to Google format
|
|
# Google uses 'user' and 'model' roles
|
|
google_messages = []
|
|
system_instruction = None
|
|
|
|
for msg in messages:
|
|
role = msg.get("role", "user")
|
|
content = msg.get("content", "")
|
|
|
|
if role == "system":
|
|
# Google handles system messages as system_instruction
|
|
system_instruction = content
|
|
elif role == "assistant":
|
|
google_messages.append({"role": "model", "parts": [content]})
|
|
else:
|
|
google_messages.append({"role": "user", "parts": [content]})
|
|
|
|
# Create model with system instruction if provided
|
|
if system_instruction:
|
|
model = self._genai.GenerativeModel(
|
|
self.model,
|
|
system_instruction=system_instruction
|
|
)
|
|
else:
|
|
model = self._model
|
|
|
|
# Generate response
|
|
loop = asyncio.get_event_loop()
|
|
|
|
if response_model:
|
|
# For structured output, use JSON mode
|
|
generation_config = self._genai.GenerationConfig(
|
|
response_mime_type="application/json"
|
|
)
|
|
|
|
response = await loop.run_in_executor(
|
|
None,
|
|
lambda: model.generate_content(
|
|
google_messages,
|
|
generation_config=generation_config
|
|
)
|
|
)
|
|
|
|
# Parse JSON response into the model
|
|
import json
|
|
try:
|
|
data = json.loads(response.text)
|
|
return response_model(**data)
|
|
except (json.JSONDecodeError, Exception):
|
|
# If parsing fails, return raw text
|
|
return response.text
|
|
else:
|
|
response = await loop.run_in_executor(
|
|
None,
|
|
lambda: model.generate_content(google_messages)
|
|
)
|
|
|
|
return response.text
|
|
|
|
async def generate_response_with_tools(
|
|
self,
|
|
messages: list[dict[str, Any]],
|
|
tools: list[Any],
|
|
**kwargs: Any,
|
|
) -> Any:
|
|
"""
|
|
Generate a response with tool calling support.
|
|
|
|
Args:
|
|
messages: List of message dicts
|
|
tools: List of tool definitions
|
|
**kwargs: Additional arguments
|
|
|
|
Returns:
|
|
Generated response with potential tool calls
|
|
"""
|
|
# For now, fall back to regular generation
|
|
# Tool calling can be added later if needed
|
|
return await self.generate_response(messages, **kwargs)
|
|
|
|
|
|
def create_google_llm_client(config: "GraphitiConfig") -> Any:
|
|
"""
|
|
Create Google AI LLM client.
|
|
|
|
Args:
|
|
config: GraphitiConfig with Google settings
|
|
|
|
Returns:
|
|
Google LLM client instance
|
|
|
|
Raises:
|
|
ProviderNotInstalled: If google-generativeai is not installed
|
|
ProviderError: If API key is missing
|
|
"""
|
|
if not config.google_api_key:
|
|
raise ProviderError("Google LLM provider requires GOOGLE_API_KEY")
|
|
|
|
model = config.google_llm_model or DEFAULT_GOOGLE_LLM_MODEL
|
|
|
|
return GoogleLLMClient(
|
|
api_key=config.google_api_key,
|
|
model=model
|
|
)
|