机器图纸文章标题搜索增强实现过程

打印 上一主题 下一主题

主题 829|帖子 829|积分 2487

1. 为什么需要使用搜索增强技术

  点击睁开

  • 机器图纸标题搜索的挑战

    • 机器图纸标题通常包罗专业术语、缩写和特定格式(如“土豆分拣机 DWG-001 不锈钢”)。
    • 用户查询可能含糊或表述不同(如“马铃薯筛选机”),传统搜索难以匹配语义相似的标题。
    • 标题信息有限,传统搜索轻易遗漏相干图纸或返回无关结果。

  • 搜索增强的上风

    • 语义理解:通过大模型天生语义嵌入向量,理解标题和查询的深层含义,支持含糊匹配和语义相干性排序。

      • 示例:用户搜索“土豆分拣机”,传统搜索只能匹配标题中包罗“土豆分拣机”的图纸;增强搜索可匹配语义相似的标题,如“马铃薯筛选机”,因为 AI 模型能够理解“土豆”和“马铃薯”是同义词,“分拣”和“筛选”是近义词。

    • 多维度匹配:结合标题中的专业术语和元数据(如质料、尺寸),提升搜索的准确性和全面性。
    • 高效索引:使用向量存储(如 Redis)支持快速的相似度搜索,满足实时性需求。
    • 用户体验提升:返回更相干、更精准的图纸标题结果,减少用户反复调解查询的成本。

1.1 体验

微信小程序名称 极客共享 输入搜索内容 有没有土豆分拣机
  点击睁开

1.2 与传统全文检索(Elasticsearch)的对比

  点击睁开维度传统全文检索(Elasticsearch)搜索增强(基于语义向量)技术原理基于倒排索引和关键词匹配,依靠分词和词频统计(如 BM25)。基于大模型天生语义嵌入向量,使用向量相似度(如余弦相似度)匹配。语义理解仅匹配关键词,缺乏语义理解。理解标题和查询的语义,支持含糊匹配和同义词匹配。查询灵活性用户查询需与标题关键词高度一致,否则结果不准确。支持含糊查询和不同表述的匹配(如“土豆分拣机”匹配“马铃薯筛选机”)。专业术语处理依靠分词器,专业术语可能被错误切分(如“土豆分拣机”被切为“土豆”和“分拣机”)。通过预训练模型理解专业术语和同义词的语义,减少分词错误。结果相干性基于词频和位置排序,可能返回无关结果。基于语义相似度排序,结果更相干。实时性与性能倒排索引查询速度快,但语义匹配需额外插件(如 Elasticsearch KNN)。向量搜索需高效索引(如 RedisSearch),实时性稍逊但可优化。适用场景得当关键词明白、标题格式标准化的场景。得当标题复杂、查询含糊或需语义理解的场景。机器图纸标题搜索示例查询“土豆分拣机”,仅匹配标题中包罗“土豆分拣机”的图纸,遗漏“马铃薯筛选机”。查询“土豆分拣机”,可匹配语义相似的标题,如“马铃薯筛选机”,因为 AI 模型理解“土豆”和“马铃薯”、“分拣”和“筛选”是同义词。

  • 总结

    • 传统全文检索(Elasticsearch)得当关键词明白、标题格式标准化的场景,但对机器图纸标题的语义理解能力有限,轻易遗漏相干结果(如“马铃薯筛选机”)。
    • 搜索增强通过语义向量匹配,解决了含糊查询、专业术语处理和同义词匹配的问题,特殊得当机器图纸标题搜索的复杂场景。

1.3 搜索增强的含义


  • 搜索增强的定义

    • 搜索增强是指通过引入语义理解、向量嵌入等技术,改进传统搜索的范围性,提升搜索结果的相干性和准确性。
    • 在机器图纸标题搜索中,搜索增强通过大模型(如 Sentence-Transformers)将标题文本转化为语义向量,支持基于语义的相似度匹配,而不但仅依靠关键词匹配。

  • 核心上风

    • 理解查询和标题的语义,支持含糊匹配、同义词匹配和跨语言匹配。
    • 结合图纸标题的上下文,提供更相干的搜索结果。
    • 提升用户体验,减少因查询表述差别导致的搜索失败。

