It was good that you added support for deserializing anyOf types because there's also a case for that in the OpenAI API (although they have not adjusted the spec appropriately yet - https://github.com/openai/openai-openapi/pull/99).
When you create an embedding, OpenAI can return the embedding as a list of floats or as a base64-encoded string. So the schema looks like this:
Embedding:
type: object
description: |
Represents an embedding vector returned by embedding endpoint.
properties:
index:
type: integer
description: The index of the embedding in the list of embeddings.
embedding:
title: EmbeddingVector
description: |
The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](https://platform.openai.com/docs/guides/embeddings).
oneOf:
- type: string
description: The embedding vector as a base64-encoded string.
- type: array
description: The embedding vector as a list of floats.
items:
type: number
object:
type: string
description: The object type, which is always "embedding".
required:
- index
- object
- embedding
The previous implementation was generating the following JSON converter:
class _EmbeddingVectorConverter
implements JsonConverter<EmbeddingVector, Object?> {
const _EmbeddingVectorConverter();
@override
EmbeddingVector fromJson(Object? data) {
if (data is String) {
return EmbeddingVector.string(data);
}
if (data is List<double>) {
return EmbeddingVector.arrayNumber(data);
}
throw Exception('Unexpected value for EmbeddingVector: $data');
}
@override
Object? toJson(EmbeddingVector data) {
return switch (data) {
_UnionEmbeddingVectorString(value: final v) => v,
_UnionEmbeddingVectorArrayNumber(value: final v) => v,
};
}
}
However, it failed to deserialize a list of floats because data is of type List<dynamic>, which is not a List<double>.
This PR changes the condition to check that data is a List and all the items of the list are of the specified type.
This is how the new JSON converter looks like:
class _EmbeddingVectorConverter
implements JsonConverter<EmbeddingVector, Object?> {
const _EmbeddingVectorConverter();
@override
EmbeddingVector fromJson(Object? data) {
if (data is String) {
return EmbeddingVector.string(data);
}
if (data is List && data.every((item) => item is double)) {
return EmbeddingVector.arrayNumber(data.cast());
}
throw Exception('Unexpected value for EmbeddingVector: $data');
}
@override
Object? toJson(EmbeddingVector data) {
return switch (data) {
_UnionEmbeddingVectorString(value: final v) => v,
_UnionEmbeddingVectorArrayNumber(value: final v) => v,
};
}
}
It was good that you added support for deserializing anyOf types because there's also a case for that in the OpenAI API (although they have not adjusted the spec appropriately yet - https://github.com/openai/openai-openapi/pull/99).
When you create an embedding, OpenAI can return the embedding as a list of floats or as a base64-encoded string. So the schema looks like this:
The previous implementation was generating the following JSON converter:
However, it failed to deserialize a list of floats because
data
is of typeList<dynamic>
, which is not aList<double>
.This PR changes the condition to check that
data
is aList
and all the items of the list are of the specified type.This is how the new JSON converter looks like:
cc @walsha2