UI and chatbot updates
This commit is contained in:
@@ -11,6 +11,7 @@ ENV/
|
|||||||
# Korpus-PDFs (urheberrechtlich geschützt, nicht ins Repository)
|
# Korpus-PDFs (urheberrechtlich geschützt, nicht ins Repository)
|
||||||
data/
|
data/
|
||||||
data_test/
|
data_test/
|
||||||
|
data_primary/
|
||||||
|
|
||||||
# Vector store
|
# Vector store
|
||||||
vectorstore/
|
vectorstore/
|
||||||
|
|||||||
+7
-5
@@ -79,9 +79,9 @@ MAX_TOOL_ROUNDS = 3 # searches per message before the LLM must answer
|
|||||||
|
|
||||||
# System prompt for every chat turn (German, like the corpus and the questions).
|
# System prompt for every chat turn (German, like the corpus and the questions).
|
||||||
SYSTEM_PROMPT = f"""Du beantwortest Fragen zu Franz Kafka, seinen Werken, seinem Leben und der Forschung.
|
SYSTEM_PROMPT = f"""Du beantwortest Fragen zu Franz Kafka, seinen Werken, seinem Leben und der Forschung.
|
||||||
Du hast ein Werkzeug, {SEARCH_TOOL_NAME}, das eine Bibliothek aus Kafkas Texten und Forschungsliteratur durchsucht.
|
Du hast ein Tool, {SEARCH_TOOL_NAME}, das eine Bibliothek aus Kafkas Texten und Forschungsliteratur durchsucht.
|
||||||
- Für jede inhaltliche Frage zu Kafka, seinen Werken, Figuren, seiner Biografie, Sprache oder zur Forschung: Rufe zuerst das Werkzeug auf und stütze die Antwort auf die gefundenen Auszüge. Antworte nicht aus dem Gedächtnis.
|
- Für jede inhaltliche Frage zu Kafka, seinen Werken, Figuren, seiner Biografie, Sprache oder zur Forschung: Rufe zuerst das Werkzeug auf und stütze die Antwort auf die gefundenen Auszüge. Antworte nicht aus dem Gedächtnis.
|
||||||
- Bei Begrüßung, Dank, Smalltalk oder Fragen zum Gespräch selbst: Antworte direkt, ohne Werkzeug.
|
- Bei Begrüßung, Dank, Smalltalk oder Fragen zum Gespräch selbst: Antworte direkt, ohne Tool.
|
||||||
- Formuliere die Suchanfrage so, dass sie ohne den Gesprächsverlauf verständlich ist.
|
- Formuliere die Suchanfrage so, dass sie ohne den Gesprächsverlauf verständlich ist.
|
||||||
- Finden sich in den Auszügen keine Belege, sage das offen, statt zu raten.
|
- Finden sich in den Auszügen keine Belege, sage das offen, statt zu raten.
|
||||||
- Nenne bei Aussagen aus den Auszügen die Quelle (Autor, Seite)."""
|
- Nenne bei Aussagen aus den Auszügen die Quelle (Autor, Seite)."""
|
||||||
@@ -387,10 +387,12 @@ class LocalRAG:
|
|||||||
content = "".join(part.get("text", "") if isinstance(part, dict) else str(part) for part in content)
|
content = "".join(part.get("text", "") if isinstance(part, dict) else str(part) for part in content)
|
||||||
return (content or "").strip()
|
return (content or "").strip()
|
||||||
|
|
||||||
def query_with_history(self, question, chat_history=None, k=None, system_prompt=None):
|
def query_with_history(self, question, chat_history=None, k=None, system_prompt=None,
|
||||||
|
tool_description=None):
|
||||||
"""Answer a chat message. The LLM decides whether to search the corpus: the search is
|
"""Answer a chat message. The LLM decides whether to search the corpus: the search is
|
||||||
offered as a tool (SEARCH_TOOL_NAME), which the LLM calls with its own query, up to
|
offered as a tool (SEARCH_TOOL_NAME), which the LLM calls with its own query, up to
|
||||||
MAX_TOOL_ROUNDS times. system_prompt defaults to SYSTEM_PROMPT (see personas.py for others).
|
MAX_TOOL_ROUNDS times. system_prompt defaults to SYSTEM_PROMPT and tool_description to
|
||||||
|
SEARCH_TOOL_DESCRIPTION (see personas.py for others).
|
||||||
Returns dict with 'answer', 'retrieved' (chunks the LLM saw, with content, source, page,
|
Returns dict with 'answer', 'retrieved' (chunks the LLM saw, with content, source, page,
|
||||||
score) and 'searches' (the queries it used)."""
|
score) and 'searches' (the queries it used)."""
|
||||||
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage
|
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage
|
||||||
@@ -418,7 +420,7 @@ class LocalRAG:
|
|||||||
for i, (d, _) in enumerate(hits, start=1))
|
for i, (d, _) in enumerate(hits, start=1))
|
||||||
|
|
||||||
tool = StructuredTool.from_function(func=search_kafka_corpus, name=SEARCH_TOOL_NAME,
|
tool = StructuredTool.from_function(func=search_kafka_corpus, name=SEARCH_TOOL_NAME,
|
||||||
description=SEARCH_TOOL_DESCRIPTION)
|
description=tool_description or SEARCH_TOOL_DESCRIPTION)
|
||||||
llm_with_tools = self.llm.bind_tools([tool])
|
llm_with_tools = self.llm.bind_tools([tool])
|
||||||
|
|
||||||
messages = [SystemMessage(system_prompt or SYSTEM_PROMPT)]
|
messages = [SystemMessage(system_prompt or SYSTEM_PROMPT)]
|
||||||
|
|||||||
+46
-26
@@ -2,9 +2,12 @@
|
|||||||
Gesprächspartner des Chats: Oberflächentexte, Systemprompt und Vektorspeicher je Figur.
|
Gesprächspartner des Chats: Oberflächentexte, Systemprompt und Vektorspeicher je Figur.
|
||||||
|
|
||||||
Die Oberfläche lädt die Einträge über /api/personas (ohne Systemprompt und Index);
|
Die Oberfläche lädt die Einträge über /api/personas (ohne Systemprompt und Index);
|
||||||
server.py wählt pro Anfrage den Systemprompt und den Vektorspeicher der Figur.
|
server.py wählt pro Anfrage den Systemprompt, die Beschreibung des Such-Werkzeugs und
|
||||||
Alle Figuren nutzen vorerst denselben Vektorspeicher (VECTORSTORE_PATH); für eigene
|
den Vektorspeicher der Figur.
|
||||||
Korpora je Figur genügt es, "vectorstore" hier zu ändern.
|
|
||||||
|
Vektorspeicher:
|
||||||
|
VECTORSTORE_PATH ganzes Kafka-Korpus (Primärtext + Forschung), für die Forscherin
|
||||||
|
PRIMARY_VECTORSTORE_PATH nur der Primärtext "Die Verwandlung", für Zeitgenosse und Autor
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from local_rag import SEARCH_TOOL_NAME, SYSTEM_PROMPT
|
from local_rag import SEARCH_TOOL_NAME, SYSTEM_PROMPT
|
||||||
@@ -14,21 +17,35 @@ from local_rag import SEARCH_TOOL_NAME, SYSTEM_PROMPT
|
|||||||
# Gebaut mit: add_pdfs.py --data data --index ./vectorstore_pypdf_2000 --loader pypdf --no-headers
|
# Gebaut mit: add_pdfs.py --data data --index ./vectorstore_pypdf_2000 --loader pypdf --no-headers
|
||||||
VECTORSTORE_PATH = "./vectorstore_pypdf_2000"
|
VECTORSTORE_PATH = "./vectorstore_pypdf_2000"
|
||||||
|
|
||||||
# Gemeinsame Regeln für das Such-Werkzeug (wie im Systemprompt der Forscherin)
|
# Nur der Primärtext, gleiche Einstellungen. Gebaut mit (data_primary/ enthält nur einen
|
||||||
_TOOL_RULES = f"""Du hast ein Werkzeug, {SEARCH_TOOL_NAME}, das eine Bibliothek aus Kafkas Texten und Forschungsliteratur durchsucht.
|
# Verweis auf data/Kafka_Die_Verwandlung_.pdf):
|
||||||
- Für jede inhaltliche Frage zu Kafka, seinen Werken, Figuren, seiner Biografie, Sprache oder zur Forschung: Rufe zuerst das Werkzeug auf und stütze die Antwort auf die gefundenen Auszüge. Antworte nicht aus dem Gedächtnis.
|
# add_pdfs.py --data data_primary --index ./vectorstore_primary_pypdf_2000 --loader pypdf --no-headers
|
||||||
- Bei Begrüßung, Dank, Smalltalk oder Fragen zum Gespräch selbst: Antworte direkt, ohne Werkzeug.
|
PRIMARY_VECTORSTORE_PATH = "./vectorstore_primary_pypdf_2000"
|
||||||
|
|
||||||
|
# Beschreibung des Such-Werkzeugs für Figuren, die nur den Primärtext durchsuchen
|
||||||
|
PRIMARY_TOOL_DESCRIPTION = (
|
||||||
|
"Durchsucht den Text von Kafkas Erzählung \"Die Verwandlung\" und liefert die passendsten "
|
||||||
|
"Textauszüge mit Seite. Die Suchanfrage sollte eine eigenständige, präzise Frage oder "
|
||||||
|
"Stichwortfolge auf Deutsch sein."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Regeln für das Such-Werkzeug bei Figuren, die nur den Primärtext durchsuchen
|
||||||
|
_TOOL_RULES = f"""Du hast ein Tool, {SEARCH_TOOL_NAME}, das den Text von Kafkas Erzählung "Die Verwandlung" durchsucht.
|
||||||
|
- Für jede inhaltliche Frage zur Verwandlung, ihren Figuren, Szenen und Motiven: Rufe zuerst das Tool auf und stütze die Antwort auf die gefundenen Textstellen. Antworte nicht aus dem Gedächtnis.
|
||||||
|
- Bei Begrüßung, Dank, Smalltalk oder Fragen zum Gespräch selbst: Antworte direkt, ohne Tool.
|
||||||
|
- Bei Fragen zu dir selbst oder zu Personen aus deinem Umfeld, die keine fiktionalen Charaktere aus der Verwandlung sind: Antworte direkt, ohne Tool.
|
||||||
- Formuliere die Suchanfrage so, dass sie ohne den Gesprächsverlauf verständlich ist.
|
- Formuliere die Suchanfrage so, dass sie ohne den Gesprächsverlauf verständlich ist.
|
||||||
- Finden sich in den Auszügen keine Belege, sage das offen, statt zu raten.
|
- Finden sich in den Auszügen keine Belege, sage das offen, statt zu raten.
|
||||||
- Nenne bei Aussagen aus den Auszügen die Quelle (Autor, Seite) knapp in Klammern."""
|
- Nenne bei Aussagen aus dem Text die Seite knapp in Klammern."""
|
||||||
|
|
||||||
PERSONAS = {
|
PERSONAS = {
|
||||||
# Die Forscherin: unverändert gegenüber der ersten Fassung der Oberfläche
|
# Die Forscherin: unverändert gegenüber der ersten Fassung der Oberfläche
|
||||||
"researcher": {
|
"researcher": {
|
||||||
"label": "Forscherin",
|
"label": "Forscherin",
|
||||||
|
"topic": "Gespräch über die Verwandlung und Franz Kafka",
|
||||||
"name": "Dr. Klara Weiß",
|
"name": "Dr. Klara Weiß",
|
||||||
"role": "Literaturwissenschaftlerin, Kafka-Forschung",
|
"role": "Literaturwissenschaftlerin, Kafka-Forschung",
|
||||||
"place": "Arbeitszimmer · Prag, am Abend",
|
"place": "Arbeitszimmer · Gegenwart",
|
||||||
"status": "antwortet aus ihrer Kafka-Bibliothek",
|
"status": "antwortet aus ihrer Kafka-Bibliothek",
|
||||||
"image": "/visuals/kafka_researcher_office.jpg",
|
"image": "/visuals/kafka_researcher_office.jpg",
|
||||||
"image_alt": "Eine Literaturwissenschaftlerin arbeitet am Abend in ihrem Arbeitszimmer in Prag: "
|
"image_alt": "Eine Literaturwissenschaftlerin arbeitet am Abend in ihrem Arbeitszimmer in Prag: "
|
||||||
@@ -37,10 +54,10 @@ PERSONAS = {
|
|||||||
"image_position": "60% 40%",
|
"image_position": "60% 40%",
|
||||||
"avatar": "/visuals/researcher_avatar.jpg",
|
"avatar": "/visuals/researcher_avatar.jpg",
|
||||||
"greeting": (
|
"greeting": (
|
||||||
"Guten Abend. Kommen Sie herein, und schieben Sie die Bücher ruhig ein wenig zur Seite.\n\n"
|
"Guten Abend. Kommen Sie herein und setzen Sie sich.\n\n"
|
||||||
"Ich arbeite seit vielen Jahren zu Kafka, vor allem zur *Verwandlung*, zu seiner Sprache und zu "
|
"Ich arbeite seit vielen Jahren zu Kafka, vor allem zur *Verwandlung*, zu seiner Sprache und zu "
|
||||||
"dem, was die Forschung daraus gemacht hat. Fragen Sie mich, was Sie interessiert: Ich antworte "
|
"dem, was die Forschung daraus gemacht hat. Fragen Sie mich, was Sie interessiert: Ich antworte "
|
||||||
"aus den Texten, die hier auf meinem Schreibtisch liegen, und sage Ihnen, wo es steht."
|
"auf Basis der Texte, die hier auf meinem Schreibtisch liegen."
|
||||||
),
|
),
|
||||||
"suggestions": [
|
"suggestions": [
|
||||||
"Was bedeutet der Name Kafka auf Tschechisch?",
|
"Was bedeutet der Name Kafka auf Tschechisch?",
|
||||||
@@ -55,15 +72,16 @@ PERSONAS = {
|
|||||||
# Ein erfundener Zeitgenosse: Prager Feuilletonist um 1915
|
# Ein erfundener Zeitgenosse: Prager Feuilletonist um 1915
|
||||||
"contemporary": {
|
"contemporary": {
|
||||||
"label": "Zeitgenosse",
|
"label": "Zeitgenosse",
|
||||||
|
"topic": "Gespräch über die Verwandlung und Franz Kafka",
|
||||||
"name": "Viktor Hollmann",
|
"name": "Viktor Hollmann",
|
||||||
"role": "Feuilletonist, ein Zeitgenosse Kafkas",
|
"role": "Feuilletonist, ein Zeitgenosse Kafkas",
|
||||||
"place": "Redaktionsstube · Prag, um 1915",
|
"place": "Redaktionsstube · Prag, um 1920",
|
||||||
"status": "erzählt aus dem Prag seiner Zeit",
|
"status": "erzählt aus dem Prag seiner Zeit",
|
||||||
"image": "/visuals/kafka_contemporary_office.jpg",
|
"image": "/visuals/kafka_contemporary_office.jpg",
|
||||||
"image_alt": "Ein Herr im Tweedanzug mit runder Brille und Schnurrbart sitzt am Abend an seinem "
|
"image_alt": "Ein Herr mit Schnurrbart und dunklem Anzug sitzt am Abend rauchend an seinem "
|
||||||
"Schreibtisch in Prag und erzählt gestikulierend; hinter ihm durchs Fenster die "
|
"Schreibtisch voller Manuskripte in Prag, den Kopf in die Hand gestützt; durchs "
|
||||||
"Karlsbrücke und die Burg in der Dämmerung.",
|
"Fenster die Karlsbrücke und die Burg in der Dämmerung.",
|
||||||
"image_position": "62% 38%",
|
"image_position": "64% 36%",
|
||||||
"avatar": "/visuals/contemporary_avatar.jpg",
|
"avatar": "/visuals/contemporary_avatar.jpg",
|
||||||
"greeting": (
|
"greeting": (
|
||||||
"Guten Abend, treten Sie nur ein! Nehmen Sie Platz, der Kaffee ist noch warm.\n\n"
|
"Guten Abend, treten Sie nur ein! Nehmen Sie Platz, der Kaffee ist noch warm.\n\n"
|
||||||
@@ -77,17 +95,19 @@ PERSONAS = {
|
|||||||
"Was war Kafka für ein Mensch?",
|
"Was war Kafka für ein Mensch?",
|
||||||
"Welche Sprachen sprach man in Kafkas Familie?",
|
"Welche Sprachen sprach man in Kafkas Familie?",
|
||||||
],
|
],
|
||||||
"system_prompt": f"""Du bist Viktor Hollmann, ein erfundener Prager Feuilletonist um 1915 und Zeitgenosse Franz Kafkas.
|
"system_prompt": f"""Du bist Viktor Hollmann, ein erfundener Prager Feuilletonist um 1920 und Zeitgenosse Franz Kafkas.
|
||||||
Du sprichst in der Ich-Form, höflich und ein wenig altmodisch, im Ton des frühen 20. Jahrhunderts, und siezt dein Gegenüber.
|
Du sprichst in der Ich-Form, höflich und klar, im Ton des frühen 20. Jahrhunderts, und siezt dein Gegenüber.
|
||||||
Du kennst Prag, seine Kaffeehäuser und den Literaturbetrieb jener Jahre.
|
Du kennst Prag und den Literaturbetrieb zu dieser Zeit. Du bist ein Zeitgenosse Kafkas und kannst keine Aussagen zu Ereignissen und Personen nach dieser Zeit machen.
|
||||||
{_TOOL_RULES}
|
{_TOOL_RULES}
|
||||||
- Die Auszüge stammen teils aus viel späterer Forschung. Gib ihren Inhalt wieder, als hättest du davon gehört oder gelesen. Erfinde keine Begegnungen, Zitate oder Ereignisse, die nicht in den Auszügen stehen.""",
|
- Du kennst die Verwandlung als Leser ihrer Zeit. Erfinde keine Begegnungen, Zitate oder Ereignisse, die nicht im Text stehen.""",
|
||||||
"vectorstore": VECTORSTORE_PATH,
|
"tool_description": PRIMARY_TOOL_DESCRIPTION,
|
||||||
|
"vectorstore": PRIMARY_VECTORSTORE_PATH,
|
||||||
},
|
},
|
||||||
|
|
||||||
# Kafka selbst: eine Annäherung aus seinen Texten, keine echte Stimme
|
# Kafka selbst: eine Annäherung aus seinen Texten, keine echte Stimme
|
||||||
"kafka": {
|
"kafka": {
|
||||||
"label": "Autor",
|
"label": "Autor",
|
||||||
|
"topic": "Gespräch mit dem Autor",
|
||||||
"name": "Franz Kafka",
|
"name": "Franz Kafka",
|
||||||
"role": "Schriftsteller, Prag",
|
"role": "Schriftsteller, Prag",
|
||||||
"place": "Arbeitszimmer · Prag, in der Nacht",
|
"place": "Arbeitszimmer · Prag, in der Nacht",
|
||||||
@@ -111,16 +131,16 @@ Du kennst Prag, seine Kaffeehäuser und den Literaturbetrieb jener Jahre.
|
|||||||
"Warum wird Gregor zu einem Ungeziefer?",
|
"Warum wird Gregor zu einem Ungeziefer?",
|
||||||
],
|
],
|
||||||
"system_prompt": f"""Du sprichst als Franz Kafka (1883–1924), in einer behutsamen Annäherung aus seinen Texten.
|
"system_prompt": f"""Du sprichst als Franz Kafka (1883–1924), in einer behutsamen Annäherung aus seinen Texten.
|
||||||
Du sprichst in der Ich-Form, ruhig, genau, zweifelnd und selbstironisch, im Ton seiner Briefe und Tagebücher, und siezt dein Gegenüber.
|
Du sprichst in der Ich-Form, ruhig, genau, zweifelnd und selbstironisch, im Ton seiner Briefe und Tagebücher, und siezt dein Gegenüber. Fragen zu deiner Person, deinem Werk und deinem Umfeld beantwortest du im Präsenz, es sei denn du sprichst über Ereignisse, die in der Vergangenheit liegen.
|
||||||
{_TOOL_RULES}
|
{_TOOL_RULES}
|
||||||
- Stütze Aussagen über dein Leben und Werk auf die gefundenen Auszüge. Wo sie nichts hergeben, sag, dass du es nicht weißt oder nicht sagen kannst. Erfinde keine Zitate.
|
- Stütze Aussagen über dein Werk auf die gefundenen Textstellen. Wo sie nichts hergeben, sag, dass du es nicht weißt oder nicht sagen kannst. Erfinde keine Zitate.""",
|
||||||
- Die Auszüge stammen teils aus der Forschung über dich. Du darfst darauf mit Befremden oder Ironie reagieren ("man schreibt, ich hätte …").""",
|
"tool_description": PRIMARY_TOOL_DESCRIPTION,
|
||||||
"vectorstore": VECTORSTORE_PATH,
|
"vectorstore": PRIMARY_VECTORSTORE_PATH,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_PERSONA = "researcher"
|
DEFAULT_PERSONA = "researcher"
|
||||||
|
|
||||||
# Felder, die die Oberfläche bekommt (Systemprompt und Index bleiben auf dem Server)
|
# Felder, die die Oberfläche bekommt (Systemprompt und Index bleiben auf dem Server)
|
||||||
PUBLIC_FIELDS = ("label", "name", "role", "place", "status", "image", "image_alt", "image_position",
|
PUBLIC_FIELDS = ("label", "topic", "name", "role", "place", "status", "image", "image_alt", "image_position",
|
||||||
"avatar", "greeting", "suggestions")
|
"avatar", "greeting", "suggestions")
|
||||||
|
|||||||
@@ -12,3 +12,4 @@ fastapi
|
|||||||
uvicorn[standard]
|
uvicorn[standard]
|
||||||
rank_bm25
|
rank_bm25
|
||||||
snowballstemmer
|
snowballstemmer
|
||||||
|
python-dotenv
|
||||||
|
|||||||
@@ -8,11 +8,15 @@ from pathlib import Path
|
|||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
from fastapi.responses import HTMLResponse
|
from fastapi.responses import HTMLResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
from dotenv import load_dotenv
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from local_rag import LocalRAG
|
from local_rag import LocalRAG
|
||||||
from personas import DEFAULT_PERSONA, PERSONAS, PUBLIC_FIELDS
|
from personas import DEFAULT_PERSONA, PERSONAS, PUBLIC_FIELDS
|
||||||
|
|
||||||
|
# OPENAI_API_KEY may come from a local .env (git-ignored); an exported variable takes precedence.
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
OLLAMA_MODEL = "gemma4:12b"
|
OLLAMA_MODEL = "gemma4:12b"
|
||||||
OPENAI_MODEL = "gpt-6-luna"
|
OPENAI_MODEL = "gpt-6-luna"
|
||||||
# One RAG instance per (LLM provider, vector store), for on-the-fly provider switching.
|
# One RAG instance per (LLM provider, vector store), for on-the-fly provider switching.
|
||||||
@@ -101,6 +105,7 @@ def chat(request: ChatRequest):
|
|||||||
request.message.strip(),
|
request.message.strip(),
|
||||||
chat_history=chat_history,
|
chat_history=chat_history,
|
||||||
system_prompt=persona["system_prompt"],
|
system_prompt=persona["system_prompt"],
|
||||||
|
tool_description=persona.get("tool_description"),
|
||||||
)
|
)
|
||||||
answer = result["answer"]
|
answer = result["answer"]
|
||||||
retrieved = result.get("retrieved", [])
|
retrieved = result.get("retrieved", [])
|
||||||
|
|||||||
+2
-1
@@ -463,7 +463,7 @@
|
|||||||
<div class="avatar" aria-hidden="true"></div>
|
<div class="avatar" aria-hidden="true"></div>
|
||||||
<div class="who">
|
<div class="who">
|
||||||
<strong id="head-name"></strong>
|
<strong id="head-name"></strong>
|
||||||
<span>Gespräch über Franz Kafka</span>
|
<span id="head-topic"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectors">
|
<div class="selectors">
|
||||||
<label class="model">
|
<label class="model">
|
||||||
@@ -519,6 +519,7 @@
|
|||||||
document.getElementById('persona-role').textContent = PERSONA.role;
|
document.getElementById('persona-role').textContent = PERSONA.role;
|
||||||
document.getElementById('persona-status').textContent = PERSONA.status;
|
document.getElementById('persona-status').textContent = PERSONA.status;
|
||||||
document.getElementById('head-name').textContent = PERSONA.name;
|
document.getElementById('head-name').textContent = PERSONA.name;
|
||||||
|
document.getElementById('head-topic').textContent = PERSONA.topic;
|
||||||
inputEl.placeholder = 'Ihre Frage an ' + PERSONA.name + ' …';
|
inputEl.placeholder = 'Ihre Frage an ' + PERSONA.name + ' …';
|
||||||
|
|
||||||
portraitEl.classList.add('switching');
|
portraitEl.classList.add('switching');
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 292 KiB After Width: | Height: | Size: 299 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
Reference in New Issue
Block a user