Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Vereist voor authenticatie (zijbalk met gesprekshistorie)
# Genereer met: python -c "import secrets; print(secrets.token_hex(32))"
CHAINLIT_AUTH_SECRET=

# Model in litellm-formaat: provider/model-naam
# Zie https://docs.litellm.ai/docs/providers voor alle opties
MODEL=anthropic/claude-sonnet-4-6
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ chainlit.md
socket:*

.uv_cache/

# Lokale data — niet in repo
data/sessions.db
data/sessions.db-shm
data/sessions.db-wal
78 changes: 77 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,34 @@

import chainlit as cl

import persistence
from agent import run
from data_layer import SQLiteDataLayer, init_db
from report import generate_report

init_db()


@cl.data_layer
def get_data_layer() -> SQLiteDataLayer:
return SQLiteDataLayer()


@cl.header_auth_callback
def auth_callback(headers) -> cl.User:
return cl.User(identifier="local", metadata={"role": "user"})


@cl.on_chat_resume
async def on_resume(thread: cl.types.ThreadDict) -> None:
metadata = thread.get("metadata") or {}
messages = metadata.get("messages", [])
cl.user_session.set("messages", messages)
cl.user_session.set("figures", [])
cl.user_session.set("turns", [])
cl.user_session.set("session_id", thread["id"])
cl.user_session.set("turn_figures", [])

WELKOM = """Welkom! Ik kan je helpen met vragen over open Nederlandse onderwijsdata.

Ik heb toegang tot:
Expand Down Expand Up @@ -38,6 +63,7 @@ async def set_starters():

@cl.on_chat_start
async def on_start():
cl.user_session.set("session_id", cl.context.session.id)
cl.user_session.set("messages", [])
cl.user_session.set("figures", [])
cl.user_session.set("turns", [])
Expand All @@ -47,11 +73,54 @@ async def on_start():
await cl.Message(content="⚠️ Geen API key gevonden. Stel een omgevingsvariabele in (bijv. `ANTHROPIC_API_KEY`) en herstart de app.").send()
return

await cl.Message(content=WELKOM).send()
await cl.Message(content=WELKOM + "\n\nTip: typ `/history` om eerdere gesprekken te hervatten.").send()


@cl.action_callback("resume_session")
async def on_resume_session(action: cl.Action):
session_id = action.payload["session_id"]
messages = persistence.load(session_id)
if not messages:
await cl.Message(content="Gesprek niet meer beschikbaar.").send()
return

cl.user_session.set("messages", messages)
cl.user_session.set("session_id", session_id)

user_turns = [(m["content"], messages[i + 1]["content"] if i + 1 < len(messages) else "")
for i, m in enumerate(messages) if m["role"] == "user"]

summary_lines = "\n".join(
f"- **V:** {q[:80]}{'…' if len(q) > 80 else ''}\n **A:** {a[:120]}{'…' if len(a) > 120 else ''}"
for q, a in user_turns[-5:]
)
await cl.Message(
content=f"Gesprek herladen ({len(user_turns)} vragen). Laatste uitwisselingen:\n\n{summary_lines}\n\nGa gerust verder."
).send()


async def _show_history() -> None:
sessions = persistence.recent()
if not sessions:
await cl.Message(content="Nog geen opgeslagen gesprekken.").send()
return
actions = [
cl.Action(
name="resume_session",
label=f"↩ {s['title'][:55]}{'…' if len(s['title']) > 55 else ''}",
payload={"session_id": s["id"]},
)
for s in sessions
]
await cl.Message(content="**Vorige gesprekken:**", actions=actions).send()


@cl.on_message
async def on_message(message: cl.Message):
if message.content.strip().lower() in ("/history", "/gesprekken"):
await _show_history()
return

messages: list = cl.user_session.get("messages")
messages.append({"role": "user", "content": message.content})

Expand All @@ -71,6 +140,13 @@ async def on_message(message: cl.Message):
turns.append({"question": message.content, "answer": response_text, "figures": turn_figures})
cl.user_session.set("turns", turns)

# Persist LLM messages in thread metadata so on_chat_resume can restore them
thread_id = cl.context.session.thread_id
from chainlit.data import get_data_layer
dl = get_data_layer()
if dl:
await dl.update_thread(thread_id, metadata={"messages": messages})


@cl.action_callback("download_rapport")
async def on_download_rapport(action: cl.Action):
Expand Down
Loading