惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
I
InfoQ
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
Y
Y Combinator Blog
博客园_首页
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
A
About on SuperTechFans
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
C
Check Point Blog
B
Blog RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Engineering at Meta
Engineering at Meta
B
Blog
爱范儿
爱范儿
Stack Overflow Blog
Stack Overflow Blog
aimingoo的专栏
aimingoo的专栏
WordPress大学
WordPress大学
F
Fortinet All Blogs
月光博客
月光博客
GbyAI
GbyAI

博客园 - 冠军

Keep alive 分析 SSRS Reporting Service 日志 [翻译] 感谢 Avalonia, .NET MAUI 即将来到 Linux 和浏览器端 多区域一致性:鱼与熊掌兼得! Microsoft Agent Framework (预览) 入门:让所有的开发者轻松创建 AI Agents 使用 AI app 模板扩展来创建基于订制数据进行聊天的 .NET AI 应用 真正的 .NET 单文件发布与构建 Microsoft.Extensions.AI 库 OfficeRuntime.storage 适配 oidc-client.js 中的 WebStorageStateStore 翻译:基于 OAuth2 在 Web 服务中使用 MailKit Microsoft.Extensions.VectorData.Abstractions 入门 使用 PdfPig 处理 PDF 文档 使用 Any CPU构建 .NET 8 应用会支持 32 位吗? 使用 NATS CLI NATS: 使用 work-queue Stream NATS: Pull Consumers in JetStream .NET 单文件执行程序拆解器 SingleFileExtractor .NET Aspire Apps 集成测试 ASCII 与 Unicode 中的引号
基于本地 Llama 生成 .NET AI 矢量搜索应用
冠军 · 2025-06-28 · via 博客园 - 冠军

本文使用运行在本地的 llama 来实现 AI 向量搜索。它使用 OllamaSharp 访问本地的 llama 中运行的模型。

注意:OllamaSharp 5.2.3 可以工作, 但是 OllamaSharp 5.0.4 不行。
会抛出异常:System.MissingMethodException: Method not found: 'Microsoft.Extensions.AI.ChatClientMetadata Microsoft.Extensions.AI.IChatClient.get_Metadata()'.

先决条件

  • .NET 8.0 SDK 或者更高版本

使用的 NuGet 包

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.6.0" />
  <PackageReference Include="Microsoft.Extensions.VectorData.Abstractions" Version="9.6.0" />
  <PackageReference Include="Microsoft.SemanticKernel.Connectors.InMemory" Version="1.58.0-preview" />
  <PackageReference Include="OllamaSharp" Version="5.2.3" />
  <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-preview.5.25277.114" />
</ItemGroup>

创建应用

1. 创建控制台应用

dotnet new console -o VectorDataAI

2. 将应用目录设为当前目录

cd VectorDataAI

3. 安装所需的 NuGet 包

dotnet add package Microsoft.Extensions.AI.Abstractions
dotnet add package Microsoft.Extensions.VectorData.Abstractions
dotnet add package Microsoft.SemanticKernel.Connectors.InMemory --prerelease
dotnet add package OllamaSharp
dotnet add package System.Linq.AsyncEnumerable --prerelease

示例所涉及的 NuGet 包:

  • Microsoft.Extensions.AI.Abstractions, 为大模型提供 AI 抽象
  • Microsoft.Extensions.VectorData.Abstractions, 启用对矢量存储的 Create-Read-Update-Delete (CRUD) 和搜索操作
  • OllamaSharp, 提供针对 Ollama 的实现支持
  • Microsoft.SemanticKernel.Connectors.InMemory, 供内存中矢量存储类来保存可查询矢量数据记录。

编写代码

1. 创建数据映射类

创建 CloudService.cs 代码文件,其中定义了数据映射。

using Microsoft.Extensions.VectorData;

namespace VectorDataAI;

internal class CloudService
{
    [VectorStoreKey]
    public int Key { get; set; }

    [VectorStoreData]
    public string Name { get; set; }

