Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,12 +9,12 @@ from backend.llm_local import generate
|
|
| 9 |
from backend.summarizer import extractive_sents, map_reduce
|
| 10 |
|
| 11 |
|
| 12 |
-
settings.RAW_DIR.
|
| 13 |
-
|
| 14 |
-
|
| 15 |
|
| 16 |
STATE_INDEXED = False
|
| 17 |
|
|
|
|
| 18 |
def list_uploaded_files():
|
| 19 |
files = []
|
| 20 |
for f in settings.RAW_DIR.glob("**/*"):
|
|
@@ -22,6 +22,60 @@ def list_uploaded_files():
|
|
| 22 |
files.append(str(f.relative_to(settings.RAW_DIR)))
|
| 23 |
return sorted(files)
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
def build_index():
|
| 27 |
"""Ingestão (parse) + construção e carga do índice. Mostra erro detalhado no UI."""
|
|
@@ -37,7 +91,6 @@ def build_index():
|
|
| 37 |
STATE_INDEXED = False
|
| 38 |
return f"Falha ao indexar/carregar: **{type(e).__name__}** — {e}"
|
| 39 |
|
| 40 |
-
|
| 41 |
def chat_answer(history, message):
|
| 42 |
"""Carrega o índice se preciso e responde; se falhar, mostra o motivo em vez de 'ERRO!'."""
|
| 43 |
if not history:
|
|
@@ -50,7 +103,6 @@ def chat_answer(history, message):
|
|
| 50 |
return history + [("system", f"Índice não está pronto: **{type(e).__name__}** — {e}\n"
|
| 51 |
"Vá na aba **Upload & Indexar** e clique em **Indexar**.")], ""
|
| 52 |
|
| 53 |
-
|
| 54 |
try:
|
| 55 |
hits = retriever.search(message, top_k=settings.TOP_K)
|
| 56 |
if not hits:
|
|
@@ -63,7 +115,6 @@ def chat_answer(history, message):
|
|
| 63 |
except Exception as e:
|
| 64 |
return history + [("system", f"Falha na busca/resposta: **{type(e).__name__}** — {e}")], ""
|
| 65 |
|
| 66 |
-
|
| 67 |
def summarize_run(filename, pages, chapter, query, style, length):
|
| 68 |
if not STATE_INDEXED:
|
| 69 |
try:
|
|
@@ -95,6 +146,7 @@ def summarize_run(filename, pages, chapter, query, style, length):
|
|
| 95 |
final = map_reduce(hits, focus=query or "resumo", style=style, length=length)
|
| 96 |
return final
|
| 97 |
|
|
|
|
| 98 |
with gr.Blocks(title="Agente de Estudos IA") as demo:
|
| 99 |
gr.Markdown("# Agente de Estudos IA \nCarregue seu **livro** e **slides** e estude com o bot.")
|
| 100 |
|
|
@@ -107,7 +159,6 @@ with gr.Blocks(title="Agente de Estudos IA") as demo:
|
|
| 107 |
upload_btn.click(upload_files, inputs=files_in, outputs=[uploaded_list, status])
|
| 108 |
index_btn.click(build_index, outputs=status)
|
| 109 |
|
| 110 |
-
|
| 111 |
with gr.Tab("Conversar"):
|
| 112 |
chatbot = gr.Chatbot(height=420)
|
| 113 |
msg = gr.Textbox(placeholder="Pergunte algo")
|
|
@@ -125,72 +176,8 @@ with gr.Blocks(title="Agente de Estudos IA") as demo:
|
|
| 125 |
length_dd = gr.Dropdown(choices=["curto", "médio", "longo"], value="médio", label="Tamanho")
|
| 126 |
run_btn = gr.Button("Gerar resumo", variant="primary")
|
| 127 |
out_md = gr.Markdown()
|
| 128 |
-
|
| 129 |
run_btn.click(summarize_run,
|
| 130 |
inputs=[file_dd, pages_tb, chapter_tb, query_tb, style_dd, length_dd],
|
| 131 |
outputs=out_md)
|
| 132 |
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
def _save_one(file_obj: Any) -> str:
|
| 137 |
-
"""
|
| 138 |
-
Salva um item vindo do componente gr.File, qualquer que seja o formato:
|
| 139 |
-
- str/Path (caminho no disco)
|
| 140 |
-
- objeto com .path
|
| 141 |
-
- objeto com .save()
|
| 142 |
-
- objeto com .name / .orig_name e .read()
|
| 143 |
-
Retorna o nome salvo.
|
| 144 |
-
"""
|
| 145 |
-
dest_dir = settings.RAW_DIR
|
| 146 |
-
dest_dir.mkdir(parents=True, exist_ok=True)
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
if isinstance(file_obj, (str, Path)):
|
| 150 |
-
src = Path(file_obj)
|
| 151 |
-
dest = dest_dir / src.name
|
| 152 |
-
shutil.copy(src, dest)
|
| 153 |
-
return dest.name
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
path = getattr(file_obj, "path", None)
|
| 157 |
-
if path:
|
| 158 |
-
src = Path(path)
|
| 159 |
-
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or src.name
|
| 160 |
-
dest = dest_dir / name
|
| 161 |
-
shutil.copy(src, dest)
|
| 162 |
-
return dest.name
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
saver = getattr(file_obj, "save", None)
|
| 166 |
-
if callable(saver):
|
| 167 |
-
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or "arquivo_subido"
|
| 168 |
-
dest = dest_dir / name
|
| 169 |
-
saver(str(dest))
|
| 170 |
-
return dest.name
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
reader = getattr(file_obj, "read", None)
|
| 174 |
-
if callable(reader):
|
| 175 |
-
data = reader()
|
| 176 |
-
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or "arquivo_subido"
|
| 177 |
-
dest = dest_dir / name
|
| 178 |
-
with open(dest, "wb") as f:
|
| 179 |
-
f.write(data)
|
| 180 |
-
return dest.name
|
| 181 |
-
|
| 182 |
-
raise ValueError("Formato de arquivo não reconhecido pelo upload.")
|
| 183 |
-
|
| 184 |
-
def upload_files(files):
|
| 185 |
-
try:
|
| 186 |
-
saved = []
|
| 187 |
-
for item in (files or []):
|
| 188 |
-
saved.append(_save_one(item))
|
| 189 |
-
msg = "Upload concluído: " + (", ".join(saved) if saved else "nenhum arquivo")
|
| 190 |
-
return gr.update(choices=list_uploaded_files(), value=None), msg + ". Agora clique em **Indexar**."
|
| 191 |
-
except Exception as e:
|
| 192 |
-
|
| 193 |
-
return gr.update(choices=list_uploaded_files(), value=None), f"Falha no upload: {type(e).__name__}: {e}"
|
| 194 |
-
|
| 195 |
-
|
| 196 |
demo.queue().launch()
|
|
|
|
| 9 |
from backend.summarizer import extractive_sents, map_reduce
|
| 10 |
|
| 11 |
|
| 12 |
+
for p in [settings.RAW_DIR, settings.INDEX_DIR, settings.MODEL_DIR]:
|
| 13 |
+
p.mkdir(parents=True, exist_ok=True)
|
|
|
|
| 14 |
|
| 15 |
STATE_INDEXED = False
|
| 16 |
|
| 17 |
+
|
| 18 |
def list_uploaded_files():
|
| 19 |
files = []
|
| 20 |
for f in settings.RAW_DIR.glob("**/*"):
|
|
|
|
| 22 |
files.append(str(f.relative_to(settings.RAW_DIR)))
|
| 23 |
return sorted(files)
|
| 24 |
|
| 25 |
+
def _save_one(file_obj: Any) -> str:
|
| 26 |
+
"""
|
| 27 |
+
Salva um item vindo do componente gr.File, qualquer que seja o formato:
|
| 28 |
+
- str/Path (caminho no disco)
|
| 29 |
+
- objeto com .path
|
| 30 |
+
- objeto com .save()
|
| 31 |
+
- objeto com .name / .orig_name e .read()
|
| 32 |
+
Retorna o nome salvo.
|
| 33 |
+
"""
|
| 34 |
+
dest_dir = settings.RAW_DIR
|
| 35 |
+
dest_dir.mkdir(parents=True, exist_ok=True)
|
| 36 |
+
|
| 37 |
+
if isinstance(file_obj, (str, Path)):
|
| 38 |
+
src = Path(file_obj)
|
| 39 |
+
dest = dest_dir / src.name
|
| 40 |
+
shutil.copy(src, dest)
|
| 41 |
+
return dest.name
|
| 42 |
+
|
| 43 |
+
path = getattr(file_obj, "path", None)
|
| 44 |
+
if path:
|
| 45 |
+
src = Path(path)
|
| 46 |
+
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or src.name
|
| 47 |
+
dest = dest_dir / name
|
| 48 |
+
shutil.copy(src, dest)
|
| 49 |
+
return dest.name
|
| 50 |
+
|
| 51 |
+
saver = getattr(file_obj, "save", None)
|
| 52 |
+
if callable(saver):
|
| 53 |
+
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or "arquivo_subido"
|
| 54 |
+
dest = dest_dir / name
|
| 55 |
+
saver(str(dest))
|
| 56 |
+
return dest.name
|
| 57 |
+
|
| 58 |
+
reader = getattr(file_obj, "read", None)
|
| 59 |
+
if callable(reader):
|
| 60 |
+
data = reader()
|
| 61 |
+
name = getattr(file_obj, "orig_name", None) or getattr(file_obj, "name", None) or "arquivo_subido"
|
| 62 |
+
dest = dest_dir / name
|
| 63 |
+
with open(dest, "wb") as f:
|
| 64 |
+
f.write(data)
|
| 65 |
+
return dest.name
|
| 66 |
+
|
| 67 |
+
raise ValueError("Formato de arquivo não reconhecido pelo upload.")
|
| 68 |
+
|
| 69 |
+
def upload_files(files):
|
| 70 |
+
try:
|
| 71 |
+
saved = []
|
| 72 |
+
for item in (files or []):
|
| 73 |
+
saved.append(_save_one(item))
|
| 74 |
+
msg = "Upload concluído: " + (", ".join(saved) if saved else "nenhum arquivo")
|
| 75 |
+
return gr.update(choices=list_uploaded_files(), value=None), msg + ". Agora clique em **Indexar**."
|
| 76 |
+
except Exception as e:
|
| 77 |
+
return gr.update(choices=list_uploaded_files(), value=None), f"Falha no upload: {type(e).__name__}: {e}"
|
| 78 |
+
|
| 79 |
|
| 80 |
def build_index():
|
| 81 |
"""Ingestão (parse) + construção e carga do índice. Mostra erro detalhado no UI."""
|
|
|
|
| 91 |
STATE_INDEXED = False
|
| 92 |
return f"Falha ao indexar/carregar: **{type(e).__name__}** — {e}"
|
| 93 |
|
|
|
|
| 94 |
def chat_answer(history, message):
|
| 95 |
"""Carrega o índice se preciso e responde; se falhar, mostra o motivo em vez de 'ERRO!'."""
|
| 96 |
if not history:
|
|
|
|
| 103 |
return history + [("system", f"Índice não está pronto: **{type(e).__name__}** — {e}\n"
|
| 104 |
"Vá na aba **Upload & Indexar** e clique em **Indexar**.")], ""
|
| 105 |
|
|
|
|
| 106 |
try:
|
| 107 |
hits = retriever.search(message, top_k=settings.TOP_K)
|
| 108 |
if not hits:
|
|
|
|
| 115 |
except Exception as e:
|
| 116 |
return history + [("system", f"Falha na busca/resposta: **{type(e).__name__}** — {e}")], ""
|
| 117 |
|
|
|
|
| 118 |
def summarize_run(filename, pages, chapter, query, style, length):
|
| 119 |
if not STATE_INDEXED:
|
| 120 |
try:
|
|
|
|
| 146 |
final = map_reduce(hits, focus=query or "resumo", style=style, length=length)
|
| 147 |
return final
|
| 148 |
|
| 149 |
+
|
| 150 |
with gr.Blocks(title="Agente de Estudos IA") as demo:
|
| 151 |
gr.Markdown("# Agente de Estudos IA \nCarregue seu **livro** e **slides** e estude com o bot.")
|
| 152 |
|
|
|
|
| 159 |
upload_btn.click(upload_files, inputs=files_in, outputs=[uploaded_list, status])
|
| 160 |
index_btn.click(build_index, outputs=status)
|
| 161 |
|
|
|
|
| 162 |
with gr.Tab("Conversar"):
|
| 163 |
chatbot = gr.Chatbot(height=420)
|
| 164 |
msg = gr.Textbox(placeholder="Pergunte algo")
|
|
|
|
| 176 |
length_dd = gr.Dropdown(choices=["curto", "médio", "longo"], value="médio", label="Tamanho")
|
| 177 |
run_btn = gr.Button("Gerar resumo", variant="primary")
|
| 178 |
out_md = gr.Markdown()
|
|
|
|
| 179 |
run_btn.click(summarize_run,
|
| 180 |
inputs=[file_dd, pages_tb, chapter_tb, query_tb, style_dd, length_dd],
|
| 181 |
outputs=out_md)
|
| 182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
demo.queue().launch()
|