인터넷 상에서 검색된 정보를 기반으로 답하는 일반적인 ChatGPT 기능을 넘어서서, 특정한 맥락을 학습시키고, 맥락을 기반으로 정확한 답을 할 수 있는 커스터마이징 챗봇을 만들 수 있는 방법으로 Langchain이 많이 거론됩니다. 여기에 대응되는 닷넷 버전의 구현체는 Microsoft의 Semantic Kernel이 있습니다.
2개의 좋아요
다음은 코드 예시와 실행 예시입니다.
// Text Completion Model: text-davinci-003
// Text Embeding Model: text-embedding-ada-002
var openAiEndpoint = "...";
var openAiApiKey = "...";
var store = await SqliteMemoryStore.ConnectAsync(
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "semantic.db"));
var kernel = new KernelBuilder()
.Configure(c => {
c.AddAzureTextCompletionService("TextCompletion", openAiEndpoint, openAiApiKey);
c.AddAzureTextEmbeddingGenerationService("TextEmbedding", openAiEndpoint, openAiApiKey);
})
.WithMemoryStorage(store)
.Build();
async Task IndexContents(IKernel kernel, string collection)
{
await kernel.Memory.SaveInformationAsync(collection, id: "info1", text: "My name is Andrea");
await kernel.Memory.SaveInformationAsync(collection, id: "info2", text: "I currently work as a tourist operator");
await kernel.Memory.SaveInformationAsync(collection, id: "info3", text: "I also currently work as a bus driver");
await kernel.Memory.SaveInformationAsync(collection, id: "info4", text: "I sometimes work as a teacher");
}
ISKFunction PrepareSkillFunction(IKernel kernel)
{
var promptTemplate = @"Use the following pieces of context to answer the question at the end. If you don't know the answer, don't try to make up an answer and answer with '모르겠어요.'. Answer in the langauge that used for the question.
{{$context}}
Question: {{$INPUT}}
Answer:
";
var config = new PromptTemplateConfig()
{
Schema = 1,
Description = "Given a context answer a question",
Type = "completion",
Completion = new PromptTemplateConfig.CompletionConfig {
MaxTokens = 2000,
Temperature = 0d,
TopP = 1d,
PresencePenalty = 0d,
FrequencyPenalty = 0d,
},
};
return kernel.CreateSemanticFunction(
promptTemplate, config, functionName: "answer", skillName: "qa");
}
async Task<string> Answer(IKernel kernel, string collection, string question)
{
var results = await kernel.Memory.SearchAsync(collection, question).ToListAsync();
var variables = new ContextVariables(question)
{
["context"] = results.Any()
? string.Join("\n", results.Select(r => r.Metadata.Text))
: "No context found for this question."
};
var function = kernel.Skills.GetFunction("qa", "answer");
var result = await kernel.RunAsync(variables, function);
return result.Result;
}
PrepareSkillFunction(kernel);
const string MemoryCollectionName = "aboutMe";
await IndexContents(kernel, MemoryCollectionName);
var questions = new[]
{
"나의 이름이 뭔지 맞춰봐.",
"나는 어디서 살고 있을까?",
"what do I do for work?",
"오늘 날씨 어때?",
};
foreach (var q in questions)
{
var response = await Answer(kernel, MemoryCollectionName, q);
Console.WriteLine(q + "\n" + response + "\n");
}
실행 예시
4개의 좋아요