    [VectorStoreData]
    public string Description { get; set; }

    [VectorStoreVector(
        Dimensions: 384,
        DistanceFunction = DistanceFunction.CosineSimilarity)]
    public ReadOnlyMemory<float> Vector { get; set; }
}

这里的 VectorStoreVector 特性标志用来存储生成的向量,它表示 Description 中文本的语义含义。

2. 创建示例数据

List<CloudService> cloudServices =
[
    new() {
            Key = 0,
            Name = "Azure App Service",
            Description = "Host .NET, Java, Node.js, and Python web applications and APIs in a fully managed Azure service. You only need to deploy your code to Azure. Azure takes care of all the infrastructure management like high availability, load balancing, and autoscaling."
    },
    new() {
            Key = 1,
            Name = "Azure Service Bus",
            Description = "A fully managed enterprise message broker supporting both point to point and publish-subscribe integrations. It's ideal for building decoupled applications, queue-based load leveling, or facilitating communication between microservices."
    },
    new() {
            Key = 2,
            Name = "Azure Blob Storage",
            Description = "Azure Blob Storage allows your applications to store and retrieve files in the cloud. Azure Storage is highly scalable to store massive amounts of data and data is stored redundantly to ensure high availability."
    },
    new() {
            Key = 3,
            Name = "Microsoft Entra ID",
            Description = "Manage user identities and control access to your apps, data, and resources."
    },
    new() {
            Key = 4,
            Name = "Azure Key Vault",
            Description = "Store and access application secrets like connection strings and API keys in an encrypted vault with restricted access to make sure your secrets and your application aren't compromised."
    },
    new() {
            Key = 5,
            Name = "Azure AI Search",
            Description = "Information retrieval at scale for traditional and conversational search applications, with security and options for AI enrichment and vectorization."
    }
];

3. 基于 OllamaSharp 创建使用 Ollama 的向量生成器实例

OllamaApiClient 实现了 3 个接口:

  • IOllamaApiClient
  • IChatClient
  • IEmbeddingGenerator<string, Embedding>

可以直接将 OllamaApiClient 转型为 IEmbeddingGenerator<string, Embedding> 引用。

var uri = "http://localhost:11434";
string model = "deepseek-r1:1.5b";

var client = new OllamaApiClient(uri, model);

// Create the embedding generator.
IEmbeddingGenerator<string, Embedding<float>> generator =
            client as IEmbeddingGenerator<string, Embedding<float>>;

Console.WriteLine($"Using Ollama API at {uri} with model {model}");

4. 使用向量生成器创建并存储向量

首先,创建内存中的向量存储。然后,在内存中的向量存储中创建名为 cloudServices 的向量集合。
最后,使用向量生成器将 Description 中内容向量化并存储。

// Create and populate the vector store.
var vectorStore = new InMemoryVectorStore();
VectorStoreCollection<int, CloudService> cloudServicesStore =
    vectorStore.GetCollection<int, CloudService>("cloudServices");
await cloudServicesStore.EnsureCollectionExistsAsync();

foreach (CloudService service in cloudServices)
{
    service.Vector = await generator.GenerateVectorAsync(service.Description);
    await cloudServicesStore.UpsertAsync(service);
}

5. 在创建的向量上执行向量搜索

// Convert a search query to a vector
// and search the vector store.
string query = "Which Azure service should I use to store my Word documents?";
Console.WriteLine($"Querying: {query}");
ReadOnlyMemory<float> queryEmbedding = await generator.GenerateVectorAsync(query);

IAsyncEnumerable<VectorSearchResult<CloudService>> results =
            cloudServicesStore.SearchAsync(queryEmbedding, top: 1);

await foreach (VectorSearchResult<CloudService> result in results)
{
    Console.WriteLine($"Name: {result.Record.Name}");
    Console.WriteLine($"Description: {result.Record.Description}");
    Console.WriteLine($"Vector match score: {result.Score}");
}

6. 执行程序

