import asyncio import base64 import hashlib import io import os import time from concurrent.futures import ThreadPoolExecutor from functools import partial import google.generativeai as genai from fasthtml.common import * from PIL import Image from shad4fast import * from vespa.application import Vespa from backend.cache import LRUCache from backend.colpali import ( add_sim_maps_to_result, get_query_embeddings_and_token_map, is_special_token, ) from backend.modelmanager import ModelManager from backend.vespa_app import VespaQueryClient from frontend.app import ( ChatResult, Home, Search, SearchBox, SearchResult, SimMapButtonPoll, SimMapButtonReady, ) from frontend.layout import Layout highlight_js_theme_link = Link(id="highlight-theme", rel="stylesheet", href="") highlight_js_theme = Script(src="/static/js/highlightjs-theme.js") highlight_js = HighlightJS( langs=["python", "javascript", "java", "json", "xml"], dark="github-dark", light="github", ) overlayscrollbars_link = Link( rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/2.10.0/styles/overlayscrollbars.min.css", type="text/css", ) overlayscrollbars_js = Script( src="https://cdnjs.cloudflare.com/ajax/libs/overlayscrollbars/2.10.0/browser/overlayscrollbars.browser.es5.min.js" ) sselink = Script(src="https://unpkg.com/htmx-ext-sse@2.2.1/sse.js") app, rt = fast_app( htmlkw={"cls": "grid h-full"}, pico=False, hdrs=( ShadHead(tw_cdn=False, theme_handle=True), highlight_js, highlight_js_theme_link, highlight_js_theme, overlayscrollbars_link, overlayscrollbars_js, sselink, ), ) vespa_app: Vespa = VespaQueryClient() result_cache = LRUCache(max_size=20) # Each result can be ~10MB task_cache = LRUCache( max_size=1000 ) # Map from query_id to boolean value - False if not all results are ready. thread_pool = ThreadPoolExecutor() # Gemini config genai.configure(api_key=os.getenv("GEMINI_API_KEY")) GEMINI_SYSTEM_PROMPT = """If the user query is a question, try your best to answer it based on the provided images. If the user query can not be interpreted as a question, or if the answer to the query can not be inferred from the images, answer with the exact phrase "I am sorry, I do not have enough information in the image to answer your question.". Your response should be HTML formatted, but only simple tags, such as .

, ,