2. 系统架构设计

2.1 团体架构


  • 前端:微信小程序 极客共享  用户输入机器图纸标题相干的查询(如“有没有土豆分拣机”)。
  • 后端

    • .NET Core 应用程序,负责处理用户请求、调用 Python API 存储和搜索向量。
    • Python API 服务,提供机器图纸标题的语义嵌入功能。

  • 向量存储

    • 使用 Redis 存储机器图纸标题的语义向量,支持快速索引和相似度匹配。

  • 数据流

    • 机器图纸标题信息 -> .NET Core -> Python API -> 返回向量 -> 存储到 Redis。
    • 用户查询 -> .NET Core -> Python API -> 天生查询向量 -> Redis 搜索 -> 返回结果。

2. 实现步骤

2.1 机器图纸标题向量天生与存储

2.1.1 准备机器图纸标题数据

  点击睁开

2.1.2 .NET Core 调用 Python API 天生向量


  • 目标: 将标题文本和元数据发送到 Python API,获取语义嵌入向量,大模型是bge-large-zh-noinstruct_embeddings):
    Python向量天生范例
  1. from FlagEmbedding import FlagModel
  2. import pandas as pd
  3. import numpy as np
  4. from datasets import Dataset
  5. from scipy.spatial import distance
  6. import datetime
  7. import configparser
  8. import pymysql  
  9. model = None
  10. def getModel():
  11.     global model
  12.     if model is None:
  13.         model = FlagModel("./model",
  14.                     query_instruction_for_retrieval="Represent this sentence for searching relevant passages:",
  15.                     use_fp16=True)
  16.     return model
  17. #获取向量
  18. def getFlagEmbedding(title):
  19.     global model
  20.     model = getModel()
  21.     embedding = model.encode(title)
  22.     return embedding
  23.   
复制代码
   .NET Core调用天生接口(其实就是普通的api请求)
  1. /// <summary>
  2. /// 获取向量
  3. /// </summary>
  4. /// <param name="keyword"></param>
  5. /// <returns></returns>
  6. public async Task<double[]> GetFlagEmbedding(string keyword)
  7. {
  8.      var vector = new double[] { };
  9.      vector = null;
  10.      try
  11.      {
  12.          var req = new
  13.          {
  14.              action = "getFlagEmbedding",
  15.              keyword
  16.          };
  17.          var content = new StringContent(
  18.                         JsonSerializer.Serialize(req)
  19.                         , Encoding.UTF8, "application/json");
  20.          var response = await _client.PostAsync(ConfigHelp.FlagSerachUrl, content);
  21.          if (response.IsSuccessStatusCode)
  22.          {
  23.              var result = await response.Content.ReadAsStringAsync();
  24.              var data = JsonSerializer.Deserialize<GetFlagEmbeddingRoot>(result);
  25.              if (data.op)
  26.              {
  27.                  vector = data.msg.Split(',').Select(double.Parse).ToArray();
  28.              }
  29.          }
  30.      }
  31.      catch (Exception ex)
  32.      {
  33.          LogUtils.Error("GetFlagEmbedding ", ex);
  34.      }
  35.      return vector;
  36. }
