From 00c04657bd23649ffb8961967433221c5fd5e73e Mon Sep 17 00:00:00 2001
From: nor0x
Date: Mon, 9 Sep 2024 17:47:56 +0200
Subject: [PATCH] =?UTF-8?q?multi-party=20=F0=9F=A5=B3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
WahlGPT.Common/Settings.cs | 8 ++
WahlGPT.Web/Pages/Home.razor | 156 ++++++++++++++++++--------------
WahlGPT.Web/wwwroot/css/app.css | 118 +++++++++++++-----------
3 files changed, 161 insertions(+), 121 deletions(-)
diff --git a/WahlGPT.Common/Settings.cs b/WahlGPT.Common/Settings.cs
index cf77fe7..b3b4dde 100644
--- a/WahlGPT.Common/Settings.cs
+++ b/WahlGPT.Common/Settings.cs
@@ -41,11 +41,19 @@ public static IKernelMemory BuildKernelMemory()
TextModel = TextModel,
};
+ var azureBlobStorageConfig = new AzureBlobsConfig
+ {
+ Auth = AzureBlobsConfig.AuthTypes.ConnectionString,
+ ConnectionString = BlobConnectionString,
+ Container = "wahlgpt"
+ };
+
#pragma warning disable KMEXP00 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var kernelMemory = new KernelMemoryBuilder()
.WithContentDecoder(new TextDecoder())
.WithOpenAITextEmbeddingGeneration(embeddingConfig)
.WithOpenAITextGeneration(generationConfig)
+ .WithAzureBlobsDocumentStorage(azureBlobStorageConfig)
.WithSearchClientConfig(new SearchClientConfig
{
Temperature = 0.7,
diff --git a/WahlGPT.Web/Pages/Home.razor b/WahlGPT.Web/Pages/Home.razor
index c47915a..f8868b0 100644
--- a/WahlGPT.Web/Pages/Home.razor
+++ b/WahlGPT.Web/Pages/Home.razor
@@ -47,44 +47,49 @@
+
+ @if (_waitingForAnswer)
+ {
+
+
+
+
+
+ }
-
-
-
- @_question
+ @if (_answers is not null)
+ {
+
+ @foreach (var answer in _answers.OrderByDescending(a => _parties.First(p => p.party == a.party).order))
+ {
+
+
- @_parties.FirstOrDefault(p => p.selected).party
+ @answer.party
-
-
- @if (_waitingForAnswer)
- {
-
-
-
-
+
@((MarkupString)ChatManager.ConvertToHtml(answer.answer))
+
- }
- else
- {
-
@((MarkupString)ChatManager.ConvertToHtml(_answer))
- }
-
-
-
- @if (_citations is not null)
- {
-
- @foreach (var citation in _citations)
+
+
+ @if (answer.source?.Partitions is not null)
{
+
+
+ @foreach (var citation in answer.source.Partitions.Take(3))
+ {
- }
+ }
-
- }
- @if (!string.IsNullOrEmpty(_downloadUrl))
- {
-
- Wahlprogamm herunterladen:
- @_downloadUrl.Split("/").Last();
-
-
+
+ }
+ else
+ {
+
Keine Quellen gefunden.
+ }
+
+
+
+ @if (!string.IsNullOrEmpty(_downloadUrl))
+ {
+
+ Wahlprogamm herunterladen:
+ @GetDownloadUrl(answer.party).Split("/").LastOrDefault()
+
+
+ }
+
}
-
+ }
- Diese Antwort wurde mittels Retrieval-Augmented Generation (RAG) und einem Large-Language Model (LLM) erstellt. Diese Technologien kombinieren die Fähigkeit, relevante Daten aus verschiedenen Quellen abzurufen, und mittels Textgenerierung Zusammenfassungen zu erstellen. Bitte berücksichtige, dass die Möglichkeit von Fehlern oder Ungenauigkeiten besteht.
+ Diese Antworten wurde mittels Retrieval-Augmented Generation (RAG) und einem Large-Language Model (LLM) erstellt. Diese Technologien kombinieren die Fähigkeit, relevante Daten aus verschiedenen Quellen abzurufen, und mittels Textgenerierung Zusammenfassungen zu erstellen. Bitte berücksichtige, dass die Möglichkeit von Fehlern oder Ungenauigkeiten besteht.
@@ -135,7 +149,7 @@
Antwortgenerierung (Augmented Generation): Das LLM verarbeitet die gefundenen Informationen und formuliert eine verständliche Antwort.
Durch diese Kombination von Suche und Textgenerierung kann das LLM präzise und nützliche Antworten auf deine Fragen zu Wahlprogrammen geben. Du erhältst schnell klare Informationen, ohne die gesamten Texte selbst durchsuchen zu müssen.
- der Code von WahlGPT ist open-source und auf GitHub verfügbar.
+ der Code von WahlGPT ist open-source und auf GitHub verfügbar. Dort können auch alle Wahlprogramme die als Import verwendet heruntergeladen werden.
@@ -147,7 +161,8 @@
- jede Antwort die von WahlGPT generiert wird, kostet Geld.
Wenn du das Projekt unterstützen möchtest, kannst du das hier tun.
+
+ jede Antwort die von WahlGPT generiert wird, kostet Geld.
Wenn du das Projekt unterstützen möchtest, kannst du das hier tun.
- Unterstützen!
@@ -193,10 +208,8 @@
@code
{
private string? _question;
- private List? _citations;
- private string? _sourceName;
private string? _downloadUrl;
- private string? _answer;
+ private List<(string answer, string party, Citation source)> _answers;
private bool _waitingForAnswer;
private bool _buttonDisabled = true;
List<(string party, string documentId, bool selected, int order)> _parties = new List<(string party, string documentId, bool
@@ -225,35 +238,35 @@
{
try
{
- _answer = null;
- _citations = null;
+ _answers = new();
if (string.IsNullOrEmpty(_question))
{
return;
}
- //check if a party is selected
if (!_parties.Any(p => p.selected))
{
return;
}
-
- //enable button only if upper conditions are met
-
- //smooth scroll to #one
_waitingForAnswer = true;
await _js.InvokeVoidAsync("scrollToElement", "#one");
- var answer = await _chat.AskQuestion(_question, _parties.Where(p => p.selected).Select(p => p.documentId).ToList());
- _waitingForAnswer = false;
- if (answer is null)
- {
- _answer = "Sorry, ich konnte keine Antwort finden.";
- }
- else
+ foreach (var p in _parties.Where(p => p.selected))
{
- _answer = answer.Result;
- _sourceName = answer.RelevantSources.FirstOrDefault()?.SourceName ?? "";
- _citations = answer.RelevantSources.FirstOrDefault().Partitions?.Take(3).ToList() ?? null;
+ var answer = await _chat.AskQuestion(_question, new List { p.documentId });
+ if (answer is null)
+ {
+ _answers.Add(("Sorry, ich konnte keine Antwort finden.", p.party, null));
+ }
+ else
+ {
+ _answers.Add((answer.Result, p.party, answer.RelevantSources.FirstOrDefault()));
+ }
+
+ _answers = _answers.OrderBy(a => _parties.First(p => p.party == a.party).order).ToList();
+ StateHasChanged();
+
}
+
+ _waitingForAnswer = false;
StateHasChanged();
}
catch (Exception e)
@@ -264,15 +277,18 @@
void SelectParty(string party)
{
- _parties = _parties.Select(p => (p.party, p.documentId, false, p.order)).ToList();
- var index = _parties.FindIndex(p => p.party == party);
- _parties[index] = (party, _parties[index].documentId, true, _parties[index].order);
- _downloadUrl = $"https://raw.githubusercontent.com/nor0x/wahlgpt/main/WahlGPT.Importer/Documents/{_parties[index].documentId}.pdf";
-
+ _parties = _parties.Select(p => p.party == party ? (p.party, p.documentId, !p.selected, p.order) : p).ToList();
+
_buttonDisabled = string.IsNullOrEmpty(_question) || !_parties.Any(p => p.selected);
StateHasChanged();
}
+ string GetDownloadUrl(string party)
+ {
+ var documentId = _parties.First(p => p.party == party).documentId;
+ return $"https://raw.githubusercontent.com/nor0x/wahlgpt/main/WahlGPT.Importer/Documents/{documentId}.pdf";
+ }
+
private async void CopyEmailToClipboard()
{
await _js.InvokeVoidAsync("copyToClipboard", "hi@johnnys.page");
diff --git a/WahlGPT.Web/wwwroot/css/app.css b/WahlGPT.Web/wwwroot/css/app.css
index 79363ae..7cef490 100644
--- a/WahlGPT.Web/wwwroot/css/app.css
+++ b/WahlGPT.Web/wwwroot/css/app.css
@@ -33,21 +33,29 @@
font-size: 1rem
}
-.party.selected {
- border: 1px solid #ffffff;
- padding: 2px;
- color: #666666;
- background-color: #ffffff;
+ .party.selected {
+ border: 1px solid #ffffff;
+ padding: 2px;
+ color: #666666;
+ background-color: #ffffff;
+ }
+
+.answer-loader {
+ margin-bottom: 2rem;
}
+ .answer-loader span {
+ width: 15px;
+ height: 15px;
+ background-color: #666666;
+ border-radius: 50%;
+ display: inline-block;
+ }
-.answer-loader span {
- width: 15px;
- height: 15px;
- background-color: #666666;
- border-radius: 50%;
- display: inline-block;
+.answer-spacer {
+ margin-bottom: 2rem;
+ border-bottom-color: rgb(70 70 70 / 50%) !important;
}
span:nth-child(1) {
@@ -95,7 +103,7 @@ span:nth-child(3) {
transition: all 0.35s;
}
-.tab input:checked~.tab__content {
+.tab input:checked ~ .tab__content {
max-height: 10rem;
}
@@ -118,7 +126,7 @@ span:nth-child(3) {
.tab__label {
justify-content: space-between;
- padding: 1rem;
+ padding: 0.5rem;
margin-bottom: 0;
background: #666666;
color: white;
@@ -126,16 +134,16 @@ span:nth-child(3) {
border-radius: 0.5rem;
}
-.tab__label::after {
- content: "\276F";
- width: 1em;
- height: 1em;
- text-align: center;
- transform: rotate(90deg);
- transition: all 0.35s;
-}
+ .tab__label::after {
+ content: "\276F";
+ width: 1em;
+ height: 1em;
+ text-align: center;
+ transform: rotate(90deg);
+ transition: all 0.35s;
+ }
-.tab input:checked+.tab__label::after {
+.tab input:checked + .tab__label::after {
transform: rotate(270deg);
}
@@ -155,7 +163,7 @@ span:nth-child(3) {
}
/* Arrow animation */
-.tab input:not(:checked)+.tab__label:hover::after {
+.tab input:not(:checked) + .tab__label:hover::after {
animation: bounce .5s infinite;
}
@@ -180,6 +188,7 @@ span:nth-child(3) {
text-align: center;
max-width: 50%;
margin: 0 auto;
+ margin-top: 2rem;
line-height: normal;
}
@@ -200,21 +209,27 @@ span:nth-child(3) {
color: #ffffff;
padding: 0 0.5rem;
border-radius: 0.5rem;
- font-size: 0.8rem;
+ font-size: 1.3rem;
font-weight: 700;
animation: none !important;
+ display: inline-block;
}
.header-img {
- height:200px;
+ height: 200px;
}
.content-link-a {
- border-bottom-color: rgb(70 70 70 / 50%);
+ border-bottom-color: rgb(70 70 70 / 50%) !important;
}
.answer-row {
flex-wrap: wrap-reverse;
+ row-gap: 4rem;
+}
+
+.answer-row .col-6 .col-12-medium {
+ border-bottom: 1px solid #666666;
}
.support-text {
@@ -238,12 +253,12 @@ span:nth-child(3) {
z-index: 1000;
}
-#blazor-error-ui .dismiss {
- cursor: pointer;
- position: absolute;
- right: 0.75rem;
- top: 0.5rem;
-}
+ #blazor-error-ui .dismiss {
+ cursor: pointer;
+ position: absolute;
+ right: 0.75rem;
+ top: 0.5rem;
+ }
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
@@ -251,9 +266,9 @@ span:nth-child(3) {
color: white;
}
-.blazor-error-boundary::after {
- content: "An error has occurred."
-}
+ .blazor-error-boundary::after {
+ content: "An error has occurred."
+ }
.loading-progress {
position: relative;
@@ -263,19 +278,19 @@ span:nth-child(3) {
margin: 20vh auto 1rem auto;
}
-.loading-progress circle {
- fill: none;
- stroke: #e0e0e0;
- stroke-width: 0.6rem;
- transform-origin: 50% 50%;
- transform: rotate(-90deg);
-}
+ .loading-progress circle {
+ fill: none;
+ stroke: #e0e0e0;
+ stroke-width: 0.6rem;
+ transform-origin: 50% 50%;
+ transform: rotate(-90deg);
+ }
-.loading-progress circle:last-child {
- stroke: #b01010;
- stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
- transition: stroke-dasharray 0.05s ease-in-out;
-}
+ .loading-progress circle:last-child {
+ stroke: #b01010;
+ stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
+ transition: stroke-dasharray 0.05s ease-in-out;
+ }
.loading-progress-text {
position: absolute;
@@ -284,9 +299,9 @@ span:nth-child(3) {
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}
-.loading-progress-text:after {
- content: var(--blazor-load-percentage-text, "Loading");
-}
+ .loading-progress-text:after {
+ content: var(--blazor-load-percentage-text, "Loading");
+ }
code {
color: #c02d76;
@@ -317,7 +332,8 @@ code {
.answer-info-text {
max-width: 80%;
}
+
.support-text {
max-width: 100%;
}
-}
\ No newline at end of file
+}