Spaces:
Sleeping
Sleeping
Commit History
-
feat: per-user OpenAI key + model preferences persisted in DB
Fabio Antonini +1: Claude Sonnet 4.6- UserSettings table stores encrypted OpenAI key (Fernet) and last-selected models (rag, vlm, ocr, embed) per user - ContextVar propagates the user's decrypted key to all core modules without changing function signatures; global OPENAI_API_KEY env var as fallback - set_openai_context FastAPI dependency injected in rag, compliance, agent routers - GET/PUT /users/me/settings and PATCH /users/me/settings/models endpoints - DELETE /users/me/settings/openai-key to revoke personal key - Sidebar restores saved model selections on login and persists changes - Inline DB migration in init_db() adds new columns to existing user_settings table - docker-compose: OPENAI_API_KEY and SETTINGS_ENCRYPTION_KEY passed as env vars - Remove PUT /rag/openai-key (global key is env-only, never written to file) - Sidebar: uppercase removed from section headers; "Configurazione" now title-case Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>413c3b1 -
feat: add OpenAI API support (gpt-5.4 family) alongside Ollama
Fabio Antonini +1: Claude Sonnet 4.6- New core/providers.py: provider abstraction layer with model detection, OpenAI client factory, API key management and model catalogue - core/rag.py: provider-aware _embed()/_embed_batch()/stream_llm() wrappers; set_embed_model() with NPZ cache invalidation on provider switch - core/compliance.py, ocr.py, document_layout.py, agent.py: OpenAI branches for all LLM/VLM call sites; max_tokens → max_completion_tokens for gpt-5.4 - core/pipeline.py: Step 7 title shows active provider and model name - backend: new /rag/openai-key and /rag/embed-model endpoints; /rag/status returns OpenAI model lists when key is configured - frontend: Sidebar dropdowns use <optgroup> Ollama/OpenAI; OpenAI key UI; embedding model selector; i18n keys for en/it Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f1196cf
-
fix: stabilize ENFSI compliance tool streaming and PDF rendering
Fabio Antonini +1: Claude Sonnet 4.6- Extract compliance marker using string find/rfind instead of lazy regex to correctly handle nested JSON objects - Emit compliance report immediately from tools node without waiting for LLM final answer (avoids context saturation on long tool results) - Skip OCR on structured PDFs: extract_perizia_text tries pypdf-only first, falls back to EasyOCR only if total text < 200 chars - Fix delete_project_document lazy-load error: read storage_key/filename into local vars before db.delete() - Fix REQ-20 suggerimento capturing riepilogo: stop block regex at \n--- Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>50a86b4
-
fix: render NER table correctly in agent chat
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: extract markdown tables from tool results verbatim and append to final response, bypassing the LLM which collapses newlines; strip mangled pipe-rows from LLM answer when clean tables are available; add remarkGfm-compatible _extract_tables() helper - frontend/AgentProjectPage.tsx: enable remark-gfm plugin on ReactMarkdown so markdown tables are rendered as HTML tables (was missing, all tables rendered as plain text) - backend/routers/agent.py: improve project context note to prevent LLM from using bare filenames as paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>167611e -
fix: agent session isolation, audit rollback, persistent images, legacy endpoint
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: use UUID session subfolder for temp files; keep original filenames so the LLM knows which file is which; clean up in finally block - core/document_layout.py: drop LayoutDetection entirely, use PPStructure directly (PaddleOCR 3.x on Windows — LayoutDetection broken due to oneDNN) - backend/audit.py: rollback session after flush error to avoid PendingRollbackError on subsequent ORM calls (was causing 500 on doc delete) - backend/routers/agent.py: GET /agent/images/{filename} serves persistent agent images from data/uploads/agent/images/; GET /agent/temp-image/ returns 410 Gone with cache header to stop browser retrying old URLs - frontend/src/pages/AgentProjectPage.tsx: refresh document list immediately after POST /agent/chat (before streaming ends) so uploaded files appear in the panel without waiting for the full agent response Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3559e28
-
feat: inject project context into agent system prompt
Fabio Antonini +1: Claude Sonnet 4.6When a chat belongs to a project, build a context block listing the project's documents and previous chat titles, and append it to the LLM system prompt so the agent is aware of the project state without the user having to re-explain it each time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>6cecbb6 -
feat: agent projects with persistent chats and reusable documents
Fabio Antonini +1: Claude Sonnet 4.6- Add AgentChat and AgentMessage models (cascade delete from Project) - Extend /agent/chat to persist messages and save uploads to MinIO - New endpoints: agent projects, chats, documents CRUD - New AgentProjectPage: 3-column layout (chat list / chat / documents) - Sidebar: Agent Projects section with inline project creation - Documents panel: click to reuse without re-uploading - i18n: new keys for agent project UI (EN + IT) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f9c4034 -
feat: show extracted signature image inline in agent chat
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/agent.py: add GET /agent/temp-image/{filename} endpoint to serve files from %TEMP%/gl/ with JWT auth and path traversal protection - core/agent.py: rileva_firma tool saves crop to gl/firma_estratta.png and returns markdown image syntax; agent_stream extracts image markdown from tool results and injects into final answer; fix: import re inside stream - frontend/src/pages/AgentPage.tsx: add AuthImage component (JWT-authenticated blob URL); wire as ReactMarkdown img renderer; fix SSE line buffer to avoid losing chunks split across read() calls (restores tool log dropdown) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>390c120 -
feat: delete single analysis artefact in Perizie page
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/analysis.py: add DELETE /analysis/{id} endpoint with project access check and audit log - frontend/src/lib/api.ts: add analysisApi.deleteOne() - frontend/src/pages/ProjectDetailPage.tsx: add Trash2 button to each AnalysisCard (red on hover), handleDeleteAnalysis() removes from local state without full reload - i18n: add delete_analysis key (it/en) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a617713 -
feat: separate LLM and VLM model slots + fix agent OCR model routing
Fabio Antonini +1: Claude Sonnet 4.6- core/rag.py: separate _rag_model (text, default qwen3:4b) from _vlm_model (vision, default qwen3-vl:8b); add get/set_vlm_model + _persist_vlm_model_to_env; load both from .env at startup via _load_model_from_env() - core/agent.py: AGENT_MODEL = qwen3:4b (was qwen3-vl:8b); trascrivi_documento now uses htr_transcribe() respecting OCR model selector instead of hardcoded VLM - core/document_layout.py: _get_active_model() reads _vlm_model instead of _rag_model - core/ocr.py: _vlm_transcribe() reads _vlm_model instead of _rag_model - backend/routers/rag.py: add GET/PUT /rag/vlm-model endpoints - frontend: add VLM model selector in sidebar (Sidebar.tsx, api.ts, i18n) - backend/config.py + .env.example: add vlm_model field, update defaults - README.md: document three model slots (LLM/VLM/OCR) with GPU impact table Result: text-only tasks (transcribe+NER+dating with OCR=easyocr) use only qwen3:4b; qwen3-vl:8b is loaded only for image analysis (table/figure/vlm-ocr). Co-Authored-By: Cl…3c9c028 -
feat: Agente Documentale LangChain + OCR selector + stop + SQLite WAL
Fabio Antonini +1: Claude Sonnet 4.6- core/agent.py: LangChain agent con 10 tool forensi (OCR, NER, firma, grafologia, scrittore, datazione, layout, RAG), streaming SSE, stop via threading.Event, short-path workaround per path truncation LLM - core/document_layout.py: wrapper PaddleOCR lazy-loaded con call_vision_model streaming (timeout=(10,300), stream=True) - backend/routers/agent.py: endpoint POST /agent/chat (SSE), GET /agent/status, GET /agent/prompts; cancellazione via GeneratorExit → stop_event - frontend/src/pages/AgentPage.tsx: chat page stile ChatGPT con upload file, streaming SSE, badge azioni tool collassabili, Stop button (AbortController) - core/ocr.py: selettore modello OCR (easyocr/vlm/paddleocr/trocr), persistenza .env, _vlm_transcribe streaming, EasyOCR senza preprocessing - backend/routers/rag.py: GET/PUT /rag/ocr-model endpoints - frontend/src/components/layout/Sidebar.tsx: dropdown OCR model in sidebar - backend/database.py: SQLite WAL mode + busy_timeout=10000 via event listener - core/…e1f6f2b
-
feat: compliance PDF export + UI structured report
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/compliance.py: POST /compliance/pdf generates a 4-page PDF with stat boxes, proportional score bar, judgment banner, summary table and per-REQ detail cards with colored left bar and suggestion boxes; adaptive colophon positioning - frontend: CompliancePage fully rewritten — streaming shows rendered markdown, on completion parses verdicts and renders structured cards with stat panels, filter tabs (Tutti/Conformi/Parziali/Mancanti), per-REQ cards with color-coded borders and lightbulb suggestions, and a Download PDF button - api.ts: complianceApi.pdf() method - i18n: compliance.download_pdf key (it/en) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>723e81b -
feat: ENFSI compliance checker + sidebar model selector
Fabio Antonini +1: Claude Sonnet 4.6- core/compliance.py: new module with 20-item ENFSI BPM checklist, streaming Ollama analysis (system/prompt separation, num_ctx=16384, /no_think for qwen3), and Python-side deterministic summary parsing (verdicts extracted via regex → counts/grid always correct) - backend/routers/compliance.py: POST /compliance/check (PDF upload → SSE) and GET /compliance/status - backend/routers/rag.py: GET /rag/model and PUT /rag/model endpoints for runtime model selection - frontend: CompliancePage, Sidebar configurazione section with model selector dropdown and refresh button, i18n keys (it/en) - docker-compose.yml: add GPU passthrough to ollama service - requirements.txt: add CUDA 12.1 extra-index-url for PyTorch GPU wheels Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>c23bac8
-
fix: RAG chat fully functional in FastAPI backend
Fabio Antonini +1: Claude Sonnet 4.6- backend/main.py: launch rag_load_docs in background thread at startup so _rag_ready becomes True - backend/routers/rag.py: fix history schema (list[dict] with role/content), JSON-encode SSE payloads to handle embedded newlines, combine partial+sources_footer in one event (mirrors Gradio wrapper) - core/rag.py: increase retrieval top-k from 2 to 5 user chunks for better recall on sparse mentions; switch embed model to nomic-embed-text; add keep_alive to Ollama calls - frontend/src/pages/RagPage.tsx: read auth token via getState() (not stale React state), send history as [{role,content}], JSON.parse SSE data, fix assistantText = (not +=) since stream yields full accumulated text Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>1355325 -
fix: rag_doc_list() call signature and frontend Docker npm install
Fabio Antonini +1: Claude Sonnet 4.6- backend/routers/rag.py: rag_doc_list() takes no args and returns [[name, count]] rows, not dicts — fixed call and response mapping - frontend/Dockerfile: switch npm ci → npm install to handle platform-specific deps missing from Windows-generated lockfile Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>905b464 -
docs: add password reset and DB reset procedures to backend README
Fabio Antonini +1: Claude Sonnet 4.6Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>7dafd7d -
feat: password reset via admin (no SMTP required)
Fabio Antonini +1: Claude Sonnet 4.6Backend: - auth/jwt.py: add TokenType.reset + create_reset_token() (24h) - routers/auth.py: POST /auth/reset-password/generate (admin only) and POST /auth/reset-password/confirm (public) - models/audit.py: add password_reset_generate / password_reset_confirm actions Frontend: - ResetPasswordPage.tsx: new public page at /reset-password?token=xxx - AdminPage.tsx: KeyRound button per user → modal with copyable reset link - App.tsx: add /reset-password route - api.ts: authApi.generateResetToken() + authApi.confirmReset() - i18n/it.json + en.json: all new strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>f4fd404 -
docs: update all YOLOv8 references to Conditional DETR
Fabio Antonini +1: Claude Sonnet 4.6README, ROADMAP, articles, backend docstring, docs/DEMO_CHECKLIST, docs/NOTEBOOKS_GUIDE, linkedin articles, slides, generate_presentation.py — all textual references to YOLOv8/ultralytics/yolov8s-signature-detector replaced with Conditional DETR/transformers/conditional-detr-50-signature-detector. ROADMAP tasks marked [x] complete with strikethrough. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>e3ef569
-
feat: immutable audit log for forensic chain-of-custody
Fabio Antonini +1: Claude Sonnet 4.6Backend: - AuditLog model (append-only, no UPDATE/DELETE) with action enum, user snapshot, resource type/id, detail, ip_address - log_event() helper — silently swallows errors so logging never breaks the main request flow - Integrated in all key endpoints: login, project create/delete, document upload/delete, all analysis types, PDF download, clear analyses - GET /audit/ (admin only) with filters by action and user email, pagination (page/page_size) Frontend: - AdminPage with two tabs: Users and Activity Log - Audit tab: filter by action and email, paginated table with color-coded action badges, timestamp, user, resource, detail, IP - auditApi in api.ts - i18n keys for audit log (IT + EN) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b59af0d -
feat: PDF report with images, formatted tables and clean layout
Fabio Antonini +1: Claude Sonnet 4.6- Embed pipeline images (sig detection, graphology) via _download_sync - Render markdown tables as proper PDF cells with borders and striped rows - Fix title/date layout with explicit vertical spacing - Skip duplicate H2 title already rendered as page header - Strip orphaned asterisks left by LLM bold patterns (**label**: style) - Add PDF download button on pipeline analysis cards - Add fpdf2 to requirements-backend.txt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4e50c56 -
feat: optional reference signature for full forensic pipeline
Fabio Antonini +1: Claude Sonnet 4.6- Backend: PipelineRequest with optional reference_document_id - Backend: load and pass ref_sig image to run_pipeline_steps when provided - Frontend: picker modal before running pipeline (skip or select reference doc) - i18n: add pipeline_ref_* keys in it/en Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0bd285f -
feat: pipeline images, markdown rendering and running spinner
Fabio Antonini +1: Claude Sonnet 4.6- Pipeline: save sig_detect and grapho images, embed as authenticated inline images in report - Add GET /analysis/{id}/image/{slot} endpoint for pipeline image slots - Frontend: AuthImage component fetches images with JWT token - ReactMarkdown with remark-gfm renders tables and inline images - Loader2 spinner on active analysis button Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>86766f3 -
feat: show annotated images in analysis cards with markdown rendering
Fabio Antonini +1: Claude Sonnet 4.6- Save annotated image to storage for signature-detection and graphology - Add GET /analysis/{id}/image endpoint (JWT-authenticated) - Frontend: fetch image via axios (with auth token) and render as blob URL - Render result_text as markdown with remark-gfm for table support - Add upload_fileobj import to analysis router Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>5b1ac36 -
feat: add Clear analyses button to project detail page
Fabio Antonini +1: Claude Sonnet 4.6- Backend: DELETE /analysis/project/{project_id} endpoint - Frontend: Cancella analisi button with confirm dialog (visible only when analyses exist) - i18n: add clear_analyses and clear_analyses_confirm keys in it/en Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>01c12ca
-
fix: local dev storage fallback and analysis URL normalization
Fabio Antonini +1: Claude Sonnet 4.6- minio_client: fall back to data/uploads/ filesystem when MinIO unreachable - api.ts: normalize analysis type underscores to hyphens to match backend routes - .gitignore: exempt frontend/src/lib/ from Python lib/ exclusion rule Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>c8c71aa -
fix: resolve local dev issues found during first test run
Fabio Antonini +1: Claude Sonnet 4.6- Replace passlib with bcrypt directly (passlib 1.7 incompatible with bcrypt 4.x) - Fix SQLite engine config: disable pool_pre_ping, add check_same_thread=False - Import all models in __init__.py so SQLAlchemy resolves relationships - Change dev proxy port to 8001 (port 8000 occupied by Wacom service on dev machine) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3d87cee -
docs: add backend/README.md with local testing guide
Fabio Antonini +1: Claude Sonnet 4.6Documents two testing modes (SQLite no-Docker vs full Docker Compose), Swagger UI workflow, first-admin bootstrap script, env vars reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>9331e8e -
feat: add FastAPI backend (Phase 1 — feature/backend)
Fabio Antonini +1: Claude Sonnet 4.6New backend/ package with 35 REST endpoints: - config.py: pydantic-settings (DB, MinIO, JWT, Ollama, CORS) - database.py: async SQLAlchemy engine + session dependency - models/user.py: User, Organization, Role (admin/examiner/viewer) - models/project.py: Project, Document, Analysis ORM models - auth/password.py: bcrypt hash/verify - auth/jwt.py: access token (30min) + refresh token (7d) - auth/dependencies.py: get_current_user(), require_role() - routers/auth.py: POST /auth/login|refresh|logout - routers/users.py: CRUD /users/ + /users/me - routers/projects.py: CRUD /projects/ + document upload/delete - routers/analysis.py: POST /analysis/{htr,sig,ner,writer,grapho,pipeline,dating} - routers/rag.py: streaming SSE /rag/chat + doc management - storage/minio_client.py: async MinIO wrapper (anyio thread offload) - main.py: FastAPI app with CORS, lifespan, health check - Dockerfile: backend container image - .env.example: environment variable template Also: - requirements-backend.txt: fast…76f414d