multilingual-e5-small + ONNX Runtime,使用 ONNX Runtime 的内置分词
使用帮助
admin
发布时间:2026-03-15
浏览:122 次 using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
public class MultilingualE5Embedding : IDisposable
{
private readonly InferenceSession _session;
private const int EmbeddingSize = 384;
private const int MaxSeqLen = 128;
// ======================
// 删掉所有单例代码!!!
// ======================
public MultilingualE5Embedding()
{
string modelPath = Path.Combine(
AppContext.BaseDirectory,
"MLModels",
"multilingual-e5-small",
"model.onnx"
);
var options = new SessionOptions();
options.AppendExecutionProvider_CPU(0);
options.IntraOpNumThreads = 1;
_session = new InferenceSession(modelPath, options);
}
public float[] Encode(string text)
{
if (string.IsNullOrWhiteSpace(text))
return new float[EmbeddingSize];
string input = $"query: {text.Trim()}";
long[] inputIds;
long[] attentionMask;
long[] tokenTypeIds;
EncodeInput(input, out inputIds, out attentionMask, out tokenTypeIds);
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("input_ids", ToTensor(inputIds)),
NamedOnnxValue.CreateFromTensor("attention_mask", ToTensor(attentionMask)),
NamedOnnxValue.CreateFromTensor("token_type_ids", ToTensor(tokenTypeIds))
};
using var results = _session.Run(inputs);
var lastHidden = results[0].AsTensor<float>();
float[] embedding = new float[EmbeddingSize];
for (int i = 0; i < EmbeddingSize; i++)
embedding[i] = lastHidden[0, 0, i];
return embedding;
}
private void EncodeInput(string text, out long[] inputIds, out long[] attentionMask, out long[] tokenTypeIds)
{
List<long> ids = new List<long> { 0 };
foreach (char c in text)
ids.Add(CharToId(c));
ids.Add(2);
while (ids.Count < MaxSeqLen)
ids.Add(1);
if (ids.Count > MaxSeqLen)
ids = ids.Take(MaxSeqLen).ToList();
inputIds = ids.ToArray();
attentionMask = inputIds.Select(i => i != 1 ? 1L : 0L).ToArray();
tokenTypeIds = new long[MaxSeqLen];
}
private long CharToId(char c)
{
if (c >= 32 && c <= 126) return c + 100;
return 3;
}
private DenseTensor<long> ToTensor(long[] array)
{
return new DenseTensor<long>(array, new[] { 1, array.Length });
}
public void Dispose() => _session?.Dispose();
}
// 向量工具类
public static class VectorHelper
{
public static byte[] Serialize(float[] vector)
{
byte[] bytes = new byte[vector.Length * 4];
Buffer.BlockCopy(vector, 0, bytes, 0, bytes.Length);
return bytes;
}
public static float[] Deserialize(byte[] bytes)
{
float[] vector = new float[bytes.Length / 4];
Buffer.BlockCopy(bytes, 0, vector, 0, bytes.Length);
return vector;
}
public static float CosineSimilarity(float[] a, float[] b)
{
if (a == null || b == null || a.Length != b.Length) return 0;
float dot = 0, magA = 0, magB = 0;
for (int i = 0; i < a.Length; i++)
{
dot += a[i] * b[i];
magA += a[i] * a[i];
magB += b[i] * b[i];
}
return dot / (float)Math.Sqrt(magA * magB);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ML.Tokenizers;
using System.IO;
using System;
using System.Collections.Generic;
namespace 智能客服.Services
{
public static class VectorHelper
{
// float[] → byte[] 存入数据库
public static byte[] Serialize(float[] vector)
{
byte[] bytes = new byte[vector.Length * 4];
Buffer.BlockCopy(vector, 0, bytes, 0, bytes.Length);
return bytes;
}
// byte[] → float[] 从数据库读取
public static float[] Deserialize(byte[] bytes)
{
float[] vector = new float[bytes.Length / 4];
Buffer.BlockCopy(bytes, 0, vector, 0, bytes.Length);
return vector;
}
// 余弦相似度
public static float CosineSimilarity(float[] a, float[] b)
{
if (a == null || b == null || a.Length != b.Length) return 0;
float dot = 0, magA = 0, magB = 0;
for (int i = 0; i < a.Length; i++)
{
dot += a[i] * b[i];
magA += a[i] * a[i];
magB += b[i] * b[i];
}
return dot / ((float)Math.Sqrt(magA) * (float)Math.Sqrt(magB));
}
}
}
使用示例:
// 为问题生成向量(使用 "passage:" 前缀)
using var embed = new MultilingualE5Embedding();
float[] vec = embed.Encode(question); // 自动带 query: 前缀
byte[] blob = VectorHelper.Serialize(vec);
相关推荐
- openclaw 国内性价比最优推荐:豆包 4.0(字节)、DeepSeek-V4(深度求索)、通义千问 Qwen 3.6(阿里)。
- 合规中转 / 聚合平台 或 企业级 Azure 通道
- OpenClaw 多模型自动切换 + 双龙虾智能体一体化完整配置
- OpenClaw 多龙虾智能体(CEO 虾 + 营销虾)完整部署方案
- 直接复制粘贴到 OpenClaw 生产环境的多模型自动切换配置
- OpenClaw 原生支持全自动模型切换(智能路由 + 故障降级)
- 散户必备、最精简、可直接落地的「股票龙虾(OpenClaw)技能包(Skills)清单」
- 股票龙虾必备技能skills清单-openclaw 自动炒股
- 智能客服应答策略设计
- 清华大学OpenClaw研究报告

售前咨询专员