Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| import os | |
| from dataclasses import dataclass | |
| from typing import List | |
| from dotenv import load_dotenv | |
| from langchain_community.chat_message_histories import ChatMessageHistory | |
| from langchain_core.messages import HumanMessage, AIMessage | |
| # ================================ | |
| # Settings / Env | |
| # ================================ | |
| class Settings: | |
| google_api_key: str | |
| file_search_store_name: str | |
| model_name: str = "gemini-2.5-flash" | |
| def load_settings() -> Settings: | |
| load_dotenv() | |
| key = (os.getenv("GOOGLE_API_KEY") or "").strip() | |
| if not (key and len(key) > 10): | |
| raise RuntimeError( | |
| "GOOGLE_API_KEY not found (or looks wrong). Put it in .env as GOOGLE_API_KEY=..." | |
| ) | |
| store = (os.getenv("FILE_SEARCH_STORE_NAME") or "").strip() | |
| if not store: | |
| raise RuntimeError( | |
| "FILE_SEARCH_STORE_NAME not found. Put it in .env as FILE_SEARCH_STORE_NAME=fileSearchStores/..." | |
| ) | |
| model = (os.getenv("GEMINI_MODEL") or "gemini-2.5-flash").strip() | |
| return Settings(google_api_key=key, file_search_store_name=store, model_name=model) | |
| # ================================ | |
| # Memory helpers (keep last ~N words) | |
| # ================================ | |
| def _count_words(msg) -> int: | |
| text = getattr(msg, "content", "") or "" | |
| if isinstance(text, list): | |
| text = " ".join( | |
| [b.get("text", "") if isinstance(b, dict) else str(b) for b in text] | |
| ) | |
| return len(str(text).split()) | |
| def trim_history_to_words( | |
| chat_history: ChatMessageHistory, | |
| max_words: int = 5000, | |
| ) -> List: | |
| msgs = chat_history.messages | |
| total = 0 | |
| kept = [] | |
| for m in reversed(msgs): | |
| w = _count_words(m) | |
| if total + w > max_words: | |
| break | |
| kept.append(m) | |
| total += w | |
| return list(reversed(kept)) | |
| def build_transcript(past_messages: List) -> str: | |
| lines = [] | |
| for m in past_messages: | |
| role = "User" if isinstance(m, HumanMessage) else "Assistant" | |
| lines.append(f"{role}: {getattr(m, 'content', '')}") | |
| return "\n".join(lines).strip() | |
| def load_prompt(path: str) -> str: | |
| with open(path, "r", encoding="utf-8") as f: | |
| return f.read().strip() | |