Skip to content

Commit

Permalink
Task 03 - week 3
Browse files Browse the repository at this point in the history
  • Loading branch information
jarmatys committed Dec 22, 2024
1 parent 5ab21cd commit 2d03818
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;

namespace ASSISTENTE.Playground.Models.CentralModel;
namespace ASSISTENTE.Playground.Models.CentralModels;

public class TaskRequestModel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;

namespace ASSISTENTE.Playground.Models.CentralModel;
namespace ASSISTENTE.Playground.Models.CentralModels;

public class TaskResponse
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;

namespace ASSISTENTE.Playground.Models.DatabaseModels;

public class DatabaseRequestModel
{
[JsonPropertyName("task")]
public required string Task { get; set; }

[JsonPropertyName("apikey")]
public required string ApiKey { get; set; }

[JsonPropertyName("query")]
public required string Query { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;

namespace ASSISTENTE.Playground.Models.DatabaseModels;

public class DatabaseResponse
{
[JsonPropertyName("reply")]
public required object Reply { get; set; }

[JsonPropertyName("error")]
public required string Error { get; set; }
}
2 changes: 1 addition & 1 deletion API/ASSISTENTE.Playground/Playground.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task LearnAsync()

public async Task RunAsync()
{
var result = await weekThree.Task_02()
var result = await weekThree.Task_03()
.Tap(result => logger.LogInformation(result))
.TapError(error => logger.LogError(error));
}
Expand Down
31 changes: 30 additions & 1 deletion API/ASSISTENTE.Playground/Tasks/TaskBase.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.Text;
using System.Text.Json;
using ASSISTENTE.Playground.Models;
using ASSISTENTE.Playground.Models.CentralModel;
using ASSISTENTE.Playground.Models.CentralModels;
using ASSISTENTE.Playground.Models.DatabaseModels;
using CSharpFunctionalExtensions;

namespace ASSISTENTE.Playground.Tasks;
Expand Down Expand Up @@ -75,4 +76,32 @@ protected async Task<Result<string>> ReportResult(string taskName, object? taskR
? Result.Failure<string>(deserializedContent?.Message)
: Result.Success(deserializedContent!.Message);
}

protected async Task<Result<string>> DatabaseQuery(string taskName, string query)
{
const string databaseUrl = "https://centrala.ag3nts.org/apidb";

var request = new DatabaseRequestModel
{
Task = taskName,
ApiKey = ApiKey,
Query = query
};

var response = await httpClient.PostAsync(
databaseUrl,
new StringContent(
JsonSerializer.Serialize(request),
Encoding.UTF8, "application/json"
)
);

var responseContent = await response.Content.ReadAsStringAsync();

var deserializedContent = JsonSerializer.Deserialize<DatabaseResponse>(responseContent);

return !response.IsSuccessStatusCode
? Result.Failure<string>(deserializedContent?.Error)
: Result.Success(deserializedContent!.Reply.ToString())!;
}
}
120 changes: 115 additions & 5 deletions API/ASSISTENTE.Playground/Tasks/WeekThree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ public async Task<Result<string>> Task_02()
const string question = "W raporcie, z którego dnia znajduje się wzmianka o kradzieży prototypu broni?";

var weaponsFiles = Directory.GetFiles(dataFilesWeapons);

await qdrantService.DropCollectionAsync("aidevs");
await qdrantService.CreateCollectionAsync("aidevs");

foreach (var weaponFile in weaponsFiles)
{
var fileName = Path.GetFileName(weaponFile);
var fileContent = await File.ReadAllTextAsync(weaponFile);

await EmbeddingText.Create(fileContent)
.Bind(async embeddingText => await embeddingClient.GetAsync(embeddingText))
.Bind(embedding =>
Expand All @@ -166,12 +166,16 @@ await EmbeddingText.Create(fileContent)
{
{ "fileName", fileName }
};

return DocumentDto.Create("aidevs", embedding.Embeddings, metadata);
})
.Bind(async document => await qdrantService.UpsertAsync(document));
}

// TODO: Create library 'ASSISTENTE.Infrastructure.Search' which will be combined qdrant, embedding and other services like typsense, database simple query
// Implement hybrid search service which will be able to search in multiple sources and score them together
// Combined score formula: (1 / vector rank) + (1 / full text rank)

