Spaces:
Sleeping
Sleeping
File size: 6,802 Bytes
d6f883a ca66299 ff3675d 5982b60 fe95c90 babf40b ff3675d 5982b60 dc36aa4 5982b60 be3d9ab d6f883a babf40b f91300a 1e41091 3a32be7 5982b60 1e41091 035b936 1e41091 f91300a c43a5f2 dc36aa4 5982b60 ff3675d babf40b f91300a d6f883a babf40b 13c0c68 13266e9 babf40b ff3675d babf40b ff3675d 5982b60 d62954c d6f883a 5982b60 ff3675d 0152a3a babf40b 13c0c68 0152a3a babf40b 0152a3a 13c0c68 0152a3a babf40b ff3675d d75a1e8 13266e9 5982b60 babf40b 0152a3a 5982b60 13266e9 72af3b2 babf40b 0152a3a babf40b 72af3b2 ff3675d babf40b ff3675d babf40b ff3675d 0152a3a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 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() |