refactor(cache-qdrant-semantic): reuse qdrant-client serde payload conversion in tests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Yujong Lee 2026-09-21 21:48:27 +00:00
parent a4fda8f0d8
commit b0c1b86382
2 changed files with 10 additions and 66 deletions

View file

@ -12,50 +12,15 @@ use litellm_cache_qdrant_semantic::{
use litellm_cache_response::{
CacheEntry, CacheKeyInput, ResponseCache, ResponseCacheCodec, ResponseCacheRequest,
};
use qdrant_client::Payload;
use qdrant_client::{
Qdrant,
qdrant::{
self, CompressionRatio, Distance, PointId, QuantizationType, Struct, Value, VectorParams,
value::Kind,
},
qdrant::{self, CompressionRatio, Distance, PointId, QuantizationType, Value, VectorParams},
};
use serde_json::{Value as JsonValue, json};
use support::{FakeQdrant, FakeState, StoredPoint};
fn json_to_qdrant(value: JsonValue) -> Value {
let kind = match value {
JsonValue::Null => Kind::NullValue(0),
JsonValue::Bool(value) => Kind::BoolValue(value),
JsonValue::Number(value) => value
.as_i64()
.map(Kind::IntegerValue)
.or_else(|| value.as_f64().map(Kind::DoubleValue))
.unwrap(),
JsonValue::String(value) => Kind::StringValue(value),
JsonValue::Array(values) => Kind::ListValue(qdrant::ListValue {
values: values.into_iter().map(json_to_qdrant).collect(),
}),
JsonValue::Object(values) => Kind::StructValue(Struct {
fields: values
.into_iter()
.map(|(key, value)| (key, json_to_qdrant(value)))
.collect(),
}),
};
Value { kind: Some(kind) }
}
fn payload_from_json(value: JsonValue) -> HashMap<String, Value> {
value
.as_object()
.unwrap()
.clone()
.into_iter()
.map(|(key, value)| (key, json_to_qdrant(value)))
.collect()
}
#[derive(Clone)]
struct FixedEmbedder {
vectors: Arc<HashMap<String, Vec<f32>>>,
@ -278,10 +243,12 @@ async fn misses_and_payload_validation_are_safe() {
server.insert_point(StoredPoint {
id: Some(PointId::from(99_u64)),
vector: vec![1.0, 0.0],
payload: payload_from_json(json!({
payload: Payload::try_from(json!({
"litellm_cache_key": 99,
"response": "{}",
})),
}))
.unwrap()
.into(),
});
assert_eq!(
cache
@ -384,10 +351,9 @@ async fn response_payloads_decode_and_invalid_entries_fail() {
server.insert_point(StoredPoint {
id: Some(PointId::from(key.len() as u64)),
vector: vec![1.0, 0.0],
payload: payload
.into_iter()
.map(|(key, value)| (key, json_to_qdrant(value)))
.collect(),
payload: Payload::try_from(JsonValue::Object(payload))
.unwrap()
.into(),
});
}
assert_eq!(

View file

@ -11,9 +11,7 @@ use qdrant_client::qdrant::{
PointsOperationResponse, ScoredPoint, SearchPoints, SearchResponse, Value, Vector, Vectors,
collections_server::Collections,
points_server::{Points, PointsServer},
value::Kind,
};
use serde_json::Value as JsonValue;
use tokio::sync::oneshot;
use tokio_stream::wrappers::TcpListenerStream;
use tonic::{Request, Response, Status, transport::Server};
@ -25,26 +23,6 @@ pub struct StoredPoint {
pub payload: HashMap<String, Value>,
}
fn qdrant_value_to_json(value: Value) -> JsonValue {
match value.kind {
Some(Kind::NullValue(_)) | None => JsonValue::Null,
Some(Kind::DoubleValue(value)) => serde_json::json!(value),
Some(Kind::IntegerValue(value)) => serde_json::json!(value),
Some(Kind::StringValue(value)) => JsonValue::String(value),
Some(Kind::BoolValue(value)) => JsonValue::Bool(value),
Some(Kind::StructValue(value)) => JsonValue::Object(
value
.fields
.into_iter()
.map(|(key, value)| (key, qdrant_value_to_json(value)))
.collect(),
),
Some(Kind::ListValue(value)) => {
JsonValue::Array(value.values.into_iter().map(qdrant_value_to_json).collect())
}
}
}
#[derive(Default)]
pub struct FakeState {
pub collections: HashSet<String>,
@ -266,7 +244,7 @@ impl Points for FakeService {
.payload
.get(field)
.and_then(|value| {
let value = qdrant_value_to_json(value.clone());
let value: serde_json::Value = value.clone().into();
value
.as_str()
.map(str::to_owned)