chatdvg / app.py
Carmen Heger
minor prompt adjustments
39e0e62
from haystack import Pipeline
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.converters import PyPDFToDocument
from haystack.components.websearch import SerperDevWebSearch
from haystack.components.fetchers import LinkContentFetcher
from haystack.components.converters import HTMLToDocument
from haystack.components.preprocessors import DocumentCleaner
from haystack.components.preprocessors import DocumentSplitter
from haystack.components.rankers import TransformersSimilarityRanker
from haystack.components.writers import DocumentWriter
from haystack.components.embedders import SentenceTransformersTextEmbedder, SentenceTransformersDocumentEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
from haystack.components.generators import OpenAIGenerator
from haystack.components.builders.answer_builder import AnswerBuilder
from haystack.components.builders.prompt_builder import PromptBuilder
import os, sys
import streamlit as st
import streamlit.components.v1 as components
### Here the streamlit app starts
st.set_page_config(layout="wide")
st.title("The Real ChatDvG")
with st.container():
st.markdown("[Dirk von Gehlen](https://www.dirkvongehlen.de), kurz DvG, ist ein deutscher Journalist und Autor. Dies hier ist sein [KI-Spiegel](https://www.dirkvongehlen.de/ich/jetzt-wirds-persoenlich-das-bin-ja-ich-digitale-dezember-notizen/) ... oder vielleicht ist es doch der wahre DvG? Finde es heraus!")
web_search = SerperDevWebSearch(top_k=5,
allowed_domains=["https://www.dirkvongehlen.de"]
)
link_content = LinkContentFetcher()
html_converter = HTMLToDocument()
prompt = PromptBuilder(template="""Du bist Dirk von Gehlen, ein deutscher Journalist und Autor.
Du magst alles run um das Internet, Digitalisierung und Innovation.
Du machst gern Sport, gehst regelmäßig joggen und verfolgst im Fußball den VfL Bochum.
Du arbeitest als Journalist und Autor und schreibst intelligent, humorvoll und charmant.
Du schreibst Texte, erörterst zu Themen und beantwortest Fragen von deinen Lesern.
Dazu nutzt die gegebenen Paragraphen.
Die Paragraphen bestehen aus Teilen deiner Newsletter, Blog-Artikel und Büchern, die zur Frage deines Lesers passen.
Falls du die Frage beantworten kannst, antworte detailliert, aber maximal 400 Worte.
Schreibe in deinem Stil und deiner Sprache, wie in den gegebenen Paragraphen.
Sei dabei humorvoll und charmant aber auch anspruchsvoll und nicht lächerlich.
Stelle sicher, dass deine Antwort keinen Bias oder Vorurteile enthält.
Wenn du eine Information aus einem Paragraphen verwendest, nutze immer Quellenangaben in der Form [Nummer des Paragraphs].
Nutze beispielsweise [x] um anzugeben, dass du Informationen aus [x] genutzt hast.
Die Quellenangabe darf nur die Zahl erwähnen, die in eckigen Klammern [x] genannt ist.
Anfrage: {{ query }}
Hier die Paragraphen:
{% for document in documents %}
Paragraph[{{ loop.index }}]:
{{ document.content }}
{% endfor %}
Dirk von Gehlen: """)
prompt_node = OpenAIGenerator(model="gpt-4", #gpt-3.5-turbo", #"gpt-4",
generation_kwargs={"temperature":0.1, "frequency_penalty":0.8}
)
ranker = TransformersSimilarityRanker()
ranker.warm_up()
# Get user input
question = st.text_input("Deine Anfrage:")
answers = ""
# Send query to the chatbot
if st.button("Los!"):
p = Pipeline()
p.add_component("search", web_search)
p.add_component("fetcher", link_content)
p.add_component("converter", html_converter)
p.add_component(instance=DocumentCleaner(), name="cleaner")
p.add_component(instance=DocumentSplitter(split_by="sentence", split_length=15), name="splitter")
p.add_component(instance=ranker, name="ranker")
p.add_component("prompt_builder", prompt)
p.add_component("llm", prompt_node)
p.add_component("answer_builder", AnswerBuilder())
p.connect("search.links", "fetcher.urls")
p.connect("fetcher.streams", "converter.sources")
p.connect("converter.documents", "cleaner.documents")
p.connect("cleaner.documents", "splitter.documents")
p.connect("splitter.documents", "ranker.documents")
p.connect("ranker.documents", "prompt_builder.documents")
p.connect("prompt_builder.prompt", "llm.prompt")
p.connect("prompt_builder", "llm")
p.connect("llm.replies", "answer_builder.replies")
p.connect("prompt_builder.prompt", "llm.prompt")
p.connect("ranker.documents", "answer_builder.documents")
results = p.run(
{
"search": {"query": question},
"ranker": {"query": question, "top_k": 3},
"prompt_builder": {"query": question},
"answer_builder": {"query": question}
},
debug = True
)
answer = results["answer_builder"]['answers'][0].data
urls = [ (d.meta["link"], d.meta["title"]) for d in results["search"]["documents"] ]
print(urls, file=sys.stderr)
print(answer, file=sys.stderr)
with st.container():
for x in answer.splitlines():
st.markdown(x.strip())
for url, title in urls:
st.markdown(f"""[{title}]({url})\n""")