首页 > 教程攻略 > ai资讯 >解锁GraphRag.Net的无限可能:手把手教你集成国产模型和本地模型

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

来源:互联网 时间:2026-08-22 14:46:07

前两篇文章聊下来,大家应该已经清楚

GraphRag.Net

原生只支持 OpenAI 规范的接口。不过社区里很多小伙伴一直在问:能不能加上对本地模型(比如 ollama)的支持?能不能接国产模型?答案是肯定的,而且实现起来并不复杂。这次我们就专门来拆解一下,怎么在 GraphRag.Net 里接入自定义模型和本地模型。

为什么选择GraphRag.Net?

GraphRag.Net 底层基于

Semantic Kernel

,这让我们能非常简洁地抽象出会话与向量接口。换句话说,只要按照框架的约定去实现对应的服务,你就能用自己想要的任何模型来驱动整个流程。接下来,我们直接通过一个具体例子,演示如何把本地模型和国产模型集成进来。

默认配置方法

先回顾一下默认配置长什么样——这也是理解自定义配置的基础:

// OpenAI配置
builder.Configuration.GetSection("OpenAI").Get();
// 文档切片配置
builder.Configuration.GetSection("TextChunker").Get();
// 配置数据库连接
builder.Configuration.GetSection("GraphDBConnection").Get();

// 注意,需要先注入配置文件,然后再注入GraphRag.Net
builder.Services.AddGraphRagNet();

这段代码做的事情很清晰:注入 OpenAI 的配置、文本切片的配置和数据库连接的配置,然后注册 GraphRag.Net 的服务。默认情况下,它自然使用的是 OpenAI 的接口。

自定义配置方法

如果想把背后的模型换成自定义的,需要自己实现几个关键服务接口。下面是一个完整的自定义配置示例:

var kernelBuild = Kernel.CreateBuilder();
kernelBuild.Services.AddKeyedSingleton("mock-text", new MockTextCompletion());
kernelBuild.Services.AddKeyedSingleton("mock-chat", new MockChatCompletion());
kernelBuild.Services.AddSingleton(new MockTextEmbeddingGeneratorService());
kernelBuild.Services.AddKeyedSingleton("mock-embedding", new MockTextEmbeddingGeneratorService());

builder.Services.AddGraphRagNet(kernelBuild.Build());

这里用到了三个核心接口:

ITextGenerationService

(文本生成)、

IChatCompletionService

(聊天补全)和

ITextEmbeddingGenerationService

(文本向量化)。只要把它们换成你实际模型的实现,就能无缝切换。

实现自定义服务接口

接下来,我们分别给出三个接口的示例实现(这里是 Mock 版本,方便你理解骨架,实际替换成本地模型的 API 调用即可)。

实现 IChatCompletionService

public class MockChatCompletion : IChatCompletionService
{
    private readonly Dictionary _attributes = new();
    private string _chatId;

    private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
    {
        NumberHandling = JsonNumberHandling.AllowReadingFromString,
        Encoder = Ja vaScriptEncoder.Create(UnicodeRanges.All)
    };

    public IReadOnlyDictionary Attributes => _attributes;

    public MockChatCompletion() { }

    public async Task> GetChatMessageContentsAsync(
        ChatHistory chatHistory,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default)
    {
        string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}";
        return [new(AuthorRole.Assistant, result.ToString())];
    }

    public async IAsyncEnumerable GetStreamingChatMessageContentsAsync(
        ChatHistory chatHistory,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default)
    {
        string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{chatHistory.LastOrDefault().ToString()}";
        foreach (var c in result)
        {
            yield return new StreamingChatMessageContent(AuthorRole.Assistant, c.ToString());
        }
    }
}

实现 ITextGenerationService

public class MockTextCompletion : ITextGenerationService, IAIService
{
    private readonly Dictionary _attributes = new();
    private string _chatId;

    private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
    {
        NumberHandling = JsonNumberHandling.AllowReadingFromString,
        Encoder = Ja vaScriptEncoder.Create(UnicodeRanges.All)
    };

    public IReadOnlyDictionary Attributes => _attributes;

    public MockTextCompletion() { }

    public async Task> GetTextContentsAsync(
        string prompt,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default)
    {
        string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{prompt}";
        return [new(result.ToString())];
    }

    public async IAsyncEnumerable GetStreamingTextContentsAsync(
        string prompt,
        PromptExecutionSettings? executionSettings = null,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default)
    {
        string result = $"这是一条Mock数据,便于聊天测试,你的消息是:{prompt}";
        foreach (var c in result)
        {
            yield return new StreamingTextContent(c.ToString(), modelId: "mock");
        }
    }
}

实现 ITextEmbeddingGenerationService

public sealed class MockTextEmbeddingGeneratorService : ITextEmbeddingGenerationService
{
    private Dictionary AttributesInternal { get; } = [];
    public IReadOnlyDictionary Attributes => this.AttributesInternal;

    public MockTextEmbeddingGeneratorService() { }

    public async Task>> GenerateEmbeddingsAsync(
        IList data,
        Kernel? kernel = null,
        CancellationToken cancellationToken = default)
    {
        IList> results = new List>();

        float[] array1 = { 1.0f, 2.0f, 3.0f };
        float[] array2 = { 4.0f, 5.0f, 6.0f };
        float[] array3 = { 7.0f, 8.0f, 9.0f };

        results.Add(new ReadOnlyMemory(array1));
        results.Add(new ReadOnlyMemory(array2));
        results.Add(new ReadOnlyMemory(array3));

        return results;
    }

    public void Dispose() { }
}

看到这里,你应该已经发现了——整个集成思路其实很直白:把三个接口按照你需要调用的模型逻辑实现一遍,然后在初始化时注入到 Kernel 里,再传给 GraphRag.Net。无论是国产模型(比如百度文心、阿里通义)还是本地部署的 ollama、llama.cpp,都可以用同样的模式接入。只需要把 Mock 代码里返回固定字符串的逻辑,换成真正的 HTTP 调用或本地推理接口即可。

结语

通过这几步,你就能在 GraphRag.Net 中自由切换模型了。实际项目中,你只需要根据自己的模型 SDK 替换掉实现类中的核心逻辑。希望这个框架能帮你省下大量对接和抽象的工作,让你更专注于业务本身。如果有任何疑问,欢迎在社区里一起讨论。

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