用 ClickHouse 玩轉向量搜索

ChatGPT 火了,順帶着把向量數據庫也帶火了。各種向量數據庫如雨後春筍般的出現在了衆人眼前。

那 ClickHouse 能玩向量搜索嗎?

答案:那必須是可以啦, ClickHouse 可是能把數組玩出花的存在啊!!!

在 ClickHouse 中,可以使用浮點類型的數組保存向量

Array(Float32)

然後用內置的距離函數,得出兩組向量之間的相似度.

目前距離函數支持主流的餘弦相似度和歐幾里得距離:

#餘弦相似度
cosineDistance(vector1, vector2)
#歐幾里得距離
L2Distance(vector1, vector2)

接下來我用一個簡單示例演示:

  1. 準備一些測試文檔數據,利用 azure openai 的接口幫我們 Embedding 成向量
input_data = [
    "ClickHouse是一款高性能的列式數據庫,特別適合處理海量數據。",
    "它支持實時分析和查詢,可以在不影響性能的情況下輕鬆搞定大規模數據。",
    "ClickHouse的可擴展性強,可以處理PB級別的數據,而且性能表現非常優異。",
    "數據存儲和壓縮方面也非常高效,可支持多種數據格式。",
    "ClickHouse提供完整的SQL支持,方便用戶進行數據查詢和分析。",
    "它可以與各種數據源集成,包括Hadoop、Kafka、Elasticsearch等等。",
    "ClickHouse還支持自定義指標和聚合函數,可以根據用戶需求進行定製化操作。",
    "作爲一款開源免費的數據庫,ClickHouse的社區非常活躍,擁有強大的生態系統。",
    "它還提供了豐富的工具和插件,包括可視化工具、ETL工具等等,方便用戶進行數據分析和處理。",
    "總的來說,ClickHouse是一款非常優秀的數據庫產品,可以滿足各種數據處理和分析的需求。"
]
embeddings_data = []
for i in range(len(input_data)):
    data = openai.Embedding.create(input=input_data[i], engine=embedding_model).data[0]["embedding"]
    embeddings_data.append([i, input_data[i], data])
    # print(data)
  1. 建一張 MergeTree,用浮點數組保存向量數據
client = clickhouse_connect.get_client(host='ch9.nauu.com', username='default')
client.command('DROP TABLE IF EXISTS test_embedding_ch')
client.command(
    """
    CREATE TABLE test_embedding_ch
    (
        `key` UInt32,
        `content`String,
        `text_embedding` Array(Float32)
    )
    ENGINE = MergeTree
    ORDER BY key
    """)
result = client.query('DESCRIBE TABLE test_embedding_ch')
print (result.column_names[0:2])
print (result.result_columns[0:2])
client.insert('test_embedding_ch', embeddings_data, column_names=['key', 'content','text_embedding'])
  1. 將用戶提問同樣向量化
q = ""
while q != 'quit':
    q = input("請提問: ")
    if q!="quit":
        # print("q: "+q)
        data = openai.Embedding.create(input=q, engine=embedding_model).data[0]["embedding"]
        result = query(data)
        for i in range(len(result.result_rows)):
            print("no:{} {} score:{} ".format(result.result_rows[i][0],result.result_rows[i][1],result.result_rows[i][2]))

4. 利用距離函數,輕鬆通過 SQL 實現向量的相似度查詢

def query(d):
    sql = "SELECT key,content,L2Distance(text_embedding,{embeddings}) AS score FROM test_embedding_ch ORDER BY score ASC LIMIT 5".format(embeddings=d)
    print(sql)
    result = client.query(sql)
    return result

最終效果:

快去試一試吧 :)

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/k594BaTXMoYcnmvpzO3xDw