Fabio Antonini Claude Sonnet 4.6 commited on
Commit
fef4e33
·
1 Parent(s): 65399d4

Add document upload to RAG tab (rag_add_docs + Accordion UI)

Browse files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. app/grapholab_demo.py +65 -3
app/grapholab_demo.py CHANGED
@@ -1742,6 +1742,52 @@ def _rag_load_docs():
1742
  print(f"[RAG] Embedding done: {embedded}/{len(_rag_chunks)} chunks indexed")
1743
 
1744
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1745
  def rag_query(question: str) -> str:
1746
  if not question or not question.strip():
1747
  return ""
@@ -1799,10 +1845,26 @@ with gr.Blocks() as rag_tab:
1799
  "## Consulente Forense IA\n"
1800
  "Fai domande sulla grafologia forense. Il sistema recupera gli estratti più "
1801
  "rilevanti dalla knowledge base e genera una risposta in italiano con "
1802
- "**Llama 3.2 via Ollama** (locale, nessun dato inviato online).\n\n"
1803
- "Per arricchire la knowledge base aggiungi file PDF o DOCX in `data/knowledge/` "
1804
- "e riavvia l'app. I PDF scansionati vengono trascritti automaticamente con OCR."
1805
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1806
  rag_in = gr.Textbox(
1807
  label="Domanda",
1808
  placeholder="Es: Come si valuta l'inclinazione della scrittura?",
 
1742
  print(f"[RAG] Embedding done: {embedded}/{len(_rag_chunks)} chunks indexed")
1743
 
1744
 
1745
+ def rag_add_docs(files) -> str:
1746
+ """Index uploaded PDF/DOCX files and add them to the live knowledge base."""
1747
+ if not files:
1748
+ return "Nessun file caricato."
1749
+ try:
1750
+ _requests.get(f"{OLLAMA_URL}/api/tags", timeout=3)
1751
+ except Exception:
1752
+ return (
1753
+ "❌ Ollama non raggiungibile — i documenti non possono essere indicizzati.\n"
1754
+ "Avvia `ollama serve` e ricarica."
1755
+ )
1756
+ lines = []
1757
+ for f in files:
1758
+ path = Path(f.name)
1759
+ suffix = path.suffix.lower()
1760
+ try:
1761
+ if suffix == ".pdf":
1762
+ text = _extract_pdf_text(path)
1763
+ elif suffix in (".docx", ".doc"):
1764
+ import docx as _docx
1765
+ doc = _docx.Document(str(path))
1766
+ text = "\n".join(p.text for p in doc.paragraphs)
1767
+ else:
1768
+ lines.append(f"⚠️ `{path.name}` — formato non supportato (solo PDF/DOCX).")
1769
+ continue
1770
+ except Exception as e:
1771
+ lines.append(f"❌ `{path.name}` — errore: {e}")
1772
+ continue
1773
+
1774
+ if not text.strip():
1775
+ lines.append(f"⚠️ `{path.name}` — nessun testo estratto.")
1776
+ continue
1777
+
1778
+ chunks = _chunk_text(text, path.name)
1779
+ embedded = 0
1780
+ for chunk in chunks:
1781
+ emb = _ollama_embed(chunk["text"])
1782
+ if emb is not None:
1783
+ chunk["emb"] = emb
1784
+ embedded += 1
1785
+ _rag_chunks.extend(chunks)
1786
+ lines.append(f"✅ `{path.name}` — {len(chunks)} chunk, {embedded} indicizzati.")
1787
+
1788
+ return "\n".join(lines)
1789
+
1790
+
1791
  def rag_query(question: str) -> str:
1792
  if not question or not question.strip():
1793
  return ""
 
1845
  "## Consulente Forense IA\n"
1846
  "Fai domande sulla grafologia forense. Il sistema recupera gli estratti più "
1847
  "rilevanti dalla knowledge base e genera una risposta in italiano con "
1848
+ "**Llama 3.2 via Ollama** (locale, nessun dato inviato online)."
 
 
1849
  )
1850
+
1851
+ with gr.Accordion("📂 Aggiungi documenti alla knowledge base", open=False):
1852
+ gr.Markdown(
1853
+ "Carica uno o più file PDF o DOCX per arricchire la knowledge base. "
1854
+ "I documenti vengono indicizzati immediatamente e restano disponibili "
1855
+ "per tutta la sessione.\n\n"
1856
+ "I PDF scansionati vengono trascritti automaticamente con OCR.\n\n"
1857
+ "*In alternativa, copia i file in `data/knowledge/` per caricarli automaticamente all'avvio.*"
1858
+ )
1859
+ rag_upload = gr.File(
1860
+ label="Documenti (PDF o DOCX)",
1861
+ file_count="multiple",
1862
+ file_types=[".pdf", ".docx", ".doc"],
1863
+ )
1864
+ rag_upload_btn = gr.Button("Indicizza documenti", variant="secondary")
1865
+ rag_upload_status = gr.Markdown(label="Esito indicizzazione")
1866
+ rag_upload_btn.click(rag_add_docs, inputs=rag_upload, outputs=rag_upload_status)
1867
+
1868
  rag_in = gr.Textbox(
1869
  label="Domanda",
1870
  placeholder="Es: Come si valuta l'inclinazione della scrittura?",