From 45372be153633823f1c374ffbcf8dfef63bbb6ff Mon Sep 17 00:00:00 2001
From: ShaoHua <345265198@qqcom>
Date: Fri, 17 Oct 2025 02:39:47 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.vscode/launch.json | 26 +++
.vscode/tasks.json | 41 ++++
MilvusDemo/MilvusDemo.csproj | 14 ++
MilvusDemo/MilvusService.cs | 144 ++++++++++++
MilvusDemo/MilvusServiceTests.cs | 125 +++++++++++
MilvusDemo/Program.cs | 74 ++++++
MilvusDemo/TestRunner.cs | 24 ++
README.md | 69 ++++++
VectorDBDemo.slnx | 10 +
VoiceToFunctionDemo/FunctionInfo.cs | 13 ++
VoiceToFunctionDemo/ParsedResult.cs | 11 +
VoiceToFunctionDemo/Program.cs | 210 ++++++++++++++++++
VoiceToFunctionDemo/User.cs | 8 +
.../VoiceToFunctionDemo.csproj | 13 ++
14 files changed, 782 insertions(+)
create mode 100644 .vscode/launch.json
create mode 100644 .vscode/tasks.json
create mode 100644 MilvusDemo/MilvusDemo.csproj
create mode 100644 MilvusDemo/MilvusService.cs
create mode 100644 MilvusDemo/MilvusServiceTests.cs
create mode 100644 MilvusDemo/Program.cs
create mode 100644 MilvusDemo/TestRunner.cs
create mode 100644 README.md
create mode 100644 VectorDBDemo.slnx
create mode 100644 VoiceToFunctionDemo/FunctionInfo.cs
create mode 100644 VoiceToFunctionDemo/ParsedResult.cs
create mode 100644 VoiceToFunctionDemo/Program.cs
create mode 100644 VoiceToFunctionDemo/User.cs
create mode 100644 VoiceToFunctionDemo/VoiceToFunctionDemo.csproj
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..d2a221f
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,26 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // 使用 IntelliSense 找出 C# 调试存在哪些属性
+ // 将悬停用于现有属性的说明
+ // 有关详细信息,请访问 https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // 如果已更改目标框架,请确保更新程序路径。
+ "program": "${workspaceFolder}/MilvusDemo/bin/Debug/net9.0/MilvusDemo.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/MilvusDemo",
+ // 有关“控制台”字段的详细信息,请参阅 https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..d546372
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/MilvusDemo/MilvusDemo.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/MilvusDemo/MilvusDemo.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/MilvusDemo/MilvusDemo.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/MilvusDemo/MilvusDemo.csproj b/MilvusDemo/MilvusDemo.csproj
new file mode 100644
index 0000000..7b77bb2
--- /dev/null
+++ b/MilvusDemo/MilvusDemo.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/MilvusDemo/MilvusService.cs b/MilvusDemo/MilvusService.cs
new file mode 100644
index 0000000..f72bcb5
--- /dev/null
+++ b/MilvusDemo/MilvusService.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Milvus.Client;
+
+namespace MilvusDemo
+{
+ ///
+ /// 提供与Milvus向量数据库交互的服务类
+ ///
+ public class MilvusService
+ {
+ private readonly MilvusClient _milvusClient;
+ private readonly string _collectionName;
+ private readonly int _dim;
+
+ ///
+ /// 初始化MilvusService的新实例
+ ///
+ /// Milvus服务器主机名
+ /// Milvus服务器端口
+ /// 集合名称
+ /// 向量维度
+ public MilvusService(string host, int port, string collectionName, int dim)
+ {
+ _milvusClient = new MilvusClient(host, port);
+ _collectionName = collectionName;
+ _dim = dim;
+ }
+
+ ///
+ /// 初始化集合,如果存在则删除并重新创建
+ ///
+ public async Task InitializeCollectionAsync()
+ {
+ // 检查集合是否存在,如果存在则删除
+ if (await _milvusClient.HasCollectionAsync(_collectionName))
+ {
+ var collectionToDrop = _milvusClient.GetCollection(_collectionName);
+ await collectionToDrop.DropAsync();
+ Console.WriteLine($"Collection '{_collectionName}' dropped.");
+ }
+
+ // 创建新的集合
+ await _milvusClient.CreateCollectionAsync(
+ _collectionName,
+ new[]
+ {
+ FieldSchema.Create("id", isPrimaryKey: true),
+ FieldSchema.CreateVarchar("varchar", 256),
+ FieldSchema.CreateFloatVector("vector", _dim)
+ });
+ Console.WriteLine($"Collection '{_collectionName}' created.");
+ }
+
+ ///
+ /// 创建索引并加载集合
+ ///
+ public async Task CreateIndexAndLoadAsync()
+ {
+ var collection = _milvusClient.GetCollection(_collectionName);
+
+ // 创建索引
+ await collection.CreateIndexAsync("vector", IndexType.Flat, SimilarityMetricType.L2);
+ Console.WriteLine("Index created.");
+
+ // 加载集合
+ await collection.LoadAsync();
+ Console.WriteLine("Collection loaded.");
+ }
+
+ ///
+ /// 插入随机向量数据
+ ///
+ /// 要插入的向量数量
+ public async Task InsertRandomDataAsync(int count)
+ {
+ var collection = _milvusClient.GetCollection(_collectionName);
+ var random = new Random();
+
+ // 生成随机向量
+ var vectors = new List>();
+ for (int i = 0; i < count; i++)
+ {
+ var vector = new float[_dim];
+ for (int j = 0; j < _dim; j++)
+ {
+ vector[j] = (float)random.NextDouble();
+ }
+ vectors.Add(vector);
+ }
+
+ // 生成ID和字符串字段
+ var ids = Enumerable.Range(0, count).Select(i => (long)i).ToList();
+ var varchars = ids.Select(i => $"varchar_{i}").ToList();
+
+ // 打包数据
+ var insertData = new List
+ {
+ FieldData.Create("id", ids),
+ FieldData.Create("varchar", varchars),
+ FieldData.CreateFloatVector("vector", vectors)
+ };
+
+ // 执行插入
+ await collection.InsertAsync(insertData);
+ Console.WriteLine("Data inserted.");
+ }
+
+ ///
+ /// 执行向量相似度搜索
+ ///
+ /// 返回最相似的结果数量
+ /// 搜索结果
+ public async Task SearchVectorAsync(int topK = 5)
+ {
+ var collection = _milvusClient.GetCollection(_collectionName);
+ var random = new Random();
+
+ // 生成随机目标向量
+ var targetVector = new float[_dim];
+ for (int j = 0; j < _dim; j++)
+ {
+ targetVector[j] = (float)random.NextDouble();
+ }
+
+ // 设置搜索参数
+ var searchParameters = new SearchParameters();
+ searchParameters.OutputFields.Add("id");
+ searchParameters.OutputFields.Add("varchar");
+
+ // 执行搜索
+ var searchResults = await collection.SearchAsync(
+ "vector",
+ new[] { (ReadOnlyMemory)targetVector },
+ SimilarityMetricType.L2,
+ topK,
+ searchParameters);
+
+ return searchResults;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MilvusDemo/MilvusServiceTests.cs b/MilvusDemo/MilvusServiceTests.cs
new file mode 100644
index 0000000..1f65522
--- /dev/null
+++ b/MilvusDemo/MilvusServiceTests.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Milvus.Client;
+
+namespace MilvusDemo
+{
+ ///
+ /// 用于测试MilvusService的模拟类
+ ///
+ public class MilvusServiceTests
+ {
+ // 模拟的MilvusService实例
+ private readonly MilvusService _milvusService;
+
+ // 标记各个方法是否被调用
+ public bool InitializeCollectionCalled { get; private set; }
+ public bool CreateIndexAndLoadCalled { get; private set; }
+ public bool InsertRandomDataCalled { get; private set; }
+ public bool SearchVectorCalled { get; private set; }
+
+ // 记录传入的参数
+ public int InsertDataCount { get; private set; }
+ public int SearchTopK { get; private set; }
+
+ public MilvusServiceTests()
+ {
+ // 创建真实的MilvusService实例,但我们将拦截其方法调用
+ _milvusService = new MilvusService("localhost", 19530, "test_collection", 8);
+ }
+
+ ///
+ /// 模拟初始化集合的方法
+ ///
+ public async Task MockInitializeCollectionAsync()
+ {
+ InitializeCollectionCalled = true;
+ Console.WriteLine("[TEST] InitializeCollectionAsync called");
+
+ // 模拟操作延迟
+ await Task.Delay(100);
+
+ Console.WriteLine("[TEST] Collection dropped and created");
+ }
+
+ ///
+ /// 模拟创建索引并加载集合的方法
+ ///
+ public async Task MockCreateIndexAndLoadAsync()
+ {
+ CreateIndexAndLoadCalled = true;
+ Console.WriteLine("[TEST] CreateIndexAndLoadAsync called");
+
+ // 模拟操作延迟
+ await Task.Delay(100);
+
+ Console.WriteLine("[TEST] Index created");
+ Console.WriteLine("[TEST] Collection loaded");
+ }
+
+ ///
+ /// 模拟插入随机数据的方法
+ ///
+ public async Task MockInsertRandomDataAsync(int count)
+ {
+ InsertRandomDataCalled = true;
+ InsertDataCount = count;
+ Console.WriteLine($"[TEST] InsertRandomDataAsync called with count: {count}");
+
+ // 模拟操作延迟
+ await Task.Delay(100);
+
+ Console.WriteLine("[TEST] Data inserted");
+ }
+
+ ///
+ /// 模拟向量搜索的方法
+ ///
+ public async Task MockSearchVectorAsync(int topK = 5)
+ {
+ SearchVectorCalled = true;
+ SearchTopK = topK;
+ Console.WriteLine($"[TEST] SearchVectorAsync called with topK: {topK}");
+
+ // 模拟操作延迟
+ await Task.Delay(100);
+
+ // 创建模拟的搜索结果
+ var mockIds = new List();
+ for (int i = 0; i < topK; i++)
+ {
+ mockIds.Add(1000 + i); // 使用1000+i作为模拟ID
+ }
+
+ Console.WriteLine("[TEST] Search completed");
+
+ // 注意:这里我们无法直接创建SearchResults实例,因为它可能是内部类
+ // 在实际测试中,您可能需要使用模拟框架如Moq来模拟这个返回值
+ // 这里我们返回null,实际使用时需要处理这种情况
+ return null;
+ }
+
+ ///
+ /// 运行完整的测试流程
+ ///
+ public async Task RunFullTestAsync()
+ {
+ Console.WriteLine("=== Starting MilvusService Test ===");
+
+ await MockInitializeCollectionAsync();
+ await MockCreateIndexAndLoadAsync();
+ await MockInsertRandomDataAsync(1000);
+ await MockSearchVectorAsync(5);
+
+ // 打印测试结果摘要
+ Console.WriteLine("\n=== Test Summary ===");
+ Console.WriteLine($"InitializeCollection Called: {InitializeCollectionCalled}");
+ Console.WriteLine($"CreateIndexAndLoad Called: {CreateIndexAndLoadCalled}");
+ Console.WriteLine($"InsertRandomData Called: {InsertRandomDataCalled} (Count: {InsertDataCount})");
+ Console.WriteLine($"SearchVector Called: {SearchVectorCalled} (TopK: {SearchTopK})");
+
+ Console.WriteLine("=== Test Completed ===");
+ }
+ }
+}
\ No newline at end of file
diff --git a/MilvusDemo/Program.cs b/MilvusDemo/Program.cs
new file mode 100644
index 0000000..e83b03c
--- /dev/null
+++ b/MilvusDemo/Program.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Threading.Tasks;
+
+namespace MilvusDemo
+{
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ Console.WriteLine("Milvus 演示程序");
+ Console.WriteLine("1. 运行实际的 Milvus 操作");
+ Console.WriteLine("2. 运行模拟测试");
+ Console.Write("请选择 (1/2): ");
+
+ string choice = Console.ReadLine();
+
+ if (choice == "2")
+ {
+ await RunTests();
+ }
+ else
+ {
+ await RunActualMilvusOperations();
+ }
+ }
+
+ static async Task RunActualMilvusOperations()
+ {
+ // 初始化MilvusService
+ const string host = "localhost";
+ const int port = 19530;
+ const string collectionName = "csharp_demo_collection";
+ const int dim = 8; // 向量维度
+
+ // 创建MilvusService实例
+ var milvusService = new MilvusService(host, port, collectionName, dim);
+
+ try
+ {
+ // 初始化集合(如果存在则删除并重新创建)
+ await milvusService.InitializeCollectionAsync();
+
+ // 创建索引并加载集合
+ await milvusService.CreateIndexAndLoadAsync();
+
+ // 插入随机数据
+ await milvusService.InsertRandomDataAsync(1000);
+
+ // 执行向量搜索
+ var searchResults = await milvusService.SearchVectorAsync(5);
+
+ // 显示搜索结果
+ Console.WriteLine("\nSearch results:");
+ foreach (var result in searchResults.Ids.LongIds)
+ {
+ Console.WriteLine($"- ID: {result}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error: {ex.Message}");
+ if (ex.InnerException != null)
+ {
+ Console.WriteLine($"Inner error: {ex.InnerException.Message}");
+ }
+ }
+ }
+
+ static async Task RunTests()
+ {
+ await TestRunner.RunTests();
+ }
+ }
+}
diff --git a/MilvusDemo/TestRunner.cs b/MilvusDemo/TestRunner.cs
new file mode 100644
index 0000000..8b190c9
--- /dev/null
+++ b/MilvusDemo/TestRunner.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Threading.Tasks;
+
+namespace MilvusDemo
+{
+ ///
+ /// 用于运行MilvusService测试的类
+ ///
+ public class TestRunner
+ {
+ ///
+ /// 运行测试
+ ///
+ public static async Task RunTests()
+ {
+ Console.WriteLine("开始运行MilvusService测试...");
+
+ var tester = new MilvusServiceTests();
+ await tester.RunFullTestAsync();
+
+ Console.WriteLine("测试完成!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f40c7fb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,69 @@
+# MilvusDemo
+
+一个使用 C#(.NET 9)与 `Milvus.Client` 的极简示例项目,演示:
+- 初始化集合(存在则删除并重建)
+- 创建向量索引与加载集合
+- 批量插入随机向量
+- 执行向量相似度搜索
+- 通过内置测试流程验证调用链
+
+### 模块划分
+- **App(入口层)**:`Program.cs`
+ - 提供交互式入口:输入 1=实际连接 Milvus 执行;输入 2=运行内置测试(无需 Milvus 实例)。
+- **Core/Service(业务层)**:`MilvusService.cs`
+ - 封装与 Milvus 的连接、集合初始化、索引创建/加载、数据插入与搜索。
+- **Test Harness(测试层)**:`TestRunner.cs`、`MilvusServiceTests.cs`
+ - `TestRunner` 负责编排测试流程;`MilvusServiceTests` 提供无外部依赖的模拟测试(验证调用链与参数)。
+
+### 环境要求
+- .NET SDK 9.0+
+- 仅当选择“实际运行(选项 1)”时需要:可访问的 Milvus Server(默认 `localhost:19530`)。
+
+### 快速开始
+1. 构建
+ ```powershell
+ dotnet build
+ ```
+2. 运行(测试模式,无需 Milvus)
+ - PowerShell:
+ ```powershell
+ echo 2 | dotnet run
+ ```
+ - Bash:
+ ```bash
+ echo 2 | dotnet run
+ ```
+3. 运行(实际连接 Milvus)
+ - 确保本地或可达的 Milvus 实例运行在 `localhost:19530`。
+ - 程序启动后输入 `1`。
+
+### 启动 Milvus(可选)
+若需在本机快速启动 Milvus,可参考官方快速开始,或使用 Docker(示例):
+
+```bash
+# 仅供参考,建议按官方文档选择合适的版本与持久化配置
+docker pull milvusdb/milvus:latest
+docker run -d --name milvus-standalone -p 19530:19530 milvusdb/milvus:latest
+```
+
+文档:`https://milvus.io/docs`(查看“Get Started / Install”)。
+
+### 主要参数(实际运行模式)
+- 主机与端口:`localhost:19530`
+- 集合名:`csharp_demo_collection`
+- 向量维度:`8`
+
+> 提示:若需修改连接地址或集合名,请在代码中相应位置调整(例如在连接初始化与集合定义处)。
+
+### 文件说明
+- `Program.cs`:控制台入口与菜单;调用服务或测试。
+- `MilvusService.cs`:核心服务,封装 Milvus 客户端操作。
+- `MilvusServiceTests.cs`:简单的模拟测试实现(不依赖 Milvus)。
+- `TestRunner.cs`:运行测试流程的编排类。
+- `MilvusDemo.csproj`:项目与依赖定义(包含 `Milvus.Client`)。
+
+### 常见问题(FAQ)
+- 无法连接到 Milvus:请确认 Milvus 是否已启动并监听 `19530` 端口,以及本机/容器网络连通性。
+- 还原/编译失败:请确认已安装 .NET 9 SDK,并允许联网下载 NuGet 依赖;必要时执行 `dotnet restore` 后再构建。
+- 端口占用:如 `19530` 已被占用,请修改容器映射或程序连接端口并保持一致。
+
diff --git a/VectorDBDemo.slnx b/VectorDBDemo.slnx
new file mode 100644
index 0000000..72029d1
--- /dev/null
+++ b/VectorDBDemo.slnx
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VoiceToFunctionDemo/FunctionInfo.cs b/VoiceToFunctionDemo/FunctionInfo.cs
new file mode 100644
index 0000000..8774fed
--- /dev/null
+++ b/VoiceToFunctionDemo/FunctionInfo.cs
@@ -0,0 +1,13 @@
+namespace VoiceToFunction
+{
+ // 函数信息模型(新增参数类型描述,用于校验)
+ public class FunctionInfo
+ {
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public List Synonyms { get; set; }
+ public int MinParams { get; set; }
+ public List ParamTypes { get; set; } // 参数类型列表(如double[], List)
+ public Func