Logius-Chatbot / app.py
Jesselg's picture
Update app.py
babf40b verified
Raw
History Blame Contribute Delete
6.8 kB
import os
import gradio as gr
import requests
# API Keys (via Hugging Face Secrets)
WEAVIATE_API_KEY = os.getenv("WEAVIATE_APIKEY")
VLAM_API_KEY = os.getenv("VLAM_APIKEY")
# Weaviate Config
WEAVIATE_URL = "https://k6hr14w1r8gwkdctkxha.c0.europe-west3.gcp.weaviate.cloud/v1/graphql"
HEADERS = {"Authorization": f"Bearer {WEAVIATE_API_KEY}", "Content-Type": "application/json"}
def fetch_relevant_docs(user_query):
# Probeer eerst met nearText (semantische zoekopdracht)
neartext_query = {
"query": f"""
{{
Get {{
DigiDDocument(
nearText: {{ concepts: ["{user_query}"] }},
limit: 3
) {{
title
content
}}
}}
}}
"""
}
response = requests.post(WEAVIATE_URL, json=neartext_query, headers=HEADERS)
if response.status_code == 200:
data = response.json()
documents = data.get("data", {}).get("Get", {}).get("DigiDDocument", [])
if documents:
return "\n\n".join([f"{doc['content']}" for doc in documents])
# Als nearText niets vindt, probeer met BM25 (keyword-zoekopdracht)
bm25_query = {
"query": f"""
{{
Get {{
DigiDDocument(
bm25: {{ query: "{user_query}" }},
limit: 3
) {{
title
content
}}
}}
}}
"""
}
response = requests.post(WEAVIATE_URL, json=bm25_query, headers=HEADERS)
if response.status_code == 200:
data = response.json()
documents = data.get("data", {}).get("Get", {}).get("DigiDDocument", [])
if documents:
return "\n\n".join([f"{doc['content']}" for doc in documents])
# Als beide queries niets vinden
return None
def generate_answer(vraag, history=[]):
# Voeg de laatste 2 berichten uit de gespreksgeschiedenis toe aan de context
history_text = ""
if history:
history_text = "\n".join(
[f"Gebruiker: {user_msg}\nAssistent: {bot_msg}"
for user_msg, bot_msg in history[-2:]] # Laatste 2 berichten
)
context = fetch_relevant_docs(vraag)
if not context:
return "Ik kan geen relevante documentatie vinden over EVA of DigiD-aansluiting. Misschien kan ik u helpen met een gerelateerd onderwerp? Bijvoorbeeld: 'Hoe werkt het aansluiten van DigiD via EVA?'"
messages = [
{"role": "system", "content": f"""
### Rol en Doel
Je bent **De Aansluitassistent voor EVA en DigiD**, een **deskundige en behulpzame** assistent voor organisaties die DigiD aansluiten via EVA.
### Antwoordstijl voor Checklists en Stappenplannen
- Als de gebruiker vraagt om een **checklist, stappenplan of eisenlijst**:
1. **Bevestig kort** dat de checklist beschikbaar is.
2. **Noem de 2-3 belangrijkste punten** (als voorproefje).
3. **Verwijs naar de volledige checklist** met een link (indien beschikbaar) of bied aan om deze te delen.
4. **Sluit af met een vervolgvraag** over een specifiek onderdeel.
**Voorbeeldantwoord voor een checklistvraag:**
*"Ja, er is een checklist voor [onderwerp]. De belangrijkste punten zijn:
- [Punt 1]
- [Punt 2]
- [Punt 3]
**Volledige checklist:** [Link naar checklist] of [Toolkit DigiD](https://www.digid.nl/toolkit).
**Vervolgvraag:** Wilt u hulp bij een specifiek criterium, zoals [onderdeel]?"*
### Gesprekscontext (gebruik deze om je antwoord te vormen):
{history_text}
### Instructies:
- **Alleen antwoorden op basis van de onderstaande context EN de gesprekscontext.**
- **Verwijs naar eerdere antwoorden** als de gebruiker daarnaar verwijst.
- **Stel vervolgvragen die natuurlijk voortvloeien uit het gesprek en de context.**
### Antwoordstijl
- **Zakelijk, maar vriendelijk, betrokken en enthousiasmerend. Eenvoudig taalgebruik.**
- Gebruik "u" en "uw".
- Toon begrip voor de situatie van de gebruiker (bijv. *"Dat is een belangrijke stap, ik help u graag verder."*).
- **Structuur:**
1. Beantwoord de **hoofdvraag** met **maximaal 3 kernpunten** (bulletpoints of alinea's).
2. **Sluit af met 1 of 2 vervolgvragen** die **direct aansluiten op het antwoord en de context**.
### Gedragsregels
1. **Als de vraag buiten de scope valt:**
*"Ik help graag met technische en procedurele vragen over EVA en DigiD. Voor [onderwerp] kunt u terecht bij [bron]. Laat me weten als u hulp nodig heeft met iets anders binnen EVA/DigiD!"*
2. **Als er geen context is:**
*"Ik kan helaas geen relevante informatie vinden over [onderwerp] in de EVA/DigiD-documentatie. Misschien kan ik u helpen met een gerelateerd onderwerp? Bijvoorbeeld: [noem een relevant onderwerp uit de context].*
3. **Als de context onduidelijk is:**
*"Kunt u uw vraag wat specifieker maken? Dan kan ik u beter helpen. Bijvoorbeeld: [geef een voorbeeldvraag die aansluit op de context]."*
### Voorbeelden van Goede Vervolgvragen
- Als de gebruiker vraagt over **Metadata**:
*"Heeft u al een PKIOverheid Certificaat? Dan kan ik u helpen met de volgende stappen."*
- Als de gebruiker vraagt over **foutmeldingen**:
*"Kunt u de specifieke foutmelding delen? Dan kan ik u gerichter helpen."*
### Context (gebruik ALLEEN deze informatie + de gesprekscontext):
{context}
"""},
{"role": "user", "content": vraag}
]
response = requests.post(
"https://api.demo.vlam.ai/v2.1/projects/poc/openai-compatible/v1/chat/completions",
headers={"Authorization": f"Bearer {VLAM_API_KEY}"},
json={
"model": "ubiops-deployment/logius-pc-mistralmedium-flexibel//chat-model",
"messages": messages,
"max_tokens": 1000,
"temperature": 0.3
}
)
full_answer = response.json()["choices"][0]["message"]["content"]
# Alleen afkappen als het antwoord te lang is
words = full_answer.split()
if len(words) > 300:
truncated = ' '.join(words[:300])
if not any(punct in truncated[-10:] for punct in ["?", "!"]):
truncated += "\n\nLaat me weten als u hier meer over wilt weten of hulp nodig heeft met een gerelateerd onderwerp!"
return truncated
return full_answer
# Gradio Interface met gespreksgeschiedenis
demo = gr.ChatInterface(
generate_answer,
title="EVA/DigiD Aansluitassistent",
description="Stel vragen over het aansluiten van DigiD via EVA. De chat onthoudt de context binnen deze sessie."
)
demo.launch()