LocalMate / app /shared /integrations /gemini_client.py
Cuong2004's picture
Initial HF deployment
ca7a2c2
"""Gemini client for LLM operations using Google GenAI."""
import json
import re
from google import genai
from app.core.config import settings
# Initialize Google GenAI client
client = genai.Client(api_key=settings.google_api_key)
class GeminiClient:
"""Client for Gemini LLM operations."""
def __init__(self, model: str | None = None):
"""Initialize with optional model override."""
self.model = model or settings.default_gemini_model
async def chat(
self,
messages: list[dict],
temperature: float = 0.7,
system_instruction: str | None = None,
) -> str:
"""
Generate chat completion using Gemini.
Args:
messages: List of message dicts with 'role' and 'parts'
temperature: Sampling temperature (0.0 - 1.0)
system_instruction: Optional system prompt
Returns:
Generated text response
"""
config = {"temperature": temperature}
if system_instruction:
config["system_instruction"] = system_instruction
response = client.models.generate_content(
model=self.model,
contents=messages,
config=config,
)
return response.text
async def generate(
self,
prompt: str,
temperature: float = 0.7,
system_instruction: str | None = None,
) -> str:
"""
Simple text generation.
Args:
prompt: Text prompt
temperature: Sampling temperature
system_instruction: Optional system prompt
Returns:
Generated text
"""
config = {"temperature": temperature}
if system_instruction:
config["system_instruction"] = system_instruction
response = client.models.generate_content(
model=self.model,
contents=prompt,
config=config,
)
return response.text
async def parse_tool_calls(self, user_message: str, available_tools: list[dict]) -> dict:
"""
Parse user message to determine which MCP tools to call.
Args:
user_message: User's natural language query
available_tools: List of available tool definitions
Returns:
Dict with tool_name and arguments
"""
tools_desc = "\n".join([
f"- {t['name']}: {t['description']}" for t in available_tools
])
prompt = f'''Bạn là AI assistant phân tích intent. Xác định công cụ cần gọi.
Các công cụ có sẵn:
{tools_desc}
Query của người dùng: "{user_message}"
Trả về JSON (chỉ JSON, không giải thích):
{{
"tool_name": "tên_tool_cần_gọi",
"arguments": {{...}},
"reasoning": "lý do chọn tool này"
}}
Nếu không cần gọi tool, trả về:
{{"tool_name": null, "arguments": {{}}, "reasoning": "..."}}'''
response = await self.generate(prompt, temperature=0.3)
try:
json_match = re.search(r'\{[^{}]*\}', response, re.DOTALL)
if json_match:
return json.loads(json_match.group())
return json.loads(response)
except json.JSONDecodeError:
return {"tool_name": None, "arguments": {}, "reasoning": "Failed to parse"}
def get_gemini_client(model: str | None = None) -> GeminiClient:
"""Factory function to create Gemini client with specified model."""
return GeminiClient(model=model)
# Global Gemini client instance (with default model)
gemini_client = GeminiClient()