昨天我們已經先把題目的向量生出來了,今天來正式加入向量搜尋。
# views.py
@app.route('/search')
def search():
...
query = request.args.get(search_type, '').lower()
if query:
...
if search_type == 'q':
# 呼叫向量搜尋函式,傳入使用者輸入內容,top_n=最相關的題目數
vector_results = vector_search(query, top_n=10)
for result in vector_results:
...
})
...
return render_template(
...
)
from mistralai import Mistral
# 進行向量搜尋
def vector_search(query_text, top_n=5):
api_key = os.environ.get("MISTRAL_API_KEY")
client = Mistral(api_key=api_key)
model = "mistral-embed"
try:
# 生成查詢關鍵字的向量
query_embedding_response = client.embeddings.create(
model=model,
inputs=[query_text],
)
query_vector = query_embedding_response.data[0].embedding
except Exception as e:
print(f"生成查詢向量時發生錯誤: {e}")
return []
# 載入生成好的題目向量
questions_data = load_questions_with_embeddings()
if not questions_data:
return []
search_results = []
for item in questions_data:
if "embedding" in item:
item_vector = item["embedding"]
# 呼叫cosine函式,計算餘弦相似度
similarity_score = cosine(query_vector, item_vector)
search_results.append({
"item": item,
"score": similarity_score
})
# 依據相似度分數進行排序,分數越高相似度越高
search_results.sort(key=lambda x: x["score"], reverse=True)
# 返回最相關的 top_n 個結果
return search_results[:top_n]
import numpy as np
def cosine(vec1, vec2):
vec1 = np.array(vec1)
vec2 = np.array(vec2)
# 避免分母為零
dot_product = np.dot(vec1, vec2)
norm_a = np.linalg.norm(vec1)
norm_b = np.linalg.norm(vec2)
if norm_a == 0 or norm_b == 0:
return 0.0
return dot_product / (norm_a * norm_b)
關係度的計算方式?
在 Mistral AI 裡,餘弦相似度、歐幾里德距離和內積是等效的。
關於餘弦相似度
餘弦相似度範圍從-1到1,-1代表兩個向量方向相反,1表示兩個向量方向完全相同,0通常表示兩向量之間獨立。
在題目後加上計算結果,測試一下。