|
|
@@ -54,9 +54,12 @@ bool SQLiteVecManager::initializeDatabase(int vectorDimension)
|
|
|
|
|
|
std::cout << "使用sqlite-vec扩展进行向量存储和搜索" << std::endl;
|
|
|
|
|
|
- // 创建vec0虚拟表
|
|
|
+ // 创建vec0虚拟表【这里只能用TEXT,不能用CHAR,不然创建表会报错】
|
|
|
std::string sql = R"(CREATE VIRTUAL TABLE IF NOT EXISTS image_features USING vec0(
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
+ food_id TEXT NOT NULL,
|
|
|
+ food_name TEXT UNIQUE NOT NULL,
|
|
|
+ image_name TEXT UNIQUE NOT NULL,
|
|
|
image_path TEXT UNIQUE NOT NULL,
|
|
|
feature_vector FLOAT[)" + std::to_string(vectorDimension) + "] distance_metric=cosine)";
|
|
|
|
|
|
@@ -71,9 +74,9 @@ bool SQLiteVecManager::initializeDatabase(int vectorDimension)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool SQLiteVecManager::addFeatureVector(const std::vector<float> & features, const std::string & imagePath)
|
|
|
+bool SQLiteVecManager::addFeatureVector(const std::vector<float>& features, const std::string& foodId, const std::string& foodName, const std::string& imageName, const std::string& imagePath)
|
|
|
{
|
|
|
- const char * sql = "INSERT INTO image_features(id, image_path, feature_vector) VALUES (?, ?, ?);";
|
|
|
+ const char * sql = "INSERT INTO image_features(food_id, food_name, image_name, image_path, feature_vector) VALUES (?, ?, ?, ?, ?);";
|
|
|
|
|
|
sqlite3_stmt * stmt;
|
|
|
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
|
|
@@ -85,12 +88,12 @@ bool SQLiteVecManager::addFeatureVector(const std::vector<float> & features, con
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- sqlite3_bind_int(stmt, 1, static_cast<int>(getFeatureCount() + 1));
|
|
|
- sqlite3_bind_text(stmt, 2, imagePath.c_str(), -1, SQLITE_STATIC);
|
|
|
-
|
|
|
- //std::string blobData = vectorToBlob(features);
|
|
|
- sqlite3_bind_blob(stmt, 3, features.data(), features.size() * sizeof(float), SQLITE_STATIC);
|
|
|
-
|
|
|
+ //sqlite3_bind_int(stmt, 1, static_cast<int>(getFeatureCount() + 1));
|
|
|
+ sqlite3_bind_text(stmt, 1, foodId.c_str(), -1, SQLITE_STATIC);
|
|
|
+ sqlite3_bind_text(stmt, 2, foodName.c_str(), -1, SQLITE_STATIC);
|
|
|
+ sqlite3_bind_text(stmt, 3, imageName.c_str(), -1, SQLITE_STATIC);
|
|
|
+ sqlite3_bind_text(stmt, 4, imagePath.c_str(), -1, SQLITE_STATIC);
|
|
|
+ sqlite3_bind_blob(stmt, 5, features.data(), features.size() * sizeof(float), SQLITE_STATIC);
|
|
|
rc = sqlite3_step(stmt);
|
|
|
|
|
|
if (rc != SQLITE_DONE) {
|
|
|
@@ -110,11 +113,9 @@ std::vector<std::pair<std::string, float>> SQLiteVecManager::searchSimilarVector
|
|
|
std::vector<std::pair<std::string, float>> results;
|
|
|
|
|
|
std::cout << "使用sqlite-vec扩展进行向量搜索" << std::endl;
|
|
|
- // 使用sqlite-vec的向量搜索功能
|
|
|
- std::string blobData = vectorToBlob(queryVector);
|
|
|
|
|
|
std::string sql =
|
|
|
- "SELECT image_path, distance "
|
|
|
+ "SELECT food_id, food_name, image_name, image_path, distance "
|
|
|
"FROM image_features "
|
|
|
"WHERE feature_vector MATCH ?1 "
|
|
|
"ORDER BY distance "
|
|
|
@@ -191,52 +192,6 @@ bool SQLiteVecManager::isEmpty() const
|
|
|
return getFeatureCount() == 0;
|
|
|
}
|
|
|
|
|
|
-std::string SQLiteVecManager::vectorToBlob(const std::vector<float> & vec)
|
|
|
-{
|
|
|
- std::string vecStr;
|
|
|
-
|
|
|
- for (std::size_t i = 0; i < vec.size(); i++) {
|
|
|
- vecStr += std::to_string(vec[i]);
|
|
|
- if (i != vec.size() - 1) {
|
|
|
- vecStr += ",";
|
|
|
- }
|
|
|
- }
|
|
|
- return vecStr;
|
|
|
-}
|
|
|
-
|
|
|
-std::vector<float> SQLiteVecManager::blobToVector(const std::string & blob)
|
|
|
-{
|
|
|
- const float * data = reinterpret_cast<const float *>(blob.data());
|
|
|
- size_t count = blob.size() / sizeof(float);
|
|
|
- return std::vector<float>(data, data + count);
|
|
|
-}
|
|
|
-
|
|
|
-float SQLiteVecManager::calculateCosineSimilarity(const std::vector<float> & vec1, const std::vector<float> & vec2)
|
|
|
-{
|
|
|
- if (vec1.size() != vec2.size() || vec1.empty())
|
|
|
- {
|
|
|
- return 0.0f;
|
|
|
- }
|
|
|
-
|
|
|
- float dotProduct = 0.0f;
|
|
|
- float norm1 = 0.0f;
|
|
|
- float norm2 = 0.0f;
|
|
|
-
|
|
|
- for (size_t i = 0; i < vec1.size(); ++i)
|
|
|
- {
|
|
|
- dotProduct += vec1[i] * vec2[i];
|
|
|
- norm1 += vec1[i] * vec1[i];
|
|
|
- norm2 += vec2[i] * vec2[i];
|
|
|
- }
|
|
|
-
|
|
|
- if (norm1 == 0.0f || norm2 == 0.0f)
|
|
|
- {
|
|
|
- return 0.0f;
|
|
|
- }
|
|
|
-
|
|
|
- return dotProduct / (std::sqrt(norm1) * std::sqrt(norm2));
|
|
|
-}
|
|
|
-
|
|
|
float SQLiteVecManager::distanceToSimilarity(float distance)
|
|
|
{
|
|
|
return 1.0f - distance;
|