@@ -198,7 +198,6 @@ public class AzureOpenAiChatClient implements ChatClient, StreamingChatClient {
|
||||
.map(ChatCompletions::getChoices)
|
||||
.flatMap(List::stream)
|
||||
.map(choice -> {
|
||||
System.out.println(choice.getDelta());
|
||||
var content = (choice.getDelta() != null) ? choice.getDelta().getContent() : null;
|
||||
var generation = new Generation(content).withChoiceMetadata(generateChoiceMetadata(choice));
|
||||
return new ChatResponse(List.of(generation));
|
||||
|
||||
@@ -40,7 +40,7 @@ public class BedrockCohereEmbeddingClient extends AbstractEmbeddingClient {
|
||||
|
||||
private final CohereEmbeddingBedrockApi embeddingApi;
|
||||
|
||||
private CohereEmbeddingRequest.InputType inputType = CohereEmbeddingRequest.InputType.search_document;
|
||||
private CohereEmbeddingRequest.InputType inputType = CohereEmbeddingRequest.InputType.SEARCH_DOCUMENT;
|
||||
|
||||
private CohereEmbeddingRequest.Truncate truncate = CohereEmbeddingRequest.Truncate.NONE;
|
||||
|
||||
|
||||
@@ -90,19 +90,19 @@ public class CohereEmbeddingBedrockApi extends
|
||||
* In search use-cases, use search_document when you encode documents for embeddings that you store in a
|
||||
* vector database.
|
||||
*/
|
||||
search_document,
|
||||
@JsonProperty("search_document") SEARCH_DOCUMENT,
|
||||
/**
|
||||
* Use search_query when querying your vector DB to find relevant documents.
|
||||
*/
|
||||
search_query,
|
||||
@JsonProperty("search_query") SEARCH_QUERY,
|
||||
/**
|
||||
* Use classification when using embeddings as an input to a text classifier.
|
||||
*/
|
||||
classification,
|
||||
@JsonProperty("classification") CLASSIFICATION,
|
||||
/**
|
||||
* Use clustering to cluster the embeddings.
|
||||
*/
|
||||
clustering
|
||||
@JsonProperty("clustering") CLUSTERING
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -150,11 +150,11 @@ public class Llama2ChatBedrockApi extends
|
||||
/**
|
||||
* The model has finished generating text for the input prompt.
|
||||
*/
|
||||
stop,
|
||||
@JsonProperty("stop") STOP,
|
||||
/**
|
||||
* The response was truncated because of the response length you set.
|
||||
*/
|
||||
length
|
||||
@JsonProperty("length") LENGTH
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class CohereEmbeddingBedrockApiIT {
|
||||
|
||||
CohereEmbeddingRequest request = new CohereEmbeddingRequest(
|
||||
List.of("I like to eat apples", "I like to eat oranges"),
|
||||
CohereEmbeddingRequest.InputType.search_document, CohereEmbeddingRequest.Truncate.NONE);
|
||||
CohereEmbeddingRequest.InputType.SEARCH_DOCUMENT, CohereEmbeddingRequest.Truncate.NONE);
|
||||
|
||||
CohereEmbeddingResponse response = api.embedding(request);
|
||||
|
||||
|
||||
@@ -138,11 +138,11 @@ public class OllamaChatClient implements ChatClient, StreamingChatClient {
|
||||
|
||||
switch (message.getMessageType()) {
|
||||
case USER:
|
||||
return Role.user;
|
||||
return Role.USER;
|
||||
case ASSISTANT:
|
||||
return Role.assistant;
|
||||
return Role.ASSISTANT;
|
||||
case SYSTEM:
|
||||
return Role.system;
|
||||
return Role.SYSTEM;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported message type: " + message.getMessageType());
|
||||
}
|
||||
|
||||
@@ -349,15 +349,15 @@ public class OllamaApi {
|
||||
/**
|
||||
* System message type used as instructions to the model.
|
||||
*/
|
||||
system,
|
||||
@JsonProperty("system") SYSTEM,
|
||||
/**
|
||||
* User message type.
|
||||
*/
|
||||
user,
|
||||
@JsonProperty("user") USER,
|
||||
/**
|
||||
* Assistant message type. Usually the response from the model.
|
||||
*/
|
||||
assistant;
|
||||
@JsonProperty("assistant") ASSISTANT;
|
||||
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ public class OllamaApi {
|
||||
*
|
||||
* @param model The model name used for completion.
|
||||
* @param createdAt When the request was made.
|
||||
* @param message The response {@link Message} with {@link Message.Role#assistant}.
|
||||
* @param message The response {@link Message} with {@link Message.Role#ASSISTANT}.
|
||||
* @param done Whether this is the final response. For streaming response only the
|
||||
* last message is marked as done. If true, this response may be followed by another
|
||||
* response with the following, additional fields: context, prompt_eval_count,
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
@SpringBootTest
|
||||
@Disabled("For manual smoke testing only.")
|
||||
|
||||
@@ -87,7 +87,7 @@ public class OllamaApiIT {
|
||||
|
||||
var request = ChatRequest.builder("orca-mini")
|
||||
.withStream(false)
|
||||
.withMessages(List.of(Message.builder(Role.user)
|
||||
.withMessages(List.of(Message.builder(Role.USER)
|
||||
.withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?")
|
||||
.build()))
|
||||
.withOptions(OllamaOptions.create().withTemperature(0.9f))
|
||||
@@ -100,7 +100,7 @@ public class OllamaApiIT {
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.model()).isEqualTo(response.model());
|
||||
assertThat(response.done()).isTrue();
|
||||
assertThat(response.message().role()).isEqualTo(Role.assistant);
|
||||
assertThat(response.message().role()).isEqualTo(Role.ASSISTANT);
|
||||
assertThat(response.message().content()).contains("Sofia");
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class OllamaApiIT {
|
||||
|
||||
var request = ChatRequest.builder("orca-mini")
|
||||
.withStream(true)
|
||||
.withMessages(List.of(Message.builder(Role.user)
|
||||
.withMessages(List.of(Message.builder(Role.USER)
|
||||
.withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?")
|
||||
.build()))
|
||||
.withOptions(OllamaOptions.create().withTemperature(0.9f).toMap())
|
||||
|
||||
@@ -100,7 +100,7 @@ public class OpenAiChatClient implements ChatClient, StreamingChatClient {
|
||||
|
||||
List<ChatCompletionMessage> chatCompletionMessages = messages.stream()
|
||||
.map(m -> new ChatCompletionMessage(m.getContent(),
|
||||
ChatCompletionMessage.Role.valueOf(m.getMessageType().getValue())))
|
||||
ChatCompletionMessage.Role.valueOf(m.getMessageType().name())))
|
||||
.toList();
|
||||
|
||||
ResponseEntity<ChatCompletion> completionEntity = this.openAiApi
|
||||
@@ -132,7 +132,7 @@ public class OpenAiChatClient implements ChatClient, StreamingChatClient {
|
||||
|
||||
List<ChatCompletionMessage> chatCompletionMessages = messages.stream()
|
||||
.map(m -> new ChatCompletionMessage(m.getContent(),
|
||||
ChatCompletionMessage.Role.valueOf(m.getMessageType().getValue())))
|
||||
ChatCompletionMessage.Role.valueOf(m.getMessageType().name())))
|
||||
.toList();
|
||||
|
||||
Flux<OpenAiApi.ChatCompletionChunk> completionChunks = this.openAiApi
|
||||
|
||||
@@ -163,7 +163,7 @@ public class OpenAiApi {
|
||||
* @param function function definition.
|
||||
*/
|
||||
public FunctionTool(Function function) {
|
||||
this(Type.function, function);
|
||||
this(Type.FUNCTION, function);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +173,7 @@ public class OpenAiApi {
|
||||
/**
|
||||
* Function tool type.
|
||||
*/
|
||||
function
|
||||
@JsonProperty("function") FUNCTION
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,10 +347,10 @@ public class OpenAiApi {
|
||||
* @param role The role of the messages author. Could be one of the {@link Role} types.
|
||||
* @param name An optional name for the participant. Provides the model information to differentiate between
|
||||
* participants of the same role.
|
||||
* @param toolCallId Tool call that this message is responding to. Only applicable for the {@link Role#tool} role
|
||||
* @param toolCallId Tool call that this message is responding to. Only applicable for the {@link Role#TOOL} role
|
||||
* and null otherwise.
|
||||
* @param toolCalls The tool calls generated by the model, such as function calls. Applicable only for
|
||||
* {@link Role#assistant} role and null otherwise.
|
||||
* {@link Role#ASSISTANT} role and null otherwise.
|
||||
* @param functionCall Deprecated and replaced by tool_calls. The name and arguments of a function that should be
|
||||
* called, as generated by the model.
|
||||
*/
|
||||
@@ -379,19 +379,19 @@ public class OpenAiApi {
|
||||
/**
|
||||
* System message.
|
||||
*/
|
||||
system,
|
||||
@JsonProperty("system") SYSTEM,
|
||||
/**
|
||||
* User message.
|
||||
*/
|
||||
user,
|
||||
@JsonProperty("user") USER,
|
||||
/**
|
||||
* Assistant message.
|
||||
*/
|
||||
assistant,
|
||||
@JsonProperty("assistant") ASSISTANT,
|
||||
/**
|
||||
* Tool message.
|
||||
*/
|
||||
tool
|
||||
@JsonProperty("tool") TOOL
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,23 +429,23 @@ public class OpenAiApi {
|
||||
/**
|
||||
* The model hit a natural stop point or a provided stop sequence.
|
||||
*/
|
||||
stop,
|
||||
@JsonProperty("stop") STOP,
|
||||
/**
|
||||
* The maximum number of tokens specified in the request was reached.
|
||||
*/
|
||||
length,
|
||||
@JsonProperty("length") LENGTH,
|
||||
/**
|
||||
* The content was omitted due to a flag from our content filters.
|
||||
*/
|
||||
content_filter,
|
||||
@JsonProperty("content_filter") CONTENT_FILTER,
|
||||
/**
|
||||
* The model called a tool.
|
||||
*/
|
||||
tool_calls,
|
||||
@JsonProperty("tool_calls") TOOL_CALLS,
|
||||
/**
|
||||
* (deprecated) The model called a function.
|
||||
*/
|
||||
function_call
|
||||
@JsonProperty("function_call") FUNCTION_CALL
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,7 @@ public class BedrockCohereEmbeddingProperties {
|
||||
* retrieval. In this case, embed your corpus with the search_document type and
|
||||
* embedded queries with type search_query type.
|
||||
*/
|
||||
private InputType inputType = InputType.search_document;
|
||||
private InputType inputType = InputType.SEARCH_DOCUMENT;
|
||||
|
||||
/**
|
||||
* Specifies how the API handles inputs longer than the maximum token length.
|
||||
|
||||
@@ -33,7 +33,7 @@ public class PgVectorStoreProperties {
|
||||
|
||||
private PgIndexType indexType = PgIndexType.HNSW;
|
||||
|
||||
private PgDistanceType distanceType = PgDistanceType.CosineDistance;
|
||||
private PgDistanceType distanceType = PgDistanceType.COSINE_DISTANCE;
|
||||
|
||||
private boolean removeExistingVectorStoreTable = false;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public class BedrockCohereEmbeddingAutoConfigurationIT {
|
||||
"spring.ai.bedrock.aws.secret-key=" + System.getenv("AWS_SECRET_ACCESS_KEY"),
|
||||
"spring.ai.bedrock.aws.region=" + Region.US_EAST_1.id(),
|
||||
"spring.ai.bedrock.cohere.embedding.model=" + CohereEmbeddingModel.COHERE_EMBED_MULTILINGUAL_V1.id(),
|
||||
"spring.ai.bedrock.cohere.embedding.inputType=search_document",
|
||||
"spring.ai.bedrock.cohere.embedding.inputType=SEARCH_DOCUMENT",
|
||||
"spring.ai.bedrock.cohere.embedding.truncate=NONE")
|
||||
.withConfiguration(AutoConfigurations.of(BedrockCohereEmbeddingAutoConfiguration.class));
|
||||
|
||||
@@ -91,7 +91,7 @@ public class BedrockCohereEmbeddingAutoConfigurationIT {
|
||||
"spring.ai.bedrock.aws.access-key=ACCESS_KEY", "spring.ai.bedrock.aws.secret-key=SECRET_KEY",
|
||||
"spring.ai.bedrock.aws.region=" + Region.EU_CENTRAL_1.id(),
|
||||
"spring.ai.bedrock.cohere.embedding.model=MODEL_XYZ",
|
||||
"spring.ai.bedrock.cohere.embedding.inputType=classification",
|
||||
"spring.ai.bedrock.cohere.embedding.inputType=CLASSIFICATION",
|
||||
"spring.ai.bedrock.cohere.embedding.truncate=RIGHT")
|
||||
.withConfiguration(AutoConfigurations.of(BedrockCohereEmbeddingAutoConfiguration.class))
|
||||
.run(context -> {
|
||||
@@ -102,7 +102,7 @@ public class BedrockCohereEmbeddingAutoConfigurationIT {
|
||||
assertThat(awsProperties.getRegion()).isEqualTo(Region.EU_CENTRAL_1.id());
|
||||
assertThat(properties.getModel()).isEqualTo("MODEL_XYZ");
|
||||
|
||||
assertThat(properties.getInputType()).isEqualTo(InputType.classification);
|
||||
assertThat(properties.getInputType()).isEqualTo(InputType.CLASSIFICATION);
|
||||
assertThat(properties.getTruncate()).isEqualTo(CohereEmbeddingRequest.Truncate.RIGHT);
|
||||
|
||||
assertThat(awsProperties.getAccessKey()).isEqualTo("ACCESS_KEY");
|
||||
|
||||
@@ -72,7 +72,7 @@ public class PgVectorStoreAutoConfigurationIT {
|
||||
.withConfiguration(AutoConfigurations.of(PgVectorStoreAutoConfiguration.class,
|
||||
JdbcTemplateAutoConfiguration.class, DataSourceAutoConfiguration.class))
|
||||
.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.pgvector.distanceType=CosineDistance",
|
||||
.withPropertyValues("spring.ai.vectorstore.pgvector.distanceType=COSINE_DISTANCE",
|
||||
// JdbcTemplate configuration
|
||||
String.format("spring.datasource.url=jdbc:postgresql://%s:%d/%s", postgresContainer.getHost(),
|
||||
postgresContainer.getMappedPort(5432), "postgres"),
|
||||
|
||||
@@ -33,7 +33,7 @@ public class PgVectorStorePropertiesTests {
|
||||
public void defaultValues() {
|
||||
var props = new PgVectorStoreProperties();
|
||||
assertThat(props.getDimensions()).isEqualTo(PgVectorStore.INVALID_EMBEDDING_DIMENSION);
|
||||
assertThat(props.getDistanceType()).isEqualTo(PgDistanceType.CosineDistance);
|
||||
assertThat(props.getDistanceType()).isEqualTo(PgDistanceType.COSINE_DISTANCE);
|
||||
assertThat(props.getIndexType()).isEqualTo(PgIndexType.HNSW);
|
||||
assertThat(props.isRemoveExistingVectorStoreTable()).isFalse();
|
||||
}
|
||||
@@ -43,12 +43,12 @@ public class PgVectorStorePropertiesTests {
|
||||
var props = new PgVectorStoreProperties();
|
||||
|
||||
props.setDimensions(1536);
|
||||
props.setDistanceType(PgDistanceType.EuclideanDistance);
|
||||
props.setDistanceType(PgDistanceType.EUCLIDEAN_DISTANCE);
|
||||
props.setIndexType(PgIndexType.IVFFLAT);
|
||||
props.setRemoveExistingVectorStoreTable(true);
|
||||
|
||||
assertThat(props.getDimensions()).isEqualTo(1536);
|
||||
assertThat(props.getDistanceType()).isEqualTo(PgDistanceType.EuclideanDistance);
|
||||
assertThat(props.getDistanceType()).isEqualTo(PgDistanceType.EUCLIDEAN_DISTANCE);
|
||||
assertThat(props.getIndexType()).isEqualTo(PgIndexType.IVFFLAT);
|
||||
assertThat(props.isRemoveExistingVectorStoreTable()).isTrue();
|
||||
}
|
||||
|
||||
@@ -196,9 +196,19 @@ public class ChromaApi {
|
||||
|
||||
public enum Include {
|
||||
|
||||
metadatas, documents, distances, embeddings;
|
||||
@JsonProperty("metadatas")
|
||||
METADATAS,
|
||||
|
||||
public static final List<Include> all = List.of(metadatas, documents, distances, embeddings);
|
||||
@JsonProperty("documents")
|
||||
DOCUMENTS,
|
||||
|
||||
@JsonProperty("distances")
|
||||
DISTANCES,
|
||||
|
||||
@JsonProperty("embeddings")
|
||||
EMBEDDINGS;
|
||||
|
||||
public static final List<Include> all = List.of(METADATAS, DOCUMENTS, DISTANCES, EMBEDDINGS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -116,17 +116,17 @@ public class PgVectorStore implements VectorStore, InitializingBean {
|
||||
// embeddings), use inner product for best performance.
|
||||
// The Sentence transformers are NOT normalized:
|
||||
// https://github.com/UKPLab/sentence-transformers/issues/233
|
||||
EuclideanDistance("<->", "vector_l2_ops",
|
||||
EUCLIDEAN_DISTANCE("<->", "vector_l2_ops",
|
||||
"SELECT *, embedding <-> ? AS distance FROM %s WHERE embedding <-> ? < ? %s ORDER BY distance LIMIT ? "),
|
||||
|
||||
// NOTE: works only if If vectors are normalized to length 1 (like OpenAI
|
||||
// embeddings), use inner product for best performance.
|
||||
// The Sentence transformers are NOT normalized:
|
||||
// https://github.com/UKPLab/sentence-transformers/issues/233
|
||||
NegativeInnerProduct("<#>", "vector_ip_ops",
|
||||
NEGATIVE_INNER_PRODUCT("<#>", "vector_ip_ops",
|
||||
"SELECT *, (1 + (embedding <#> ?)) AS distance FROM %s WHERE (1 + (embedding <#> ?)) < ? %s ORDER BY distance LIMIT ? "),
|
||||
|
||||
CosineDistance("<=>", "vector_cosine_ops",
|
||||
COSINE_DISTANCE("<=>", "vector_cosine_ops",
|
||||
"SELECT *, embedding <=> ? AS distance FROM %s WHERE embedding <=> ? < ? %s ORDER BY distance LIMIT ? ");
|
||||
|
||||
public final String operator;
|
||||
@@ -197,12 +197,12 @@ public class PgVectorStore implements VectorStore, InitializingBean {
|
||||
}
|
||||
|
||||
public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingClient embeddingClient) {
|
||||
this(jdbcTemplate, embeddingClient, INVALID_EMBEDDING_DIMENSION, PgVectorStore.PgDistanceType.CosineDistance,
|
||||
this(jdbcTemplate, embeddingClient, INVALID_EMBEDDING_DIMENSION, PgVectorStore.PgDistanceType.COSINE_DISTANCE,
|
||||
false, PgIndexType.NONE);
|
||||
}
|
||||
|
||||
public PgVectorStore(JdbcTemplate jdbcTemplate, EmbeddingClient embeddingClient, int dimensions) {
|
||||
this(jdbcTemplate, embeddingClient, dimensions, PgVectorStore.PgDistanceType.CosineDistance, false,
|
||||
this(jdbcTemplate, embeddingClient, dimensions, PgVectorStore.PgDistanceType.COSINE_DISTANCE, false,
|
||||
PgIndexType.NONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public class PgVectorStoreIT {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(TestApplication.class)
|
||||
.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=CosineDistance",
|
||||
.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=COSINE_DISTANCE",
|
||||
|
||||
// JdbcTemplate configuration
|
||||
String.format("app.datasource.url=jdbc:postgresql://%s:%d/%s", postgresContainer.getHost(),
|
||||
@@ -101,7 +101,7 @@ public class PgVectorStoreIT {
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "CosineDistance", "EuclideanDistance", "NegativeInnerProduct" })
|
||||
@ValueSource(strings = { "COSINE_DISTANCE", "EUCLIDEAN_DISTANCE", "NEGATIVE_INNER_PRODUCT" })
|
||||
public void addAndSearch(String distanceType) {
|
||||
contextRunner.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=" + distanceType)
|
||||
.run(context -> {
|
||||
@@ -130,7 +130,7 @@ public class PgVectorStoreIT {
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "CosineDistance", "EuclideanDistance", "NegativeInnerProduct" })
|
||||
@ValueSource(strings = { "COSINE_DISTANCE", "EUCLIDEAN_DISTANCE", "NEGATIVE_INNER_PRODUCT" })
|
||||
public void searchWithFilters(String distanceType) {
|
||||
|
||||
contextRunner.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=" + distanceType)
|
||||
@@ -204,7 +204,7 @@ public class PgVectorStoreIT {
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "CosineDistance", "EuclideanDistance", "NegativeInnerProduct" })
|
||||
@ValueSource(strings = { "COSINE_DISTANCE", "EUCLIDEAN_DISTANCE", "NEGATIVE_INNER_PRODUCT" })
|
||||
public void documentUpdate(String distanceType) {
|
||||
|
||||
contextRunner.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=" + distanceType)
|
||||
@@ -244,8 +244,8 @@ public class PgVectorStoreIT {
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0} : {displayName} ")
|
||||
@ValueSource(strings = { "CosineDistance", "EuclideanDistance", "NegativeInnerProduct" })
|
||||
// @ValueSource(strings = { "CosineDistance" })
|
||||
@ValueSource(strings = { "COSINE_DISTANCE", "EUCLIDEAN_DISTANCE", "NEGATIVE_INNER_PRODUCT" })
|
||||
// @ValueSource(strings = { "COSINE_DISTANCE" })
|
||||
public void searchWithThreshold(String distanceType) {
|
||||
|
||||
contextRunner.withPropertyValues("test.spring.ai.vectorstore.pgvector.distanceType=" + distanceType)
|
||||
|
||||
Reference in New Issue
Block a user