import asyncio import os import time from pathlib import Path from concurrent.futures import ThreadPoolExecutor import uuid import google.generativeai as genai from fasthtml.common import ( Div, Img, Main, P, Script, Link, fast_app, HighlightJS, FileResponse, RedirectResponse, Aside, StreamingResponse, JSONResponse, serve, ) from shad4fast import ShadHead from vespa.application import Vespa import base64 from fastcore.parallel import threaded from PIL import Image from backend.colpali import get_query_embeddings_and_token_map, gen_similarity_maps from backend.modelmanager import ModelManager from backend.vespa_app import VespaQueryClient from frontend.app import ( ChatResult, Home, Search, SearchBox, SearchResult, SimMapButtonPoll, SimMapButtonReady, AboutThisDemo, ) 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" ) awesomplete_link = Link( rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.7/awesomplete.min.css", type="text/css", ) awesomplete_js = Script( src="https://cdnjs.cloudflare.com/ajax/libs/awesomplete/1.1.7/awesomplete.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=( highlight_js, highlight_js_theme_link, highlight_js_theme, overlayscrollbars_link, overlayscrollbars_js, awesomplete_link, awesomplete_js, sselink, ShadHead(tw_cdn=False, theme_handle=True), ), ) vespa_app: Vespa = VespaQueryClient() 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 .

, ,