Files
flowdeck/docs/V69_Search_Ask_AI.md
bruno 1706ad1ee9
FlowDeck CI / lint (push) Successful in 1m48s
FlowDeck CI / test (push) Failing after 21m19s
FlowDeck CI / docker (push) Skipped
feat: v7.3.0 — cycle v6.8.0→v7.3.0 (Sites, Search, Automations, Calendar, SCIM, Wiki) + audit A9
- v6.8.0 Sites & Forms publics (migrations 24)
- v6.9.0 Recherche sémantique hybride + Ask AI (migration 25)
- v7.0.0 Automations v2 multi-étapes + Workers sandboxés (migration 26)
- v7.1.0 Calendar sync Google/CalDAV + Meeting Notes (migration 27)
- v7.2.0 Enterprise : SCIM 2.0, 2FA TOTP/passkeys, audit UI, agent approvals (migration 28)
- v7.3.0 Wiki/Teamspaces, verified pages, collab polish, charts, unfurl (migration 29)
- docs V68→V73, ROADMAP/CHANGELOG/WORKLOAD à jour, VERSION 7.3.0
- A9 : flowdeck.db, flowdeck_dev.db, test-commit.md, upload_test.txt et e2e/{node_modules,shots,test-results} désindexés + ignorés (.gitignore/.dockerignore)
2026-09-30 20:02:57 -04:00

4.0 KiB

V6.9.0 — Recherche sémantique + Ask AI

Statut : ✅ Livré en v6.9.0 (2026-09-28) — app/services/semantic_search.py, app/routers/search_ai.py, migration 25, 24 tests verts · Roadmap : ROADMAP.md § v6.9.0 Note d'implémentation : table générique semantic_embeddings(resource_type, resource_id, …) au lieu de page_embeddings(page_id, …) — couvre aussi les collections ; encodeur hashed-TF hash-256 (pas d'appel /embeddings externe) ; pièces jointes et onglets palette en follow-up. Référence Notion : Enterprise Search (Notion + Slack/Jira/Drive) + AI Q&A avec citations. Existant : FTS5 (services/search.py, GET /api/search, GET /api/v2/search), palette Ctrl+K, AgentEngine (ReAct 12 tours), PermissionManager, llm_config + LLMClient (9 providers).


1. Vision

question → top-k chunks autorisés → réponse avec [[fdpage:ID]] cliquables. Hybride lexical + vectoriel (RRF), jamais de fuite ACL (filtrage avant prompt).

Hors scope : index temps réel < 1s, connecteurs Slack/Jira (v7.x si besoin forge d'abord).

2. Indexation

2.1 Schéma (migration 25)

CREATE TABLE page_embeddings (
  page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,
  chunk_id INTEGER NOT NULL,             -- index du chunk (0..N)
  chunk_text TEXT NOT NULL,
  embedding BLOB NOT NULL,               -- float32 serialisé
  model TEXT NOT NULL DEFAULT 'local-tfidf',
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (page_id, chunk_id)
);
CREATE TABLE search_index_state (page_id INTEGER PRIMARY KEY, indexed_at TIMESTAMP);
ALTER TABLE pages ADD COLUMN search_excluded BOOLEAN NOT NULL DEFAULT 0;
  • Chunking : blocs → texte brut (~500 tokens, overlap 50), ignore embed/images (légende seule).
  • Providers : openai-compatible /embeddings via LLMClient si clé user/workspace, sinon TF-IDF local (zéro dépendance, FR+EN stopwords) — même interface embed(texts) -> vectors.
  • Job : scheduler 5 min, batch 50 (updated_at > indexed_at), DELETE embeddings si page trashée/exclue.

2.2 Contenus indexés

Pages blocks + markdown/file (résolution déjà export.py), pièces jointes texte (pdf via pypdf, docx via python-docx, txt/md — cap 1 MB/fichier), titres de lignes DB (sans valeurs privées si property_permissions restreint → chunk « titre seul »), issues Gitea/GitHub liées (titre + labels, pas de body privé sans grant).

3. Recherche hybride

GET /api/v2/search/hybrid?q=&workspace_id=&type=&limit=20 :

  1. FTS5 score (existants) ; 2. cosine top-50 ; 3. fusion RRF k=60 ; 4. filtre ACL (can_view_page/can_view_collection) ; 5. X-Total-Count. Filtres : verified:1, type:page|collection|file, after:YYYY-MM-DD. Palette Ctrl+K : onglets Pages / Fichiers / ✨ Réponses IA.

4. Ask AI

POST /api/v2/search/ask {question, workspace_id} → {answer_markdown, citations: [{page_id, title}]} :

  • top-k=8 chunks autorisés → prompt system: réponds en français, cite [[fdpage:ID]] → LLMClient.chat() (clé user, sinon mock déterministe « hors-ligne » comme ai_writing.py).
  • Budget : 4k tokens contexte, timeout 60s, cache (hash(question)+workspace) 10 min.
  • Citations résolues via wiki/titles (renommage propagé, « Deleted page » gérée).

5. UI / perfs / sécu

  • Badge ✨ + temps de réponse, feedback 👍/👎 (ask_feedback log, futur fine-tune).
  • ACL avant LLM (jamais de chunk interdit dans le prompt) ; search_excluded respecté partout ; audit api_audit_log.
  • Perfs : embeddings lazy (pas au save, job fond), cosine en numpy si dispo sinon pur Python (DB < 10k pages OK).

6. Tests (tests/test_v69_search_ask.py, ~20)

Index chunks, hybride RRF ordre, ACL (page restricted exclue), verified filtre, exclusion flag, pièces jointes cap, ask citations valides, ask sans clé → fallback, cache hit, rate-limit, X-Total-Count.

7. Rollout

  1. embed() + TF-IDF + job. 2. /hybrid + palette. 3. /ask + cache + feedback. 4. Docs /help + OpenAPI.