昨天我們讓 Gemini 學會了「呼叫函式」。
AI 不只是回答問題,還能根據需求決定要不要使用外部工具。
今天再往前一步。
假設有兩段程式碼:
function calculateTotal(price, quantity) {
return price * quantity;
}
以及:
function getAmount(unitPrice, count) {
return unitPrice * count;
}
雖然函式名稱和變數名稱完全不同,但我們一眼就知道,它們做的事情很接近。
那麼問題來了:
程式要怎麼判斷兩段文字「意思很像」?
答案就是今天要認識的 Embedding。
可以先把 Embedding 想成一台「文字轉數字」的機器。
把一段文字交給模型:
"calculate total price"
它會轉換成一串數字,也就是所謂的「向量(Vector)」。
[0.12, -0.08, 0.31, ...]
這些數字本身沒有必要閱讀,真正重要的是:
意思接近的內容,轉換後的向量通常也會比較接近。
因此我們就可以利用向量來做:
今天先不碰複雜的向量資料庫,也不做完整 RAG。
只完成一個最小實驗:
程式碼 A
↓
Embedding
↓
向量 A
程式碼 B
↓
Embedding
↓
向量 B
向量 A + 向量 B
↓
Cosine Similarity
↓
相似度
前幾天的專案可以直接延續。
今天只需要安裝計算 Cosine Similarity 的套件:
npm install compute-cosine-similarity
.env 一樣使用前幾天的 API Key:
GEMINI_API_KEY=你的_API_Key
建立:
day13-embedding.js
完整程式如下:
import "dotenv/config";
import { GoogleGenAI } from "@google/genai";
import cosineSimilarity from "compute-cosine-similarity";
const ai = new GoogleGenAI({});
const codes = [
`function calculateTotal(price, quantity) {
return price * quantity;
}`,
`function getAmount(unitPrice, count) {
return unitPrice * count;
}`,
`function sendEmail(to, subject) {
console.log(to, subject);
}`,
];
const response = await ai.models.embedContent({
model: "gemini-embedding-001",
contents: codes,
config: {
taskType: "SEMANTIC_SIMILARITY",
},
});
const embeddings = response.embeddings.map(e => e.values);
for (let i = 0; i < embeddings.length; i++) {
for (let j = i + 1; j < embeddings.length; j++) {
const score = cosineSimilarity(
embeddings[i],
embeddings[j]
);
console.log(
`Code ${i + 1} vs Code ${j + 1}: ${score.toFixed(4)}`
);
}
}
執行:
node day13-embedding.js
就會看到類似:
Code 1 vs Code 2: 0.9537
Code 1 vs Code 3: 0.7881
Code 2 vs Code 3: 0.7791
實際數值會依模型與輸入內容不同而變化,所以不要把某個固定分數當成標準答案。
我們真正要觀察的是:
calculateTotal ↔ getAmount
兩段程式碼的用途接近,因此相似度會比較高。
而:
calculateTotal ↔ sendEmail
功能完全不同,相似度通常就會比較低。
這就是 Embedding 最直觀的用途。
今天第一次看到:
cosineSimilarity(vectorA, vectorB)
可以先不用背公式。
簡單理解成:
兩個向量的方向越接近,代表內容在語意上越接近。
Google 官方文件也直接使用 SEMANTIC_SIMILARITY 搭配 Cosine Similarity 來比較文字的語意接近程度。
所以整個流程其實很單純:
文字
↓
Embedding
↓
向量
↓
Cosine Similarity
↓
相似度
原本看起來像 AI 魔法的「理解相似內容」,到了程式裡,其實已經變成可以計算的數字。
假設今天不是只有三段程式碼,而是有 1,000 個:
sample01.js
sample02.js
sample03.js
...
sample1000.js
使用者輸入:
「幫我找和非同步 API 呼叫最像的程式碼」
就可以把查詢內容也轉成向量,再和資料庫裡的向量比較。
使用者問題
↓
Embedding
↓
查詢向量
↓
比較大量程式碼向量
↓
找出最接近的結果
這就是「語意搜尋(Semantic Search)」的基本概念。
而當這個概念再搭配文件切分、向量儲存、檢索結果與 Gemini 生成回答,就會進一步走向大家常聽到的 RAG。
不過今天先不急。
先把「文字 → 向量 → 相似度」這條路走通比較重要。
回頭看這一週:
Day 08 Gemini API
↓
Day 09 Streaming
↓
Day 10 JSON
↓
Day 11 Schema
↓
Day 12 Function Calling
↓
Day 13 Embedding
我們可以發現:
Gemini API 不只是「問問題拿答案」。
它可以生成文字、串接工具,也可以把內容轉換成程式能夠進一步處理的資料。
這次的 Embedding,就是從「AI 回答問題」跨到「AI 成為程式的一部分」的重要一步。
明天 Day 14,就來做第二週總結,把這幾天學到的 API、Schema、Function Calling 與 Embedding 全部重新整理一次。
第二週,也差不多要收尾了。