Spaces:
Runtime error
Runtime error
File size: 6,709 Bytes
e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 1bfb390 b4c7867 e12c660 b4c7867 e12c660 b4c7867 1bfb390 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 e12c660 b4c7867 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | import os
import time
from datetime import datetime
import gradio as gr
from src.backend.notebooks import create_notebook, rename_notebook, delete_notebook
from src.storage.index_store import list_notebooks
from src.storage.paths import ensure_tree, nb_root
from src.storage.chat_store import append_chat, load_chat
from src.storage.artifact_store import list_artifacts as list_artifacts_store, next_artifact_path
from src.backend.ingest import ingest_files as ingest_files_backend, ingest_url as ingest_url_backend
from src.backend.rag import retrieve, rag_answer
from src.backend.artifacts import (
generate_report,
generate_quiz,
generate_podcast_transcript,
transcript_to_mp3,
)
def now_iso():
return datetime.utcnow().isoformat() + "Z"
def _require_notebook(notebook_id: str):
if not notebook_id:
raise gr.Error("Please create/select a notebook first.")
def chat_pairs(history):
pairs = []
last_user = None
for m in history:
if m.get("role") == "user":
last_user = m.get("content", "")
elif m.get("role") == "assistant":
pairs.append((last_user or "", m.get("content", "")))
last_user = None
return pairs
def ui_bootstrap(username: str):
nbs = list_notebooks(username)
if not nbs:
nb_id = create_notebook(username, "My First Notebook")
nbs = list_notebooks(username)
current = nb_id
else:
current = nbs[0][1]
ensure_tree(username, current)
history = load_chat(username, current)
artifacts = list_artifacts_store(username, current)
return gr.Dropdown(choices=nbs, value=current), chat_pairs(history), artifacts
def on_switch_notebook(username: str, notebook_id: str):
_require_notebook(notebook_id)
ensure_tree(username, notebook_id)
history = load_chat(username, notebook_id)
return chat_pairs(history), list_artifacts_store(username, notebook_id)
def on_create_notebook(username: str, name: str):
name = (name or "").strip() or "Untitled Notebook"
nb_id = create_notebook(username, name)
nbs = list_notebooks(username)
ensure_tree(username, nb_id)
return gr.Dropdown(choices=nbs, value=nb_id), [], list_artifacts_store(username, nb_id)
def on_rename_notebook(username: str, notebook_id: str, new_name: str):
_require_notebook(notebook_id)
new_name = (new_name or "").strip()
if not new_name:
raise gr.Error("Enter a new notebook name.")
rename_notebook(username, notebook_id, new_name)
return gr.Dropdown(choices=list_notebooks(username), value=notebook_id)
def on_delete_notebook(username: str, notebook_id: str):
_require_notebook(notebook_id)
delete_notebook(username, notebook_id)
# Return the bootstrap tuple (dropdown, chat, artifacts)
return ui_bootstrap(username)
def on_ingest_files(username: str, notebook_id: str, files):
_require_notebook(notebook_id)
if not files:
raise gr.Error("Upload at least one file.")
try:
added = ingest_files_backend(username, notebook_id, files)
except Exception as e:
raise gr.Error(f"File ingest failed: {e}")
if added == 0:
raise gr.Error("No chunks were indexed. Use supported files (PDF/PPTX/TXT) with extractable text.")
return f"Ingested files. Added {added} chunks."
def on_ingest_url(username: str, notebook_id: str, url: str):
_require_notebook(notebook_id)
url = (url or "").strip()
if not url:
raise gr.Error("Enter a URL.")
try:
added = ingest_url_backend(username, notebook_id, url)
except Exception as e:
raise gr.Error(f"URL ingest failed: {e}")
if added == 0:
raise gr.Error("No chunks were indexed from the URL.")
return f"Ingested URL. Added {added} chunks."
def on_chat(username: str, notebook_id: str, chatbot, msg: str):
_require_notebook(notebook_id)
msg = (msg or "").strip()
if not msg:
return chatbot, ""
t0 = time.time()
append_chat(username, notebook_id, {"role": "user", "content": msg, "ts": now_iso()})
hits = retrieve(username, notebook_id, msg, k=6)
ans = rag_answer(msg, hits)
append_chat(
username,
notebook_id,
{
"role": "assistant",
"content": ans,
"ts": now_iso(),
"latency_ms": int((time.time() - t0) * 1000),
},
)
chatbot = chatbot + [(msg, ans)]
return chatbot, ""
def on_report(username: str, notebook_id: str, topic: str, extra: str):
_require_notebook(notebook_id)
topic = (topic or "").strip()
if not topic:
raise gr.Error("Enter a topic.")
hits = retrieve(username, notebook_id, topic, k=6)
if not hits:
raise gr.Error("No sources yet. Ingest files/URL first.")
md = generate_report(topic, hits, extra)
out = next_artifact_path(username, notebook_id, "reports", ".md")
with open(out, "w", encoding="utf-8") as f:
f.write(md)
return "Report generated.", list_artifacts_store(username, notebook_id), out
def on_quiz(username: str, notebook_id: str, topic: str, extra: str):
_require_notebook(notebook_id)
topic = (topic or "").strip()
if not topic:
raise gr.Error("Enter a topic.")
hits = retrieve(username, notebook_id, topic, k=6)
if not hits:
raise gr.Error("No sources yet. Ingest files/URL first.")
md = generate_quiz(topic, hits, extra)
out = next_artifact_path(username, notebook_id, "quizzes", ".md")
with open(out, "w", encoding="utf-8") as f:
f.write(md)
return "Quiz generated.", list_artifacts_store(username, notebook_id), out
def on_podcast(username: str, notebook_id: str, topic: str, extra: str):
_require_notebook(notebook_id)
topic = (topic or "").strip()
if not topic:
raise gr.Error("Enter a topic.")
hits = retrieve(username, notebook_id, topic, k=6)
if not hits:
raise gr.Error("No sources yet. Ingest files/URL first.")
md = generate_podcast_transcript(topic, hits, extra)
md_path = next_artifact_path(username, notebook_id, "podcasts", ".md")
with open(md_path, "w", encoding="utf-8") as f:
f.write(md)
mp3_path = next_artifact_path(username, notebook_id, "podcasts", ".mp3")
transcript_to_mp3(md, mp3_path)
return "Podcast generated.", list_artifacts_store(username, notebook_id), md_path, mp3_path
def on_download(username: str, notebook_id: str, selection: str):
_require_notebook(notebook_id)
if not selection:
return None
p = os.path.join(nb_root(username, notebook_id), "artifacts", selection)
return p if os.path.exists(p) else None |