C# FaissNet 向量查询示例,要用VS2022打开,不支持Framework ,用得NET9.0平台,并且要引用 using SentenceTransformers.MiniLM;
https://gitee.com/zyy1982/vector-search-faiss-net.git
var vectorizer = new MiniLMTitleVectorizer();
// 1. 生成测试数据并存储“向量-标题”映射(用于后续查询结果反向映射)
var testTitles = new List();
// 注意:原代码中用 float[] 作为字典键不可靠(数组引用不同),改用 List 存储向量和标题的顺序对应关系
var vectorTitleList = new List<(float[] vector, string title)>(); // 关键:按添加顺序存储向量和标题
progressBar1.Minimum = 0;
progressBar1.Maximum = 1 * 10000;
progressBar1.Value = 0;
string tempPath = Path.Combine(Application.StartupPath, "Temps");
if (!Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath);
for (int i = 1; i <= 1 * 10000; i++) // 生成101个标题(0-100)
{
progressBar1.Value += 1;
string tempstr = "Test测试" + i;
string vectorfn = Path.Combine(tempPath, i + ".txt");
if (!File.Exists(vectorfn))
{
var tempVector = vectorizer.EncodeSingleTitle(tempstr);
string json = JsonConvert.SerializeObject(tempVector);
File.WriteAllText(vectorfn, json, Encoding.UTF8);
}
string content = File.ReadAllText(vectorfn, Encoding.UTF8);
float[] data = JsonConvert.DeserializeObject(content)!;
testTitles.Add(tempstr);
vectorTitleList.Add((data, tempstr)); // 按顺序记录:向量+标题
}
const int dimension = 384;
const int k = 10;
FaissNet.Index index;
string fn = Path.Combine(Application.StartupPath, "vectors.txt");
if (!File.Exists(fn))
{
index = FaissNet.Index.Create(dimension, "Flat", MetricType.METRIC_L2);
// 2. 批量编码标题并构建FAISS索引
var vectors = vectorizer.EncodeTitles(testTitles); // 批量生成向量(顺序与testTitles一致)
index.Add(vectors); // 添加向量到索引(索引中向量的ID = 添加顺序,即0-100)
index.Save(fn);
}
index = FaissNet.Index.Load(fn);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine($"已添加 {testTitles.Count} 个 {dimension} 维向量");
// 3. 生成查询向量(例如查询“Test测试82”)
var testVector = vectorizer.EncodeSingleTitle("999999");
// 4. 执行近邻搜索(n=1:1个查询向量;k=10:返回10个近邻)
var searchResult = index.SearchFlat(1, testVector, k); // n=1,vectors=testVector,k=10
// 5. 解析并查看结果
float[] distances = searchResult.Item1; // 距离数组(长度10)
long[] neighborIds = searchResult.Item2; // 邻居ID数组(长度10,存储索引中向量的ID)
stopwatch.Stop();
StringBuilder sb = new StringBuilder();
int minitues = (int)(stopwatch.ElapsedMilliseconds);
sb.AppendLine(minitues.ToString());
sb.AppendLine($"\n查询向量:Test测试82 的 {k} 个最近邻结果:");
sb.AppendLine("排名 | 邻居ID | 原始标题 | 距离(L2)");
sb.AppendLine("-------------------------------------");
for (int i = 0; i < k; i++)
{
long neighborId = neighborIds[i]; // 第i个近邻的ID(索引中添加的顺序)
float distance = distances[i]; // 第i个近邻的距离
string title = vectorTitleList[(int)neighborId].title; // 通过ID反向映射到原始标题
sb.AppendLine($"{i + 1} | {neighborId} | {title} | {distance:F6}");
}
string str = sb.ToString();
MessageBox.Show(str);