var date = await EmbeddingText.Create(question)
.Bind(async embeddingText => await embeddingClient.GetAsync(embeddingText))
.Bind(embedding => VectorDto.Create("aidevs", embedding.Embeddings, elements: 1))
Expand All @@ -181,8 +185,114 @@ await EmbeddingText.Create(fileContent)
.Map(Path.GetFileNameWithoutExtension)
.Map(dateString => DateTime.Parse(dateString!.Replace("_", "-")).ToString("yyyy-MM-dd"))
.GetValueOrDefault(x => x);


return await ReportResult("wektory", date);
}

public async Task<Result<string>> Task_03()
{
// Dostępne tabele: users, datacenters & connections

const string question = "które aktywne datacenter (DC_ID) są zarządzane przez pracowników, " +
"którzy są na urlopie (is_active=0)";

const string acceptableFormat = "1, 2, 3";

var context = new StringBuilder();

while (true)
{
var masterContext = context.ToString() == string.Empty
? "BRAK INFORMACJI - NAPISZ ZAPYTANIE SQL"
: context.ToString();

if (context.ToString() != string.Empty)
{
var verifyPrompt = $"""
Twoim zadaniem jest zweryfikować czy w pozyskanych informacjach znajduje się
odpowiedź na zadane pytanie.
<PYTANIE>
{question}
</PYTANIE>
<KONTEKST>
{masterContext}
</KONTEKST>
Jeżeli nie znajdziesz odpowiedzi, zwróć "BRAK".
Jeżeli znajdziesz odpowiedź, zwróć znalezioną informację.
Zwrócona informacja powinna zawierać tylko i wyłącznie odpowiedź na pytanie
w formacie: {acceptableFormat}
""";

var hasAnswer = await Prompt.Create(verifyPrompt)
.Bind(async prompt => await llmClient.GenerateAnswer(prompt))
.GetValueOrDefault(x => x.Text, "");

if (hasAnswer != "BRAK")
{
var inActiveDataCenterIds = hasAnswer.Split(", ")
.Select(int.Parse)
.ToList();

return await ReportResult("database", inActiveDataCenterIds);
}
}

var masterPrompt = $"""
Twoim zadaniem jest otrzymać odpowiedź na pytanie:
<PYTANIE>
{question}
</PYTANIE>
<ZASADY>
1. Do dyspozycji masz dostęp do bazy danych. Musisz napisać zapytania SQL, które naprowadzą Cię na odpowiedź.
2. Nie podawaj żadnych dodatkowych informacji, zwróć sam SQL lub odpowiedź na pytanie.
3. Nie zwracaj żadnych tagów markdown, ani znaków specjalnych, same zapytanie SQL.
</ZASADY>
<PRZYDATNE ZAPYTANIA>
`show tables` = zwraca listę tabel
`show create table <NAZWA_TABELI>` = pokazuje, jak zbudowana jest konkretna tabela
</PRZYDATNE ZAPYTANIA>
Jeżeli nie jesteś pewny jak odpowiedzieć na zadane pytanie przygotuj kolejne zapytanie SQL aby uzyskać więcej szczegółów.
Jeżeli masz wszystko czego potrzebujesz zwróć rezultat w postaci liczb po przecinku np. 1, 2, 3.
<PRZYKŁAD ODPOWIEDZI>
select * from datacenters
</PRZYKŁAD ODPOWIEDZI>
<POZYSKANE INFORMACJE>
{masterContext}
</POZYSKANE INFORMACJE>
""";

var sqlQuery = await Prompt.Create(masterPrompt)
.Bind(async prompt => await llmClient.GenerateAnswer(prompt))
.GetValueOrDefault(x => x.Text, "");

var isSqlQuery = sqlQuery.Contains("select", StringComparison.OrdinalIgnoreCase) ||
sqlQuery.Contains("show", StringComparison.OrdinalIgnoreCase);

if (isSqlQuery)
{
var queryResult = await DatabaseQuery("database", sqlQuery);

context.Append($"<WYKONANE ZAPYTANIE>{sqlQuery}</WYKONANE ZAPYTANIE>\n" +
$"<REZULTAT>{queryResult}</REZULTAT>\n\n");

continue;
}

break;
}

return Result.Success("Zadanie zakończone");
}
}

0 comments on commit 2d03818

Please sign in to comment.