总部位于柏林的 Jina AI 刚刚发布了一系列新的嵌入模型,并宣称它们是“世界上第一个开源 8K 文本嵌入模型”,并且在质量上可与 OpenAI 的text-embedding-ada-002
相媲美。
前几天我写了很多关于嵌入的文章 – 如果您不熟悉它们是什么以及可以用它们做什么,我建议您先阅读它。
今天晚上,我为我的LLM工具构建并发布了一个新插件,它增加了对 Jina 的新嵌入模型的支持。
尝试 llm-embed-jina
该插件称为llm-embed-jina 。这是开始使用它的最快方法:
首先,如果尚未安装 LLM,请安装。您可以在 Mac 上使用Homebrew :
酿造安装llm
或pipx :
pipx 安装 llm
或者pip
:
pip安装llm
现在您可以安装llm-embed-jina
插件:
llm 安装 llm-embed-jina
llm install
命令可确保将其安装在正确的虚拟环境中,无论您如何安装 LLM 本身。
运行此命令以检查它是否添加了模型:
llm 嵌入模型
您应该看到如下输出:
ada-002 (aliases: ada, oai) jina-embeddings-v2-small-en jina-embeddings-v2-base-en jina-embeddings-v2-large-en
jina-emebddings-v2-large-en
模型尚不可用,但一旦 Jina 发布它就应该可以使用。我预计它会出现在huggingface.co/jinaai/jina-embeddings-v2-large-en (目前是404)。
现在您可以运行其中一个模型。 -small-en
模型是一个很好的起点,它只有 65MB 下载-base-en
模型是 275MB。
该模型将在您第一次尝试使用时下载。运行这个:
llm 嵌入-m jina-embeddings-v2-small-en -c '你好世界'
这将返回一个包含 512 个浮点数的 JSON 数组 – 字符串“Hello world”的嵌入向量。
如果将嵌入存储在某处然后使用它们进行比较,那么嵌入会更有趣。 llm embed-multi命令可以做到这一点。
将目录更改为您知道包含README.md
文件的文件夹(任何包含node_modules
文件夹的文件夹都可以)并运行以下命令:
llm 嵌入多自述文件 \ -m jina-embeddings-v2-small-en \ --文件。 ' **/README.md ' \ --数据库自述文件.db
这将创建一个名为readmes.db
的 SQLite 数据库,然后搜索当前目录和所有子目录中的每个README.md
文件,嵌入每个文件的内容并将结果存储在该数据库中。
这些嵌入将存在于一个名为readmes
的集合中。
如果您省略--database readmes.db
选项,集合将存储在隐藏在系统某处的默认 SQLite 数据库中。
完成此操作后,您可以对新集合运行语义相似性搜索,如下所示:
llm 类似的自述文件 -d readmes.db -c '实用函数'
当我在hmb-map目录中运行它时,我得到了这些:
{ “id” : “ node_modules/@maplibre/maplibre-gl-style-spec/src/feature_filter/README.md ” , “分数” : 0.7802185991017785 , “内容” : null , “元数据” : null } { “id” : “ node_modules/kind-of/README.md ” , “分数” : 0.7725600920927725 , “内容” : null , “元数据” : null } { “id” : “ node_modules/which/README.md ” , “分数” : 0.7645426557095619 , “内容” : null , “元数据” : null } { “id” : “ node_modules/@mapbox/point-geometry/README.md ” , “分数” : 0.7636548563018607 , “内容” : null , “元数据” : null } { “id” : “ node_modules/esbuild/README.md ” , “分数” : 0.7633325127194481 , “内容” : null , “元数据” : null } { “id” : “ node_modules/maplibre-gl/src/shaders/README.md ” , “分数” : 0.7614428292518743 , “内容” : null , “元数据” : null } { “id” : “ node_modules/minimist/README.md ” , “分数” : 0.7581314986768929 , “内容” : null , “元数据” : null } { “id” : “ node_modules/split-string/README.md ” , “分数” : 0.7563253351715924 , “内容” : null , “元数据” : null } { “id” : “ node_modules/assign-symbols/README.md ” , “分数” : 0.7555915219064293 , “内容” : null , “元数据” : null } { “id” : “ node_modules/maplibre-gl/build/README.md ” , “分数” : 0.754027372081506 , “内容” : null , “元数据” : null }
这些是与我输入的字符串相似度排名前十的结果。
您还可以传入集合中某个项目的 ID 来查看其他类似项目:
llm 类似自述文件 -d readmes.db node_modules/esbuild/README.md | jq.id
我把它通过管道| jq .id
仅返回 ID。我懂了:
"node_modules/@esbuild/darwin-arm64/README.md" "node_modules/rollup/README.md" "node_modules/assign-symbols/README.md" "node_modules/split-string/node_modules/extend-shallow/README.md" "node_modules/isobject/README.md" "node_modules/maplibre-gl/build/README.md" "node_modules/vite/README.md" "node_modules/nanoid/README.md" "node_modules/@mapbox/tiny-sdf/README.md" "node_modules/split-string/node_modules/is-extendable/README.md"
有关可以使用此工具执行的操作的更多详细信息,请参阅LLM 嵌入文档。
我是如何构建插件的
我用了大约 15 分钟构建了这个插件的第一个版本。又花了一个小时才解决了几个错误。
我从这个 cookiecutter 模板开始,然后粘贴 LLM 文档中有关编写嵌入模型插件的配方以及 Jina在其模型发布中提供的一些示例代码。这是他们的代码:
从Transformers导入AutoModel 来自numpy 。线性导入规范 cos_sim = lambda a , b : ( a @ b . T ) / (范数( a ) *范数( b )) 模型=汽车模型。 from_pretrained ( 'jinaai/jina-embeddings-v2-small-en' , trust_remote_code = True ) # 使用encode方法需要trust_remote_code 嵌入=模型。编码([ '今天天气怎么样?' , '今天天气怎么样?' ]) 打印( cos_sim (嵌入[ 0 ],嵌入[ 1 ]))
numpy
和cos_sim
位不是必需的,所以我忽略了它。
该插件的第一个工作版本是一个名为llm_embed_jina.py
的文件,如下所示:
导入LLM 从Transformers导入AutoModel @llm 。胡克普尔 def register_embedding_models (注册): 对于model_id ( “jina-embeddings-v2-small-en” , “jina-embeddings-v2-base-en” , “jina-embeddings-v2-large-en” , ): 注册( JinaEmbeddingModel ( model_id )) 类JinaEmbeddingModel ( llm . EmbeddingModel ): def __init__ ( self , model_id ): 自我。型号_id =型号_id 自我。 _模型=无 def embed_batch (自身,文本): 如果自己. _model是None : 自我。 _model =自动模型。 from_pretrained ( “jinaai/{}” 。格式( self . model_id ), trust_remote_code = True ) 结果=自我. _模型。编码(文本) return ( list ( map ( float , result )) for result in results )
确实没有太多内容。
register_embedding_models()
函数是一个插件钩子,LLM 调用它来注册所有嵌入模型。
JinaEmbeddingModel
是llm.EmbeddingModel
的子类。它只需要实现两件事:构造函数和embed_batch(self, texts)
方法。
AutoModel.from_pretrained()
由Hugging Face Transformers提供。它会在您第一次调用模型时下载并缓存模型。
该模型返回 numpy 数组,但 LLM 需要一个常规的 Python 浮点列表 – 这就是最后一个return
行所做的事情。
我发现了一些错误。该模型不喜欢使用生成器调用.encode(texts)
,因此我需要将其转换为列表。后来我发现超过8192个字符的文本可能会导致模型在某些情况下挂起,所以我添加了自己的截断。
该插件的当前版本(0.1.2)修复了这两个问题,如下所示:
导入LLM 从Transformers导入AutoModel 最大长度= 8192 @llm 。胡克普尔 def register_embedding_models (注册): 对于model_id ( “jina-embeddings-v2-small-en” , “jina-embeddings-v2-base-en” , “jina-embeddings-v2-large-en” , ): 注册( JinaEmbeddingModel ( model_id )) 类JinaEmbeddingModel ( llm . EmbeddingModel ): def __init__ ( self , model_id ): 自我。型号_id =型号_id 自我。 _模型=无 def embed_batch (自身,文本): 如果自己. _model是None : 自我。 _model =自动模型。 from_pretrained ( “jinaai/{}” 。格式( self . model_id ), trust_remote_code = True ) 结果=自我. _模型。编码([ text [: MAX_LENGTH ]用于文本中的文本]) return ( list ( map ( float , result )) for result in results )
我对它的快速整合感到非常满意 – 我认为这是一个强烈的信号,表明LLM 嵌入插件设计运行良好。
原文: http://simonwillison.net/2023/Oct/26/llm-embed-jina/#atom-everything