Add web search enrichment feature with source persistence and UI integration

Introduce optional web search enrichment flow for chat and regenerate requests. New /websearch endpoint calls enrich_prompt via SearXNG and returns enriched_prompt + citation sources.

DB: add sources_json column to chat_messages via ensure_sources_column migration helper.

Backend: persist sources_json for assistant replies (streaming and non-streaming); extend ChatRequest/RegenerateRequest to accept enriched_message and sources; history endpoint returns sources.

Frontend: add toggle for web search, settings for SearXNG URL + engines, and optional enrichment calls in sendMessage/regenerate. Render citation sources as rounded chips labeled with base domain under assistant replies.

Dependencies: add beautifulsoup4, httpx[http2], numpy for enrichment pipeline.
This commit is contained in:
2025-08-27 04:27:18 +02:00
parent e262e4b4fe
commit 728c7763e2
9 changed files with 1296 additions and 300 deletions

View File

@@ -1,6 +1,20 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, DeclarativeBase
from sqlalchemy import text
"""
Database utilities and configuration. This module defines the SQLAlchemy
engine, session factory and base class for models. It also contains a
lightweight migration helper used to evolve the schema over time. The
`ensure_sources_column` helper adds a new `sources_json` column to the
`chat_messages` table if it does not already exist. This is required
for persisting citation sources alongside assistant messages.
The migration uses SQLite's `ALTER TABLE` syntax and therefore should
only run once on startup. It is safe to call repeatedly: when the
column already exists, the function will simply noop.
"""
DATABASE_URL = "sqlite:///./backend/app.db"
@@ -12,3 +26,13 @@ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
class Base(DeclarativeBase):
pass
def ensure_sources_column(engine):
try:
with engine.connect() as conn:
cols = [row[1] for row in conn.execute(text("PRAGMA table_info(chat_messages)"))]
if "sources_json" not in cols:
conn.execute(text("ALTER TABLE chat_messages ADD COLUMN sources_json TEXT DEFAULT '[]'"))
except Exception as e:
print("[db] ensure_sources_column error:", e)