复制代码
2.1.3 存储向量到 Redis


  • 目标:将天生的向量存储到 Redis,支持后续的相似度搜索。
    搜索数据
  1.    public class RedisVectorHelp
  2.    {
  3.        private readonly IDatabase _db;
  4.        private string _freefix;
  5.        private string _indexName;
  6.        private SearchCommands ft;
  7.        public RedisVectorHelp(string freefix,string redisConnectionString,int dbNum=0)
  8.        {
  9.            var redis = ConnectionMultiplexer.Connect(redisConnectionString);
  10.            _db = redis.GetDatabase(dbNum);
  11.            _freefix = freefix;
  12.            _indexName = _freefix + "_index";
  13.            ft = new SearchCommands(_db, null);
  14.        }
  15.        /// <summary>
  16.        /// 创建索引
  17.        /// </summary>
  18.        public void CreateFt()
  19.        {
  20.            var list = ft._List();
  21.            var indexList = list.Select(result => result.ToString()).ToArray();
  22.            //判断是否存在索引
  23.            if (indexList.Contains(_indexName))
  24.            {
  25.                Console.WriteLine("Index already exists.");
  26.                return;
  27.            }
  28.            ft.Create(_indexName,
  29. new FTCreateParams()
  30.      .On(IndexDataType.HASH)
  31.      .Prefix(_freefix + ":"),
  32. new Schema()
  33.      .AddTextField("id")
  34.      .AddVectorField("vector",
  35.      VectorField.VectorAlgo.FLAT,
  36.          new Dictionary<string, object>
  37.          {
  38.              ["TYPE"] = "FLOAT32",
  39.              ["DIM"] = 1024,
  40.              ["DISTANCE_METRIC"] = "COSINE"
  41.          })
  42.      );
  43.        }
  44.        /// <summary>
  45.        /// 存储向量
  46.        /// </summary>
  47.        /// <param name="id"></param>
  48.        /// <param name="vector"></param>
  49.        public void StoreVectorData(string id, float[] vector)
  50.        {
  51.            // 构造键名
  52.            var key = $"{_freefix}:{id}";
  53.            VectorDom dom = new VectorDom
  54.            {
  55.                id = id,
  56.                vector = vector
  57.            };
  58.            byte[] vectorBinary = vector.SelectMany(f => BitConverter.GetBytes(f)).ToArray();
  59.            _db.HashSet(key, "id", dom.id);
  60.            _db.HashSet(key, "vector", vectorBinary);
  61.        }
  62.        /// <summary>
  63.        /// 向量搜索
  64.        /// </summary>
  65.        /// <param name="queryVector"></param>
  66.        /// <param name="topK"></param>
  67.        public List<string> SearchSimilarVectors(float[] queryVector, int topK = 50)
  68.        {
  69.            byte[] vectorQueryBinary = queryVector.SelectMany(f => BitConverter.GetBytes(f)).ToArray();
  70.            //十六进制字符串
  71.            //string vectorQueryBinaryStr = BitConverter.ToString(vectorQueryBinary).Replace("-", "");
  72.            Query q = new Query($"*=>[KNN {topK} @vector $vec as score]");
  73.            q.SortBy = "score";
  74.            q.AddParam("vec", vectorQueryBinary);
  75.            q.ReturnFields("id", "vector");
  76.            q.Limit(0, topK);
  77.            q.Dialect(2);
  78.            var obj = ft.Search(_indexName, q);
  79.            var docList = obj.Documents;
  80.            var list = new List<string>();
  81.            foreach (var doc in docList)
  82.            {
  83.                list.Add(doc["id"]);
  84.            }
  85.            return list;
  86.        }
  87.    }
  88.    public class VectorDom
  89.    {
  90.        public string id { get; set; }
  91.        public float[] vector { get; set; }
  92.    }
复制代码
2.2.1 使用查询向量在 Redis 中搜索

    RedisVector核心操作类
  1. var searchVector = await GetFlagEmbedding(keyword);
  2. if (searchVector != null)
  3. {
  4.      var queryVector = Array.ConvertAll(searchVector, x => (float)x);
  5.      var temp = bykcsjRVHelp.SearchSimilarVectors(queryVector, 30);
  6.      foreach (var id in temp)
  7.      {
  8.          if (!ids.Contains(id))
  9.          {
  10.              ids.Add(id);
  11.          }
  12.      }
  13. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表