关于使用PgVector相似度算法查询脚本的问题 返回

下面是C#的调用代码:
SugarDbContext.UsePgVector<SentenceVectorR>();
var jsonVector = $"'{SerializeHelper.SerializeObject(vector, true)}'";
var sql = @$"select sentence_id, sentence, vector <-> @vector as distance
from public.sentence_vector
where Abs(vector <-> @vector) < {maxDistance}
order by vector <-> @vector
limit {pageSize} offset {pageNo * pageSize}";
var parameters = new SugarParameter[]{
new SugarParameter("@vector", jsonVector)
};
var sentenceVectors = SugarDbContext.Ado.SqlQuery<SentenceVectorR>(sql, parameters);
return Task.FromResult(sentenceVectors);
UsePgVector的定义如下:
private static IDbConnection OpenDbConnection4Vector()
{
var dataSourceBuilder = new NpgsqlDataSourceBuilder("数据库连接串");
dataSourceBuilder.UseVector();
var dataSource = dataSourceBuilder.Build();
return dataSource.OpenConnection();
}
vector为float[]数组,当我直接使用向量的字符串表达(例如,'[0.1,0.2,0.3]')去代替@vector参数时,数据库脚本可以正常执行并返回正确的结果。
但是当我使用@vector参数执行时,报下面的错误:
Npgsql.PostgresException
HResult=0x80004005
Message=42883: operator does not exist: vector <-> text
POSITION: 38
Source=Npgsql
StackTrace:
在 Npgsql.Internal.NpgsqlConnector.<<ReadMessage>g__ReadMessageLong|233_0>d.MoveNext() 在 /_/src/Npgsql/Internal/NpgsqlConnector.cs 中: 第 1334 行
在 System.Threading.Tasks.ValueTask`1.get_Result() 在 /_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs 中: 第 800 行
在 Npgsql.NpgsqlDataReader.<NextResult>d__47.MoveNext() 在 /_/src/Npgsql/NpgsqlDataReader.cs 中: 第 451 行
在 Npgsql.NpgsqlDataReader.<NextResult>d__47.MoveNext() 在 /_/src/Npgsql/NpgsqlDataReader.cs 中: 第 609 行
在 Npgsql.NpgsqlDataReader.NextResult() 在 /_/src/Npgsql/NpgsqlDataReader.cs 中: 第 342 行
在 Npgsql.NpgsqlCommand.<ExecuteReader>d__124.MoveNext() 在 /_/src/Npgsql/NpgsqlCommand.cs 中: 第 1468 行
在 Npgsql.NpgsqlCommand.<ExecuteReader>d__124.MoveNext() 在 /_/src/Npgsql/NpgsqlCommand.cs 中: 第 1543 行
在 System.Threading.Tasks.ValueTask`1.get_Result() 在 /_/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ValueTask.cs 中: 第 800 行
在 Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior) 在 /_/src/Npgsql/NpgsqlCommand.cs 中: 第 1273 行
在 Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior) 在 /_/src/Npgsql/NpgsqlCommand.cs 中: 第 1253 行
在 SqlSugar.AdoProvider.GetDataReader(String sql, SugarParameter[] parameters)
在 SqlSugar.AdoProvider.SqlQuery[T,T2,T3,T4,T5,T6,T7](String sql, Object parameters)
在 SqlSugar.AdoProvider.SqlQuery[T](String sql, SugarParameter[] parameters)
在 amaSoGrain.Ai.Grains.AiGrain.SemanticSearchSentence(Single[] vector, Int32 mode, Single maxDistance, Int32 pageNo, Int32 pageSize) 在 D:\hwq\amaSmartTask\amaSoGrain.Ai\Grains\AiGrain.cs 中: 第 81 行
此异常最初是在此调用堆栈中引发的:
Npgsql.Internal.NpgsqlConnector.ReadMessage.__ReadMessageLong|233_0(Npgsql.Internal.NpgsqlConnector, bool, Npgsql.Internal.DataRowLoadingMode, bool, bool) (位于 NpgsqlConnector.cs 中)
System.Threading.Tasks.ValueTask<TResult>.Result.get() (位于 ValueTask.cs 中)
Npgsql.NpgsqlDataReader.NextResult(bool, bool, System.Threading.CancellationToken) (位于 NpgsqlDataReader.cs 中)
Npgsql.NpgsqlDataReader.NextResult(bool, bool, System.Threading.CancellationToken) (位于 NpgsqlDataReader.cs 中)
Npgsql.NpgsqlDataReader.NextResult() (位于 NpgsqlDataReader.cs 中)
Npgsql.NpgsqlCommand.ExecuteReader(System.Data.CommandBehavior, bool, System.Threading.CancellationToken) (位于 NpgsqlCommand.cs 中)
Npgsql.NpgsqlCommand.ExecuteReader(System.Data.CommandBehavior, bool, System.Threading.CancellationToken) (位于 NpgsqlCommand.cs 中)
System.Threading.Tasks.ValueTask<TResult>.Result.get() (位于 ValueTask.cs 中)
Npgsql.NpgsqlCommand.ExecuteReader(System.Data.CommandBehavior) (位于 NpgsqlCommand.cs 中)
Npgsql.NpgsqlCommand.ExecuteDbDataReader(System.Data.CommandBehavior) (位于 NpgsqlCommand.cs 中)
...
[调用堆栈已截断]
这是我使用参数的方式有问题吗?
谢谢!
热忱回答(11)
-
fate sta VIP0
2周前vector <-> text
这个很明显类型不一样
0 回复 -
fate sta VIP0
2周前SugarParameter你没有设置 isarray,我记得要传数组
0 回复 -
细雨牧童笛 VIP0
2周前@fate sta:我将参数的IsArray属性设置为true,代码如下:
var sql = @$"select sentence_id, sentence, vector <-> @vector as distance
from public.sentence_vector
where Abs(vector <-> @vector) < {maxDistance}
order by vector <-> @vector
limit {pageSize} offset {pageNo * pageSize}";
var parameters = new SugarParameter[]{
new SugarParameter("@vector", vector)
};
parameters[0].IsArray = true;
var sentenceVectors = SugarDbContext.Ado.SqlQuery<SentenceVectorR>(sql, parameters);
报的错误为以下内容:
Npgsql.PostgresException:“42883: operator does not exist: vector <-> real[]
不使用参数时,直接使用字符串方式是可以正确执行的
vector <-> '[0.1,0.2,0.3]'我将上述的字符串写入参数变量,感觉上应该可以的,结果就是不对。
我将错误信息发给ChatGPT,给我的建议是这样的:
var vector = new NpgsqlTypes.NpgsqlParameter("vector", NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Double);
vector.Value = new double[] {-0.007534305, 0.014973218};
代码修改如下:
parameters[0].IsArray = true;
parameters[0].DbType = System.Data.DbType.Double;
错误依然是:
Npgsql.PostgresException:“42883: operator does not exist: vector <-> real[]
请问有没有好的建议来解决这个问题?
谢谢!
0 回复 -
fate sta VIP0
2周前var embedding = new Vector(new float[] { 1, 1, 1 });
数组什么的都去掉改成直接用这个
0 回复 -
fate sta VIP0
2周前看ado.net用法
0 回复 -
细雨牧童笛 VIP0
2周前我参考PgVector.Dapper的示例代码,修改后可以执行查询并返回正确的结果:
SqlMapper.AddTypeHandler(new VectorTypeHandler());
var sql = @$"select sentence_id, sentence, embedding <-> @embedding as distance
from public.sentence_vector
where Abs(embedding <-> @embedding) < {maxDistance}
order by embedding <-> @embedding
limit {pageSize} offset {pageNo * pageSize}";
using (var conn = DbContextExt.GetDbConnection4Vector())
{
var embedding = new Vector(vector);
var sentenceVectors = conn.Query<SentenceVectorR>(sql, new { embedding }).AsList();
return Task.FromResult(sentenceVectors);
}
其中最关键的是:SqlMapper.AddTypeHandler(new VectorTypeHandler());
我看了VectorTypeHandler的代码,似乎和SqlSugar的自定义类型思路很相似,我曾经尝试过自定义类型
代码如下定义:public class PgVectorConverter : ISugarDataConverter
{
public SugarParameter ParameterConverter<T>(object value, int i)
{
var name = "@vectorP" + i;
if (value is not Vector vector)
throw new SmartException("传入数据不是向量实例!", false);
return new SugarParameter(name, vector.ToArray());
}
public T QueryConverter<T>(IDataRecord dr, int i)
{
var data = dr.GetValue(i);
if (data is Vector)
return (T)data;
return default;
}
}
在向量属性的标注为下面的方式:
[SugarColumn(ColumnName = "embedding", IsNullable = false, IsArray = true, ColumnDataType = "vector", SqlParameterDbType = typeof(PgVectorConverter))]
public Vector Embedding
修改后的查询代码如下:
SugarDbContext.UsePgVector<SentenceVectorR>();
var sql = @$"select sentence_id, sentence, embedding <-> @embedding as distance
from public.sentence_vector
where Abs(embedding <-> @embedding) < {maxDistance}
order by embedding <-> @embedding
limit {pageSize} offset {pageNo * pageSize}";
var embedding = new Vector(vector);
var parameters = new SugarParameter[]{
new SugarParameter("embedding", embedding)
};
var sentenceVectors = SugarDbContext.Ado.SqlQuery<SentenceVectorR>(sql, parameters);
return Task.FromResult(sentenceVectors);
运行后报的错误如下:
Can't write CLR type Pgvector.Vector with handler type TextHandler似乎很接近答案了,但又不知如何解决?
谢谢!0 回复 -
fate sta VIP0
2周前var dataSourceBuilder = new NpgsqlDataSourceBuilder("数据库连接串");
dataSourceBuilder.UseVector();
var dataSource = dataSourceBuilder.Build();
这个处理了吗
0 回复 -
fate sta VIP0
2周前实体也要用这个类型
0 回复 -
细雨牧童笛 VIP0
2周前@fate sta:参考了AI的回答:
conn.TypeMapper.MapComposite<Vector>("vector", new VectorHandler());
关键还是要定义Vector类型的Handler,PgVector.Dapper实现了这个功能:
SqlMapper.AddTypeHandler(new VectorTypeHandler());
所以可以正确执行,SqlSugar的自定义类型似乎与Hanlder的功能不一样,所以执行报错。
感谢大力支持,谢谢!
0 回复 -
fate sta VIP0
2周前@细雨牧童笛:解决了吗
0 回复 -
细雨牧童笛 VIP0
2周前@fate sta:目前使用
SqlMapper.AddTypeHandler(new VectorTypeHandler());
解决的,有时间再动态跟踪一下SqlSugar源码,这个问题花费的时间比较多,先放一放。
感谢!
0 回复