# app.py import os import shutil import textwrap import streamlit as st from huggingface_hub import hf_hub_download from rag_pipeline import ( load_vectorstore, search_chunks, generate_answer, ) # ---------------------------------------------------- # Yollar # ---------------------------------------------------- VSTORE_DIR = "./vectorstore" NEEDED = ["index.faiss", "meta.jsonl"] # signature.json opsiyonel # ---------------------------------------------------- # Vectorstore bootstrap: Dosyalar yoksa Space repo'sundan indir # ---------------------------------------------------- def ensure_vectorstore(vstore_dir: str = VSTORE_DIR) -> None: os.makedirs(vstore_dir, exist_ok=True) missing = [f for f in NEEDED if not os.path.exists(os.path.join(vstore_dir, f))] if not missing: return # her şey zaten var # Space içinde otomatik olarak set edilir: "/" space_id = os.getenv("SPACE_ID") # örn: "ecceembusra/turkish-wikipedia-rag" if not space_id: # Lokal çalıştırıyorsan buraya manuel repo id yazabilirsin: # space_id = "ecceembusra/turkish-wikipedia-rag" return # Space dışında otomatik indirme yapmayalım for fname in missing: repo_path = f"vectorstore/{fname}" try: downloaded = hf_hub_download( repo_id=space_id, filename=repo_path, repo_type="space", ) shutil.copyfile(downloaded, os.path.join(vstore_dir, fname)) except Exception as e: # İndirme başarısız olursa sessiz kalmayalım; kullanıcıya göstereceğiz raise FileNotFoundError( f"'{repo_path}' indirilemedi veya bulunamadı. " f"Lütfen bu dosyayı Space deposunda 'vectorstore/' klasörüne yükleyin." ) from e # ---------------------------------------------------- # Streamlit sayfa ayarları # ---------------------------------------------------- st.set_page_config( page_title="Turkish Wikipedia Q&A (Gemini RAG)", page_icon="🧠", layout="centered", ) @st.cache_resource(show_spinner=False) def _load_vdb(): # Dosyalar yoksa kendi Space'inden çek ensure_vectorstore(VSTORE_DIR) # rag_pipeline.load_vectorstore(vstore_dir="...") imzasını destekliyor return load_vectorstore(VSTORE_DIR) st.title("🧠 Turkish Wikipedia Q&A") with st.expander("⚙️ Ayarlar", expanded=False): top_k = st.slider("Top K (kaç pasaj getirilsin?)", 2, 8, 5) show_passages = st.checkbox("Getirilen pasaj özetini göster", value=True) has_gemini = bool(os.getenv("GOOGLE_API_KEY") or st.secrets.get("GOOGLE_API_KEY", None)) st.info(f"LLM: {'Gemini ✅' if has_gemini else 'Yapılandırılmadı ❌'}") query = st.text_input("📝 Sorunuzu yazın (ör. “Türkiye'nin ilk kadın pilotu kimdir?”)") if st.button("Cevabı Getir", type="primary", use_container_width=True) and query.strip(): try: with st.spinner("Aranıyor ve cevap oluşturuluyor..."): index, records = _load_vdb() answer = generate_answer(query.strip(), index, records, top_k=top_k) hits = search_chunks(query.strip(), index, records, top_k=top_k) st.subheader("✅ Yanıt") st.write(answer if answer else "_Cevap üretilemedi._") st.subheader("🔎 Kaynaklar") if hits: for i, h in enumerate(hits, 1): title = h.get("title") or "(başlık yok)" url = h.get("source") or "" score = float(h.get("score_rerank", h.get("score_boosted", 0.0))) lead = textwrap.shorten((h.get("text") or "").replace("\n", " "), width=220, placeholder="…") if url: st.markdown(f"**{i}.** [{title}]({url}) \nRerank skoru: `{score:.3f}`") else: st.markdown(f"**{i}.** {title} \nRerank skoru: `{score:.3f}`") if show_passages and lead: st.caption(lead) st.markdown("---") else: st.write("_Kaynak bulunamadı._") except FileNotFoundError as e: st.error( "Vektör deposu bulunamadı. `vectorstore/index.faiss` ve `vectorstore/meta.jsonl` " "dosyalarının Space'in kökünde `vectorstore/` klasöründe olduğundan emin olun." ) st.code(str(e)) except Exception as e: st.error("Bir hata oluştu.") st.exception(e)