Compare commits

..

7 Commits

Author SHA1 Message Date
Matteo Rosati
865f4ee1b6 remove sensitive logs 2026-01-29 15:07:10 +01:00
Matteo Rosati
3a7f329499 MEDIUM thinking level is not supported by this model 2026-01-29 15:05:00 +01:00
Matteo Rosati
f14c56ddd3 explicit project_id 2026-01-29 15:02:18 +01:00
Matteo Rosati
da726dc777 add missing scopes 2026-01-29 14:40:43 +01:00
Matteo Rosati
ead140a2f4 add logging 2026-01-29 14:20:01 +01:00
Matteo Rosati
20919298c8 google credentials 2026-01-29 12:54:47 +01:00
Matteo Rosati
b18c56e2f2 remove copy 2026-01-29 10:49:45 +01:00
4 changed files with 72 additions and 5 deletions

View File

@@ -1,4 +1,12 @@
# Google Cloud Authentication - Choose ONE of the following methods:
# Option 1: Local development - Path to JSON credentials file
GOOGLE_APPLICATION_CREDENTIALS=credentials.json
# Option 2: Production - JSON content as string (useful for serverless platforms like Vercel)
# Paste the entire JSON content of your service account key here
# GOOGLE_CREDENTIALS_JSON={"type":"service_account","project_id":"..."}
PORT=8000
HOST=0.0.0.0
BASIC_AUTH_USERNAME=admin

View File

@@ -55,7 +55,6 @@ COPY --chown=appuser:appuser llm_config.py .
COPY --chown=appuser:appuser lib.py .
RUN echo $CREDENTIALS > credentials.json
COPY --chown=appuser:appuser credentials.json .
COPY --chown=appuser:appuser static ./static
# Copy and setup entrypoint script

66
lib.py
View File

@@ -4,18 +4,71 @@ This module provides functionality to generate content using Google's Gemini mod
with Vertex AI RAG (Retrieval-Augmented Generation) support.
"""
from llm_config import generate_content_config
import logging
import asyncio
import json
import os
import threading
from google import genai
from google.genai import types
from google.oauth2 import service_account
from dotenv import load_dotenv
from llm_config import generate_content_config
logger = logging.getLogger(__name__)
# Load environment variables from .env file
load_dotenv()
def get_credentials():
"""Get Google Cloud credentials and project ID from environment.
Supports two methods:
1. GOOGLE_CREDENTIALS_JSON: Direct JSON content as string (production)
2. GOOGLE_APPLICATION_CREDENTIALS: Path to JSON file (local development)
Returns:
tuple: (credentials, project_id) where credentials is a
service_account.Credentials object and project_id is the Google Cloud project
"""
# OAuth scopes required for Vertex AI API
SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
# Try to load credentials from JSON content directly
credentials_json = os.getenv("GOOGLE_CREDENTIALS_JSON")
if credentials_json:
try:
credentials_info = json.loads(credentials_json)
project_id = credentials_info.get("project_id")
credentials = service_account.Credentials.from_service_account_info(
credentials_info, scopes=SCOPES
)
return credentials, project_id
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON in GOOGLE_CREDENTIALS_JSON: {e}")
# Fall back to file-based credentials (standard behavior)
credentials_path = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
if credentials_path and os.path.exists(credentials_path):
with open(credentials_path) as f:
credentials_info = json.load(f)
project_id = credentials_info.get("project_id")
credentials = service_account.Credentials.from_service_account_file(
credentials_path, scopes=SCOPES
)
return credentials, project_id
# If neither is provided, return None to let the client use default credentials
# (useful when running on Google Cloud with service account attached)
return None, None
# Gemini model name
GEMINI_MODEL: str = "gemini-3-pro-preview"
@@ -42,10 +95,17 @@ async def generate(prompt: str):
def run_streaming():
"""Run the synchronous streaming in a separate thread."""
try:
client = genai.Client(vertexai=True)
credentials, project_id = get_credentials()
client = genai.Client(
vertexai=True,
credentials=credentials,
project=project_id
)
contents = [
types.Content(role="user", parts=[types.Part.from_text(text=prompt)]),
types.Content(role="user", parts=[
types.Part.from_text(text=prompt)]),
]
for chunk in client.models.generate_content_stream(

View File

@@ -34,6 +34,6 @@ generate_content_config = types.GenerateContentConfig(
],
tools=tools,
thinking_config=types.ThinkingConfig(
thinking_level="MEDIUM",
thinking_level="HIGH",
),
)