| import streamlit as st |
| import base64 |
| import os |
| from rag_core import process_pdf_to_vectorstore, get_rag_answer |
| |
|
|
| |
| |
| current_dir = os.path.dirname(os.path.abspath(__file__)) |
| root_dir = os.path.dirname(current_dir) |
| svg_path = os.path.join(root_dir, "assets", "pdfi-avatar.svg") |
| favicon_path = os.path.join(root_dir, "assets", "favicon-pdfi.svg") |
|
|
| |
| |
| st.set_page_config(page_title="Ask PDFi", page_icon=favicon_path, layout="centered") |
|
|
| |
| st.markdown(""" |
| <style> |
| /* Disclaimer direkt unter dem Streamlit Chat-Eingabefeld anheften */ |
| [data-testid="stChatInput"]::after { |
| content: "Ask PDFi kann Fehler machen. Bitte überprüfe wichtige Informationen. Deine Daten werden nur lokal und temporär im RAM verarbeitet."; |
| display: block; |
| font-size: 0.75rem; |
| color: #888888; |
| text-align: center; |
| margin-top: 8px; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| |
| |
| if "messages" not in st.session_state: |
| st.session_state.messages = [] |
| if "pdf_processed" not in st.session_state: |
| st.session_state.pdf_processed = False |
|
|
| |
| with st.sidebar: |
| st.header("📄 Dokumenten-Upload") |
| uploaded_file = st.file_uploader("PDF hier ablegen", type=["pdf"]) |
| |
| if uploaded_file is None: |
| st.session_state.pdf_processed = False |
| st.info("Bitte lade ein PDF hoch, um zu starten.") |
| else: |
| if st.button("PDF verarbeiten"): |
| |
| with st.spinner("PDFi überfliegt das Dokument..."): |
| |
| st.session_state.vectorstore = process_pdf_to_vectorstore(uploaded_file) |
| st.session_state.pdf_processed = True |
| st.success("Dokument erfolgreich im Nest abgelegt!") |
|
|
| |
| st.markdown("---") |
| with st.expander("⚖️ Impressum & Datenschutz"): |
| st.markdown(""" |
| **Angaben gemäß § 5 TMG:** |
| |
| Lars Patzenbein |
| |
| **Kontakt:** E-Mail: kontakt@askpdfi.com |
| |
| --- |
| **Datenschutz & Security:** Diese Anwendung ist ein lokaler RAG-Prototyp. Sie läuft vollständig autark. Alle hochgeladenen Dokumente und Chat-Verläufe werden **ausschließlich temporär im Arbeitsspeicher (RAM)** verarbeitet. |
| |
| Es findet keine Speicherung auf Festplatten statt und es fließen **keine Daten an externe APIs oder Drittanbieter**. Nach Beendigung der Sitzung oder einem Neuladen der Seite werden alle Daten restlos gelöscht. |
| """) |
|
|
| |
| |
| def get_image_base64(path): |
| with open(path, "rb") as image_file: |
| return base64.b64encode(image_file.read()).decode() |
|
|
| svg_base64 = get_image_base64(svg_path) |
|
|
| |
| st.markdown(f""" |
| <div style="display: flex; align-items: center; margin-bottom: 15px;"> |
| <img src="data:image/svg+xml;base64,{svg_base64}" width="75" height="75" style="margin-right: 15px;"> |
| <h1 style="margin: 0; padding: 0;">Ask PDFi</h1> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| st.markdown("""Deine smarte Tech-Eule für Dokumentenanalyse. Stelle komplexe Fragen zu deinen PDFs und **PDFi** findet die Antworten mit der Power von **Llama 3.1 8B**.""") |
| st.markdown("<hr style='border: 1px solid #FF6600; opacity: 0.5;'>", unsafe_allow_html=True) |
|
|
| |
| for message in st.session_state.messages: |
| |
| avatar = svg_path if message["role"] == "assistant" else "👤" |
| with st.chat_message(message["role"], avatar=avatar): |
| st.markdown(message["content"]) |
|
|
| |
| |
| if not st.session_state.pdf_processed: |
| st.chat_input("Bitte lade zuerst ein PDF in der Seitenleiste hoch.", disabled=True) |
| else: |
| |
| if prompt := st.chat_input("Was möchtest du aus dem PDF wissen?"): |
| |
| |
| st.session_state.messages.append({"role": "user", "content": prompt}) |
| with st.chat_message("user", avatar="👤"): |
| st.markdown(prompt) |
|
|
| |
| with st.chat_message("assistant", avatar=svg_path): |
| |
| |
| |
| answer = st.write_stream(get_rag_answer(st.session_state.vectorstore, prompt)) |
| |
| |
| st.session_state.messages.append({"role": "assistant", "content": answer}) |