BotSharp/src/Infrastructure/BotSharp.Core/Knowledges/Services/KnowledgeService.cs

84 lines
2.6 KiB
C#
Raw Normal View History

2023-06-17 02:42:35 +00:00
using BotSharp.Abstraction.Knowledges.Models;
using System.IO;
using BotSharp.Abstraction.MLTasks;
namespace BotSharp.Core.Knowledges.Services;
public class KnowledgeService : IKnowledgeService
{
private readonly ITextEmbedding _textEmbedding;
private readonly ITextCompletion _textCompletion;
2023-06-18 18:15:00 +00:00
private readonly ITextChopper _textChopper;
2023-06-18 02:56:22 +00:00
private readonly IVectorDb _db;
2023-06-18 18:15:00 +00:00
2023-06-18 02:56:22 +00:00
public KnowledgeService(ITextEmbedding textEmbedding,
ITextCompletion textCompletion,
2023-06-18 18:15:00 +00:00
ITextChopper textChopper,
2023-06-18 02:56:22 +00:00
IVectorDb db)
2023-06-17 02:42:35 +00:00
{
_textEmbedding = textEmbedding;
_textCompletion = textCompletion;
2023-06-18 18:15:00 +00:00
_textChopper = textChopper;
2023-06-18 02:56:22 +00:00
_db = db;
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 = 256,
Conjunction = 32
});
// Store chunks in local file system
var knowledgeStoreDir = Path.Combine("knowledge_chunks", knowledge.AgentId);
if(!Directory.Exists(knowledgeStoreDir))
{
Directory.CreateDirectory(knowledgeStoreDir);
}
var knowledgePath = Path.Combine(knowledgeStoreDir, knowledge.Name);
File.WriteAllLines(knowledgePath + ".txt", lines);
2023-06-17 02:42:35 +00:00
2023-06-18 18:15:00 +00:00
await _db.CreateCollection(knowledge.Name, _textEmbedding.Dimension);
2023-06-17 02:42:35 +00:00
foreach (var line in lines)
{
2023-06-18 18:15:00 +00:00
await _db.Upsert(knowledge.Name, idStart, _textEmbedding.GetVector(line));
2023-06-17 02:42:35 +00:00
idStart++;
}
}
2023-06-18 18:15:00 +00:00
public async Task<string> GetAnswer(KnowledgeRetrievalModel retrievalModel)
2023-06-17 02:42:35 +00:00
{
2023-06-18 18:15:00 +00:00
var vector = _textEmbedding.GetVector(retrievalModel.Question);
// Scan local knowledge directory
var knowledgeName = "";
var chunks = new string[0];
foreach (var file in Directory.GetFiles(Path.Combine("knowledge_chunks", retrievalModel.AgentId)))
{
knowledgeName = new FileInfo(file).Name.Split('.').First();
chunks = File.ReadAllLines(file);
}
2023-06-17 02:42:35 +00:00
// Vector search
2023-06-18 18:15:00 +00:00
var result = await _db.Search(knowledgeName, vector);
2023-06-17 02:42:35 +00:00
2023-06-18 18:15:00 +00:00
// Restore
2023-06-17 02:42:35 +00:00
var prompt = "";
2023-06-18 02:56:22 +00:00
foreach (var r in result)
2023-06-17 02:42:35 +00:00
{
2023-06-18 18:15:00 +00:00
prompt += chunks[r] + "\n";
2023-06-17 02:42:35 +00:00
}
2023-06-18 18:15:00 +00:00
prompt += "\r\n###\r\n";
2023-06-17 02:42:35 +00:00
prompt += "Answer the user's question based on the content provided above, and your reply should be as concise and organized as possible.\r\n";
2023-06-18 18:15:00 +00:00
prompt += $"Question: {retrievalModel.Question}\r\nAnswer: ";
2023-06-17 02:42:35 +00:00
var completion = await _textCompletion.GetCompletion(prompt);
return completion;
}
}