> dotnet run
Hello, World!
Using Ollama API at http://localhost:11434 with model deepseek-r1:1.5b
Querying: Which Azure service should I use to store my Word documents?
Name: Microsoft Entra ID
Description: Manage user identities and control access to your apps, data, and resources.
Vector match score: 0.8528178930282593

完整代码

using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel;
using VectorDataAI;
using OllamaSharp;
using OllamaSharp.Models;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;

// See https://aka.ms/new-console-template for more information
class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Hello, World!");

        List<CloudService> cloudServices = new List<CloudService>
        {
            new() {
                Key = 0,
                Name = "Azure App Service",
                Description = "Host .NET, Java, Node.js, and Python web applications and APIs in a fully managed Azure service. You only need to deploy your code to Azure. Azure takes care of all the infrastructure management like high availability, load balancing, and autoscaling."
            },
            new() {
                Key = 1,
                Name = "Azure Service Bus",
                Description = "A fully managed enterprise message broker supporting both point to point and publish-subscribe integrations. It's ideal for building decoupled applications, queue-based load leveling, or facilitating communication between microservices."
            },
            new() {
                Key = 2,
                Name = "Azure Blob Storage",
                Description = "Azure Blob Storage allows your applications to store and retrieve files in the cloud. Azure Storage is highly scalable to store massive amounts of data and data is stored redundantly to ensure high availability."
            },
            new() {
                Key = 3,
                Name = "Microsoft Entra ID",
                Description = "Manage user identities and control access to your apps, data, and resources."
            },
            new() {
                Key = 4,
                Name = "Azure Key Vault",
                Description = "Store and access application secrets like connection strings and API keys in an encrypted vault with restricted access to make sure your secrets and your application aren't compromised."
            },
            new() {
                Key = 5,
                Name = "Azure AI Search",
                Description = "Information retrieval at scale for traditional and conversational search applications, with security and options for AI enrichment and vectorization."
            }
        };

        var uri = "http://localhost:11434";
        string model = "deepseek-r1:1.5b";

        var client = new OllamaApiClient(uri, model);

        // Create the embedding generator.
        IEmbeddingGenerator<string, Embedding<float>> generator =
            client as IEmbeddingGenerator<string, Embedding<float>>;

        Console.WriteLine($"Using Ollama API at {uri} with model {model}");

        // Create and populate the vector store.
        var vectorStore = new InMemoryVectorStore();
        VectorStoreCollection<int, CloudService> cloudServicesStore =
            vectorStore.GetCollection<int, CloudService>("cloudServices");
        await cloudServicesStore.EnsureCollectionExistsAsync();

        foreach (CloudService service in cloudServices)
        {
            service.Vector = await generator.GenerateVectorAsync(service.Description);
            await cloudServicesStore.UpsertAsync(service);
        }

        // Convert a search query to a vector
        // and search the vector store.
        string query = "Which Azure service should I use to store my Word documents?";
        Console.WriteLine($"Querying: {query}");
        ReadOnlyMemory<float> queryEmbedding = await generator.GenerateVectorAsync(query);

        IAsyncEnumerable<VectorSearchResult<CloudService>> results =
            cloudServicesStore.SearchAsync(queryEmbedding, top: 1);

        await foreach (VectorSearchResult<CloudService> result in results)
        {
            Console.WriteLine($"Name: {result.Record.Name}");
            Console.WriteLine($"Description: {result.Record.Description}");
            Console.WriteLine($"Vector match score: {result.Score}");
        }
    }
}

执行结果

Hello, World!
Using Ollama API at http://localhost:11434 with model deepseek-r1:1.5b
Querying: Which Azure service should I use to store my Word documents?
Name: Microsoft Entra ID
Description: Manage user identities and control access to your apps, data, and resources.
Vector match score: 0.8528178930282593

这个文档已经过时!
https://learn.microsoft.com/zh-cn/dotnet/ai/quickstarts/build-vector-search-app?pivots=openai