BotSharp/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs

119 lines
4.3 KiB
C#
Raw Normal View History

namespace BotSharp.Plugin.KnowledgeBase.Services;
2023-06-17 02:42:35 +00:00
2024-02-19 22:55:41 +00:00
public partial class KnowledgeService : IKnowledgeService
2023-06-17 02:42:35 +00:00
{
2023-06-26 23:08:24 +00:00
private readonly IServiceProvider _services;
private readonly KnowledgeBaseSettings _settings;
2023-06-18 18:15:00 +00:00
private readonly ITextChopper _textChopper;
2023-06-26 23:08:24 +00:00
public KnowledgeService(IServiceProvider services,
KnowledgeBaseSettings settings,
ITextChopper textChopper)
2023-06-17 02:42:35 +00:00
{
2023-06-26 23:08:24 +00:00
_services = services;
_settings = settings;
2023-06-18 18:15:00 +00:00
_textChopper = textChopper;
2023-06-17 02:42:35 +00:00
}
2023-12-30 03:54:41 +00:00
public async Task EmbedKnowledge(KnowledgeCreationModel knowledge)
{
var idStart = 0;
var lines = _textChopper.Chop(knowledge.Content, new ChunkOption
{
Size = 1024,
Conjunction = 32,
SplitByWord = true,
});
var db = GetVectorDb();
var textEmbedding = GetTextEmbedding();
await db.CreateCollection("shared", textEmbedding.Dimension);
foreach (var line in lines)
{
var vec = await textEmbedding.GetVectorAsync(line);
2024-07-02 14:52:16 +00:00
await db.Upsert("shared", idStart.ToString(), vec, line);
2023-12-30 03:54:41 +00:00
idStart++;
Console.WriteLine($"Saved vector {idStart}/{lines.Count}: {line}\n");
}
}
2023-06-17 02:42:35 +00:00
public async Task Feed(KnowledgeFeedModel knowledge)
{
var idStart = 0;
2023-06-18 18:15:00 +00:00
var lines = _textChopper.Chop(knowledge.Content, new ChunkOption
{
Size = 1024,
Conjunction = 32,
2023-06-29 23:14:57 +00:00
SplitByWord = true,
2023-06-18 18:15:00 +00:00
});
2023-06-26 23:08:24 +00:00
var db = GetVectorDb();
var textEmbedding = GetTextEmbedding();
await db.CreateCollection(knowledge.AgentId, textEmbedding.Dimension);
2023-06-17 02:42:35 +00:00
foreach (var line in lines)
{
var vec = await textEmbedding.GetVectorAsync(line);
2024-07-02 14:52:16 +00:00
await db.Upsert(knowledge.AgentId, idStart.ToString(), vec, line);
2023-06-17 02:42:35 +00:00
idStart++;
Console.WriteLine($"Saved vector {idStart}/{lines.Count}: {line}\n");
2023-06-17 02:42:35 +00:00
}
}
2023-06-29 23:14:57 +00:00
public async Task<string> GetKnowledges(KnowledgeRetrievalModel retrievalModel)
2023-06-17 02:42:35 +00:00
{
2023-06-26 23:08:24 +00:00
var textEmbedding = GetTextEmbedding();
var vector = await textEmbedding.GetVectorAsync(retrievalModel.Question);
2023-06-18 18:15:00 +00:00
2023-06-17 02:42:35 +00:00
// Vector search
2024-01-06 03:24:13 +00:00
var db = GetVectorDb();
2024-07-17 21:03:46 +00:00
var result = await db.Search("shared", vector, "answer", limit: 10);
2023-06-17 02:42:35 +00:00
2023-06-18 18:15:00 +00:00
// Restore
2023-08-09 21:49:55 +00:00
return string.Join("\n\n", result.Select((x, i) => $"### Paragraph {i + 1} ###\n{x.Trim()}"));
2023-06-29 23:14:57 +00:00
}
2023-08-09 21:49:55 +00:00
public async Task<List<RetrievedResult>> GetAnswer(KnowledgeRetrievalModel retrievalModel)
2023-06-29 23:14:57 +00:00
{
// Restore
var prompt = await GetKnowledges(retrievalModel);
2023-06-17 02:42:35 +00:00
var sb = new StringBuilder(prompt);
sb.AppendLine();
sb.AppendLine();
2023-08-09 21:49:55 +00:00
sb.AppendLine("------");
sb.AppendLine("Answer question based on the given information above. Keep your answers concise. Please response with paragraph number, cite sources and reasoning in JSON format, if multiple paragraphs are found, put them in a JSON array. make sure the paragraph number is real. If you don't know the answer just output empty.");
sb.AppendLine("[" + JsonSerializer.Serialize(new RetrievedResult()) + "]");
sb.AppendLine("------");
sb.AppendLine($"QUESTION: \"{retrievalModel.Question}\"");
sb.AppendLine("Which paragraphs are relevant in order to answer the above question?");
sb.AppendLine("ANSWER: ");
prompt = sb.ToString().Trim();
2023-06-17 02:42:35 +00:00
2023-10-30 16:48:18 +00:00
var completion = await GetTextCompletion().GetCompletion(prompt, Guid.Empty.ToString(), Guid.Empty.ToString());
2023-08-09 21:49:55 +00:00
return JsonSerializer.Deserialize<List<RetrievedResult>>(completion);
2023-06-17 02:42:35 +00:00
}
2023-06-26 23:08:24 +00:00
public IVectorDb GetVectorDb()
{
var db = _services.GetServices<IVectorDb>()
.FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.VectorDb));
2023-06-26 23:08:24 +00:00
return db;
}
public ITextEmbedding GetTextEmbedding()
{
var embedding = _services.GetServices<ITextEmbedding>()
.FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.TextEmbedding));
2023-06-26 23:08:24 +00:00
return embedding;
}
public ITextCompletion GetTextCompletion()
{
var textCompletion = _services.GetServices<ITextCompletion>()
2023-06-27 19:17:53 +00:00
.FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.TextCompletion));
return textCompletion;
}
2023-06-17 02:42:35 +00:00
}