woocommerce做零售網(wǎng)站網(wǎng)站排名推廣工具
Embedding介紹
??????? Embedding是向量的意思,向量可以理解為平面坐標(biāo)中的一個(gè)坐標(biāo)點(diǎn)(x,y),在編程領(lǐng)域,一個(gè)二維向量就是一個(gè)大小為float類型的數(shù)組。也可以用三維坐標(biāo)系中的向量表示一個(gè)空間中的點(diǎn)。在機(jī)器學(xué)習(xí)中,向量通常用于表示數(shù)據(jù)的特征。
?????? 向量分?jǐn)?shù)越高,代表位置越接近,匹配的數(shù)據(jù)越相似。
?
文本向量化
????? 而文本向量化是指,利用大模型可以吧一個(gè)字,一個(gè)詞或一段話映射為一個(gè)多維向量,比如我們可以直接在LangChain4j中調(diào)用向量模型來(lái)對(duì)一句話進(jìn)行向量化。
案例代碼:
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)過(guò)大模型向量化之后,得到一個(gè)長(zhǎng)度為1536的float數(shù)組。注意,1536是固定的,不會(huì)隨著句子長(zhǎng)度而變化。
??????? 那么我們通過(guò)這種向量模型得到一句話對(duì)應(yīng)的向量有什么作用呢?非常有用,因?yàn)槲覀兛梢曰谙蛄縼?lái)判斷兩句話之間的相似度,進(jìn)而可以實(shí)現(xiàn)超越elasticsearch的高級(jí)搜索。
?
向量相似度
??????? 我們可以使用余弦相似度來(lái)計(jì)算向量的相似度,余弦相似度是一種用于衡量向量之間相似度的指標(biāo),可以用于文本向量之間的相似度,在計(jì)算機(jī)中用來(lái)判斷文本之間的距離。
例如:
"機(jī)器學(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 {// 計(jì)算兩個(gè)向量的點(diǎn)積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;}// 計(jì)算向量的模public static double vectorMagnitude(double[] vector) {double magnitude = 0;for (double component : vector) {magnitude += Math.pow(component, 2);}return Math.sqrt(magnitude);}// 計(jì)算余弦相似度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) {// 示例向量//機(jī)器學(xué)習(xí)double[] vectorA = {1, 2, 3};//深度學(xué)習(xí)double[] vectorB = {2,3,3};//英雄聯(lián)盟double[] vectorC = {9,1,3};// 計(jì)算余弦相似度//機(jī)器學(xué)習(xí)”與“深度學(xué)習(xí)”的距離:double similarityAB = cosineSimilarity(vectorA, vectorB);System.out.println("Cosine SimilarityAB: " + similarityAB);//"機(jī)器學(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é)論:“機(jī)器學(xué)習(xí)”與“深度學(xué)習(xí)”兩個(gè)文本之間的余弦相似度更高,表示它們?cè)谡Z(yǔ)義上更相似。
?
文本向量算法
文本向量算法是指將文本數(shù)據(jù)轉(zhuǎn)化為向量表示的具體算法,通常包括以下幾個(gè)步驟:
- 分詞:將文本劃分成一個(gè)個(gè)單詞或短語(yǔ)。
- 構(gòu)建詞匯表:將分詞后的單詞或短語(yǔ)建立詞匯表,并為每個(gè)單詞或短語(yǔ)賦予一個(gè)唯一的編號(hào)。
- 計(jì)算詞嵌入:使用預(yù)訓(xùn)練的模型或自行訓(xùn)練的模型,將每個(gè)單詞或短語(yǔ)映射到向量空間中。
- 計(jì)算文本嵌入:將文本中每個(gè)單詞或短語(yǔ)的向量表示取平均或加權(quán)平均,得到整個(gè)文本的向量表示。
????????常見(jiàn)的文本向量算法包括 Word2Vec、GloVe、FastText 等。這些算法通過(guò)預(yù)訓(xùn)練或自行訓(xùn)練的方式,將單詞或短語(yǔ)映射到低維向量空間中,從而能夠在計(jì)算機(jī)中方便地處理文本數(shù)據(jù)。當(dāng)然這中間最關(guān)鍵的就是向量模型,因?yàn)橄蛄渴撬傻?#xff0c;向量模型也是經(jīng)過(guò)大量機(jī)器學(xué)習(xí)訓(xùn)練之后產(chǎn)生的,向量模型效果越好,就表示它對(duì)于自然語(yǔ)言理解的程度越好,同時(shí)也就表示它生成出來(lái)的向量越準(zhǔn)確,越能反映出語(yǔ)義的相似度。
?
文本向量用途
文本嵌入用于測(cè)量文本字符串的相關(guān)性,通常用于:
- 搜索(結(jié)果按與查詢字符串的相關(guān)性排序)
- 聚類(其中文本字符串按相似性分組)
- 推薦(推薦具有相關(guān)文本字符串的項(xiàng)目)
- 異常檢測(cè)(識(shí)別出相關(guān)性很小的異常值)
- 多樣性測(cè)量(分析相似性分布)
- 分類(其中文本字符串按其最相似的標(biāo)簽分類)
?
向量數(shù)據(jù)庫(kù)
LangChain4j支持的向量數(shù)據(jù)庫(kù):
向量數(shù)據(jù)庫(kù)名稱 | 保存 | 過(guò)濾 | 刪除 |
---|---|---|---|
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ù)庫(kù),它有20個(gè)實(shí)現(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也開(kāi)始支持面向Ai的向量數(shù)據(jù)庫(kù)了。
?
案例實(shí)現(xiàn)
下面案例就以redis來(lái)演示對(duì)于向量的增刪改查
引入redis依賴
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-redis</artifactId><version>${langchain4j.version}</version>
</dependency>
然后需要注意的是,普通的Redis是不支持向量存儲(chǔ)和查詢的,需要額外的redisearch模塊,我這邊是直接使用docker來(lái)運(yùn)行一個(gè)帶有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("機(jī)器學(xué)習(xí)");TextSegment textSegment2 = TextSegment.textSegment("深度學(xué)習(xí)");TextSegment textSegment3 = TextSegment.textSegment("英雄聯(lián)盟");// 生成向量Response<Embedding> embed1 = embeddingModel.embed("機(jī)器學(xué)習(xí)");Response<Embedding> embed2 = embeddingModel.embed("深度學(xué)習(xí)");Response<Embedding> embed3 = embeddingModel.embed("英雄聯(lián)盟");// 存儲(chǔ)向量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() + ",分?jǐn)?shù)為:" + embeddingMatch.score());}}
}
代碼執(zhí)行結(jié)果為
深度學(xué)習(xí),分?jǐn)?shù)為:0.94541862607
機(jī)器學(xué)習(xí),分?jǐn)?shù)為:0.943170130253
英雄聯(lián)盟,分?jǐn)?shù)為:0.9012748003005
????????從這就更容易看出向量的好處,能夠基于向量快速的得到和文本相似的文本,這樣就能非常適合用來(lái)做RAG,也就是檢索增強(qiáng)生成。
?
?
?
?