woocommerce做零售網(wǎng)站網(wǎng)站排名推廣工具
Embedding介紹
??????? Embedding是向量的意思,向量可以理解為平面坐標(biāo)中的一個坐標(biāo)點(x,y),在編程領(lǐng)域,一個二維向量就是一個大小為float類型的數(shù)組。也可以用三維坐標(biāo)系中的向量表示一個空間中的點。在機器學(xué)習(xí)中,向量通常用于表示數(shù)據(jù)的特征。
?????? 向量分數(shù)越高,代表位置越接近,匹配的數(shù)據(jù)越相似。
?
文本向量化
????? 而文本向量化是指,利用大模型可以吧一個字,一個詞或一段話映射為一個多維向量,比如我們可以直接在LangChain4j中調(diào)用向量模型來對一句話進行向量化。
案例代碼:
public class EmbeddingDemo{public static void main(String[] args) {OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();Response<Embedding> embed = embeddingModel.embed("你好,我叫g(shù)orgor");System.out.println(embed.content().toString());System.out.println(embed.content().vector().length);}
}
? 代碼執(zhí)行結(jié)果為:
Embedding { vector = [-0.019351093, -0.02137422...] }
1536
從結(jié)果可以知道“你好,我叫g(shù)orgor”這句話經(jīng)過大模型向量化之后,得到一個長度為1536的float數(shù)組。注意,1536是固定的,不會隨著句子長度而變化。
??????? 那么我們通過這種向量模型得到一句話對應(yīng)的向量有什么作用呢?非常有用,因為我們可以基于向量來判斷兩句話之間的相似度,進而可以實現(xiàn)超越elasticsearch的高級搜索。
?
向量相似度
??????? 我們可以使用余弦相似度來計算向量的相似度,余弦相似度是一種用于衡量向量之間相似度的指標(biāo),可以用于文本向量之間的相似度,在計算機中用來判斷文本之間的距離。
例如:
"機器學(xué)習(xí)"表示為 [1,2,3]
"深度學(xué)習(xí)"表示為[2,3,3]
"英雄聯(lián)盟"表示為[9,1,3]
?????? 示例代碼(余弦相似度):
package com.gorgor.langchain4j.embedding;import java.util.*;public class CosineSimilarity {// 計算兩個向量的點積public static double dotProduct(double[] vectorA, double[] vectorB) {double dotProduct = 0;for (int i = 0; i < vectorA.length; i++) {dotProduct += vectorA[i] * vectorB[i];}return dotProduct;}// 計算向量的模public static double vectorMagnitude(double[] vector) {double magnitude = 0;for (double component : vector) {magnitude += Math.pow(component, 2);}return Math.sqrt(magnitude);}// 計算余弦相似度public static double cosineSimilarity(double[] vectorA, double[] vectorB) {double dotProduct = dotProduct(vectorA, vectorB);double magnitudeA = vectorMagnitude(vectorA);double magnitudeB = vectorMagnitude(vectorB);if (magnitudeA == 0 || magnitudeB == 0) {return 0; // 避免除以零} else {return dotProduct / (magnitudeA * magnitudeB);}}public static void main(String[] args) {// 示例向量//機器學(xué)習(xí)double[] vectorA = {1, 2, 3};//深度學(xué)習(xí)double[] vectorB = {2,3,3};//英雄聯(lián)盟double[] vectorC = {9,1,3};// 計算余弦相似度//機器學(xué)習(xí)”與“深度學(xué)習(xí)”的距離:double similarityAB = cosineSimilarity(vectorA, vectorB);System.out.println("Cosine SimilarityAB: " + similarityAB);//"機器學(xué)習(xí)”與“英雄聯(lián)盟“的距離":double similarityAC = cosineSimilarity(vectorA, vectorC);System.out.println("Cosine SimilarityAB: " + similarityAC);}
}
??? 代碼執(zhí)行結(jié)果:
Cosine SimilarityAB: 0.9686648999069225
Cosine SimilarityAB: 0.5603318146805258
? 結(jié)論:“機器學(xué)習(xí)”與“深度學(xué)習(xí)”兩個文本之間的余弦相似度更高,表示它們在語義上更相似。
?
文本向量算法
文本向量算法是指將文本數(shù)據(jù)轉(zhuǎn)化為向量表示的具體算法,通常包括以下幾個步驟:
- 分詞:將文本劃分成一個個單詞或短語。
- 構(gòu)建詞匯表:將分詞后的單詞或短語建立詞匯表,并為每個單詞或短語賦予一個唯一的編號。
- 計算詞嵌入:使用預(yù)訓(xùn)練的模型或自行訓(xùn)練的模型,將每個單詞或短語映射到向量空間中。
- 計算文本嵌入:將文本中每個單詞或短語的向量表示取平均或加權(quán)平均,得到整個文本的向量表示。
????????常見的文本向量算法包括 Word2Vec、GloVe、FastText 等。這些算法通過預(yù)訓(xùn)練或自行訓(xùn)練的方式,將單詞或短語映射到低維向量空間中,從而能夠在計算機中方便地處理文本數(shù)據(jù)。當(dāng)然這中間最關(guān)鍵的就是向量模型,因為向量是它生成的,向量模型也是經(jīng)過大量機器學(xué)習(xí)訓(xùn)練之后產(chǎn)生的,向量模型效果越好,就表示它對于自然語言理解的程度越好,同時也就表示它生成出來的向量越準(zhǔn)確,越能反映出語義的相似度。
?
文本向量用途
文本嵌入用于測量文本字符串的相關(guān)性,通常用于:
- 搜索(結(jié)果按與查詢字符串的相關(guān)性排序)
- 聚類(其中文本字符串按相似性分組)
- 推薦(推薦具有相關(guān)文本字符串的項目)
- 異常檢測(識別出相關(guān)性很小的異常值)
- 多樣性測量(分析相似性分布)
- 分類(其中文本字符串按其最相似的標(biāo)簽分類)
?
向量數(shù)據(jù)庫
LangChain4j支持的向量數(shù)據(jù)庫:
向量數(shù)據(jù)庫名稱 | 保存 | 過濾 | 刪除 |
---|---|---|---|
In-memory | ? | ? | ? |
Astra DB | ? | ? | ? |
Azure AI Search | ? | ? | ? |
Azure CosmosDB Mongo vCore | ? | ? | ? |
Azure CosmosDB NoSQL | ? | ? | ? |
Cassandra | ? | ? | ? |
Chroma | ? | ? | ? |
Elasticsearch | ? | ? | ? |
Infinispan | ? | ? | ? |
Milvus | ? | ? | ? |
MongoDB Atlas | ? | ? | ? |
Neo4j | ? | ? | ? |
OpenSearch | ? | ? | ? |
PGVector | ? | ? | ? |
Pinecone | ? | ? | ? |
Qdrant | ? | ? | ? |
Redis | ? | ? | ? |
Vearch | ? | ? | ? |
Vespa | ? | ? | ? |
Weaviate | ? | ? | ? |
EmbeddingStore表示向量數(shù)據(jù)庫,它有20個實現(xiàn)類:
- AstraDbEmbeddingStore
- AzureAiSearchEmbeddingStore
- CassandraEmbeddingStore
- ChromaEmbeddingStore
- ElasticsearchEmbeddingStore
- InMemoryEmbeddingStore
- InfinispanEmbeddingStore
- MemoryIdEmbeddingStore
- MilvusEmbeddingStore
- MinimalEmbeddingStore
- MongoDbEmbeddingStore
- Neo4jEmbeddingStore
- OpenSearchEmbeddingStore
- PgVectorEmbeddingStore
- PineconeEmbeddingStore
- QdrantEmbeddingStore
- RedisEmbeddingStore
- VearchEmbeddingStore
- VespaEmbeddingStore
- WeaviateEmbeddingStore
其中我們熟悉的有Elasticsearch、MongoDb、Pg、Redis,令人驚喜的是MySQL 9.0也開始支持面向Ai的向量數(shù)據(jù)庫了。
?
案例實現(xiàn)
下面案例就以redis來演示對于向量的增刪改查
引入redis依賴
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-redis</artifactId><version>${langchain4j.version}</version>
</dependency>
然后需要注意的是,普通的Redis是不支持向量存儲和查詢的,需要額外的redisearch模塊,我這邊是直接使用docker來運行一個帶有redisearch模塊的redis容器的,命令為:
docker run -p 6379:6379 redis/redis-stack-server:latest
注意端口6379不要和你現(xiàn)有的Redis沖突了。
然后就可以使用以下代碼把向量存到redis中了:
public class EmbeddingDemo {public static void main(String[] args) {OpenAiEmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").build();RedisEmbeddingStore embeddingStore = RedisEmbeddingStore.builder().host("127.0.0.1").port(6379).dimension(1536).build();TextSegment textSegment1 = TextSegment.textSegment("機器學(xué)習(xí)");TextSegment textSegment2 = TextSegment.textSegment("深度學(xué)習(xí)");TextSegment textSegment3 = TextSegment.textSegment("英雄聯(lián)盟");// 生成向量Response<Embedding> embed1 = embeddingModel.embed("機器學(xué)習(xí)");Response<Embedding> embed2 = embeddingModel.embed("深度學(xué)習(xí)");Response<Embedding> embed3 = embeddingModel.embed("英雄聯(lián)盟");// 存儲向量embeddingStore.add(embed1.content(),textSegment1);embeddingStore.add(embed2.content(),textSegment2);embeddingStore.add(embed3.content(),textSegment3);// 生成向量Response<Embedding> embed = embeddingModel.embed("學(xué)習(xí)");// 查詢List<EmbeddingMatch<TextSegment>> result = embeddingStore.findRelevant(embed.content(), 5);for (EmbeddingMatch<TextSegment> embeddingMatch : result) {System.out.println(embeddingMatch.embedded().text() + ",分數(shù)為:" + embeddingMatch.score());}}
}
代碼執(zhí)行結(jié)果為
深度學(xué)習(xí),分數(shù)為:0.94541862607
機器學(xué)習(xí),分數(shù)為:0.943170130253
英雄聯(lián)盟,分數(shù)為:0.9012748003005
????????從這就更容易看出向量的好處,能夠基于向量快速的得到和文本相似的文本,這樣就能非常適合用來做RAG,也就是檢索增強生成。
?
?
?
?