解锁GraphRag.Net的无限可能:手把手教你集成国产模型和本地模型

        在上次的文章中,我们已经详细介绍了GraphRag的基本功能和使用方式。如果你还不熟悉,建议先阅读前面的文章

        通过前两篇文章,相信你已经了解到GraphRag.Net目前只支持OpenAI规范的接口,但许多小伙伴在社区中提议,希望能增加对本地模型(例如:ollama等)的支持。所以这次,我们将探讨如何在GraphRag.Net中使用自定义模型和本地模型。

 
为什么选择GraphRag.Net?

        GraphRag.Net采用了Semantic Kernel作为基础,让我们能够非常简洁地抽象出会话与向量接口。因此,用户可以非常方便地实现自己定制的解决方案。接下来,我们会通过一个具体的例子,展示如何将本地模型和国产模型集成到GraphRag.Net中。

默认配置方法

        首先,我们来看看如何进行默认配置:

?
1
2
3
4
5
6
7
8
9
// OpenAI配置
builder.Configuration.GetSection( "OpenAI" ).Get<OpenAIOption>();
// 文档切片配置
builder.Configuration.GetSection( "TextChunker" ).Get<TextChunkerOption>();
// 配置数据库连接
builder.Configuration.GetSection( "GraphDBConnection" ).Get<GraphDBConnectionOption>();
 
// 注意,需要先注入配置文件,然后再注入GraphRag.Net
builder.Services.AddGraphRagNet();

        这里,我们将在默认配置中注入OpenAI的配置、文本切片的配置和数据库连接的配置。然后,依次注入这些配置文件和GraphRag.Net的服务。

自定义配置方法

        如果需要自定义模型或本地模型,可能需要实现一些额外的服务接口,下面是自定义配置的示例:

?
1
2
3
4
5
6
7
var kernelBuild = Kernel.CreateBuilder();
kernelBuild.Services.AddKeyedSingleton<ITextGenerationService>( "mock-text" , new MockTextCompletion());
kernelBuild.Services.AddKeyedSingleton<IChatCompletionService>( "mock-chat" , new MockChatCompletion());
kernelBuild.Services.AddSingleton<ITextEmbeddingGenerationService>( new MockTextEmbeddingGeneratorService());
kernelBuild.Services.AddKeyedSingleton( "mock-embedding" , new MockTextEmbeddingGeneratorService());
 
builder.Services.AddGraphRagNet(kernelBuild.Build());

在这个自定义配置示例中,我们引入了三个自定义服务接口:ITextGenerationServiceIChatCompletionServiceITextEmbeddingGenerationService

实现自定义服务接口

接下来,我们需要为每个服务接口提供具体的实现。以下是三个接口的具体实现:

实现IChatCompletionService
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class MockChatCompletion : IChatCompletionService
{
     private readonly Dictionary< string , object ?> _attributes = new ();
     private string _chatId;
 
 
     private static readonly JsonSerializerOptions _jsonSerializerOptions = new ()
     {
         NumberHandling = JsonNumberHandling.AllowReadingFromString,
         Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
     };
 
     public IReadOnlyDictionary< string , object ?> Attributes => _attributes;
 
     public MockChatCompletion()
     {
 
     }
 
     public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null , Kernel? kernel = null , [EnumeratorCancellation] CancellationToken cancellationToken = default )
     {
         StringBuilder sb = new ();
         string result = $ "这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}" ;
         return [ new (AuthorRole.Assistant, result.ToString())];
     }
 
     public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null , Kernel? kernel = null , [EnumeratorCancellation] CancellationToken cancellationToken = default )
     {
         StringBuilder sb = new ();
         string result = $ "这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}" ;
         foreach ( var c in result)
         {
             yield return new StreamingChatMessageContent(AuthorRole.Assistant, c.ToString());
         }
     }
}

  

实现ITextGenerationService
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MockTextCompletion : ITextGenerationService, IAIService
{
     private readonly Dictionary< string , object ?> _attributes = new ();
     private string _chatId;
 
     private static readonly JsonSerializerOptions _jsonSerializerOptions = new ()
     {
         NumberHandling = JsonNumberHandling.AllowReadingFromString,
         Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
     };
 
     public IReadOnlyDictionary< string , object ?> Attributes => _attributes;
 
     public MockTextCompletion()
     {
 
     }
 
     public async Task<IReadOnlyList<TextContent>> GetTextContentsAsync( string prompt, PromptExecutionSettings? executionSettings = null , Kernel? kernel = null , CancellationToken cancellationToken = default )
     {
         StringBuilder sb = new ();
         string result = $ "这是一条Mock数据,便于聊天测试,你的消息是:{prompt}" ;
         return [ new (result.ToString())];
     }
 
     public async IAsyncEnumerable<StreamingTextContent> GetStreamingTextContentsAsync( string prompt, PromptExecutionSettings? executionSettings = null , Kernel? kernel = null , CancellationToken cancellationToken = default )
     {
         StringBuilder sb = new ();
         string result = $ "这是一条Mock数据,便于聊天测试,你的消息是:{prompt}" ;
         foreach ( var c in result)
         {
             var streamingTextContent = new StreamingTextContent(c.ToString(), modelId: "mock" );
 
             yield return streamingTextContent;
         }
     }
}
实现ITextEmbeddingGenerationService
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public sealed class MockTextEmbeddingGeneratorService : ITextEmbeddingGenerationService
{
     private Dictionary< string , object ?> AttributesInternal { get ; } = [];
     public IReadOnlyDictionary< string , object ?> Attributes => this .AttributesInternal;
     public MockTextEmbeddingGeneratorService()
     {
 
     }
     public async Task<IList<ReadOnlyMemory< float >>> GenerateEmbeddingsAsync(
       IList< string > data,
       Kernel? kernel = null ,
       CancellationToken cancellationToken = default )
     {
         IList<ReadOnlyMemory< float >> results = new List<ReadOnlyMemory< float >>();
 
         float [] array1 = { 1.0f, 2.0f, 3.0f };
         float [] array2 = { 4.0f, 5.0f, 6.0f };
         float [] array3 = { 7.0f, 8.0f, 9.0f };
 
         // 将数组包装为ReadOnlyMemory<float>并添加到列表中
         results.Add( new ReadOnlyMemory< float >(array1));
         results.Add( new ReadOnlyMemory< float >(array2));
         results.Add( new ReadOnlyMemory< float >(array3));
 
         return results;
     }
 
     public void Dispose()
     {
 
     }
}

  

        看到这里,你可能已经发现,集成自定义模型和本地模型非常简单。只需按照上述步骤,实现相应的接口并注入配置,你就可以在GraphRag.Net中使用这些自定义的功能。

 

结语

        通过本文的介绍,我们了解了如何在GraphRag.Net中集成国产模型和本地模型。希望大家能够根据这些示例,开发出更多适合自己需求的功能。更多精彩内容,欢迎关注我的公众号,并发送进群加入我们的GraphRag.Net交流群,与社区小伙伴们一起交流学习!

        感谢阅读,我们下期再见!

 

原创作者: xuzeyu 转载于: https://www.cnblogs.com/xuzeyu/p/18343527
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值