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 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 PORT=8000
HOST=0.0.0.0 HOST=0.0.0.0
BASIC_AUTH_USERNAME=admin BASIC_AUTH_USERNAME=admin

View File

@@ -55,7 +55,6 @@ COPY --chown=appuser:appuser llm_config.py .
COPY --chown=appuser:appuser lib.py . COPY --chown=appuser:appuser lib.py .
RUN echo $CREDENTIALS > credentials.json RUN echo $CREDENTIALS > credentials.json
COPY --chown=appuser:appuser credentials.json .
COPY --chown=appuser:appuser static ./static COPY --chown=appuser:appuser static ./static
# Copy and setup entrypoint script # 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. with Vertex AI RAG (Retrieval-Augmented Generation) support.
""" """
from llm_config import generate_content_config
import logging
import asyncio import asyncio
import json
import os
import threading import threading
from google import genai from google import genai
from google.genai import types from google.genai import types
from google.oauth2 import service_account
from dotenv import load_dotenv from dotenv import load_dotenv
from llm_config import generate_content_config logger = logging.getLogger(__name__)
# Load environment variables from .env file # Load environment variables from .env file
load_dotenv() 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 name
GEMINI_MODEL: str = "gemini-3-pro-preview" GEMINI_MODEL: str = "gemini-3-pro-preview"
@@ -42,10 +95,17 @@ async def generate(prompt: str):
def run_streaming(): def run_streaming():
"""Run the synchronous streaming in a separate thread.""" """Run the synchronous streaming in a separate thread."""
try: try:
client = genai.Client(vertexai=True) credentials, project_id = get_credentials()
client = genai.Client(
vertexai=True,
credentials=credentials,
project=project_id
)
contents = [ 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( for chunk in client.models.generate_content_stream(

View File

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