Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
7294f7d
Add ElasticsearchAiSearchFilterExpressionConverter
JM-Lab Jan 9, 2024
c069db8
Add support for Elasticsearch vector store
JM-Lab Jan 9, 2024
8ff8b87
Add support for various vector functions provided by Elasticsearch
JM-Lab Jan 14, 2024
5d41978
Add support for Elasticsearch 8 vector store using the elasticsearch-…
JM-Lab Mar 3, 2024
011dfcb
Merge branch 'spring-projects:main' into elasticsearch-vector-store
JM-Lab Mar 3, 2024
8701ccc
Improve VertexAiGeminiAutoConfiguration to allow function calling por…
tzolov Mar 4, 2024
db383f8
Update README.md
markpollack Mar 4, 2024
7d04167
Adding support for OpenAI Audio transcriptions
michaellavelle Feb 6, 2024
8ae506f
Improve the OpenAi Audio code structure
tzolov Mar 6, 2024
c0c9dd2
Upgrade Azure OpenAI from 1.0.0-beta.6 to 1.0.0-beta.7
tzolov Mar 6, 2024
7cc2eab
Change flatten pom config
markpollack Mar 1, 2024
7396597
Update to add latest gpt-3.5 turbo model number
youngmoneee Mar 5, 2024
3938cc8
Remove setters from options interface
youngmoneee Mar 6, 2024
f6c57f6
rename directory spring-ai-stabilityai to stability-ai
Mar 3, 2024
bcb559a
add license header plugin and update all java files
markpollack Mar 6, 2024
8ed2af4
Add Ollama enum with supported models and their ids
sblashuk Mar 1, 2024
78f73d1
Exclude .antlr and aot.factories from license headers check
tzolov Mar 7, 2024
1e3eaec
Refactor and centralize Retry logic:
tzolov Mar 6, 2024
1d6d11c
Resolve OpenAiApi initialization bug
tzolov Mar 7, 2024
e535c0e
Adjust the retry properties names and documentation
tzolov Mar 8, 2024
ba94039
Use platform independent line separators
tzolov Mar 8, 2024
4fa2c6c
Move the maven license plugin into a 'license' profile
tzolov Mar 8, 2024
659f007
Update auto-configure classes to return the most specific class types
tzolov Mar 8, 2024
af957b9
Add ETL pipeline diagrams
tzolov Mar 8, 2024
1ea8515
Fix spring-ai-retry BOM version
tzolov Mar 8, 2024
fef7303
Replace %n by System.lineSeparator()
tzolov Mar 8, 2024
8a0ad1d
Disable outdated samples
tzolov Mar 8, 2024
8a336fb
Update google could bom from 26.33.0 to 26.34.0
tzolov Mar 8, 2024
680150e
Use MessageType.FUNCTION for FunctionMessage
yarisvt Mar 8, 2024
7f60e03
Fix Bedrock Anthropic line separator handling on Windows
tzolov Mar 8, 2024
8784a59
Add logging of page processing progress in PagePdfDocumentReader
markpollack Mar 7, 2024
7b89341
Add shell.log to gitignore
markpollack Mar 8, 2024
634e6d0
Add Azure Workshop sample app to getting started doc
markpollack Mar 8, 2024
f8f38d6
Add MistralAI links to getting started doc
ricken07 Mar 9, 2024
0fdc6aa
Add streaming Function Calling support of OpenAI and Mistral AI
tzolov Mar 10, 2024
c5d9ae3
Improve Milvus documentation
tzolov Mar 11, 2024
7f1570d
Update javadoc for message package and docs for Gemini Multimodal sup…
markpollack Mar 11, 2024
4209d5a
Make consistent sync/stream AssistantMessage properties for OpenAI an…
tzolov Mar 12, 2024
777b79e
Fix RedisVectorStore not closing Jedis pipelines
Bragolgirith Mar 10, 2024
1e98f82
Change Azure embedding and chat options 'model' property to 'deployme…
markpollack Mar 11, 2024
ed5eef4
fix failing test due to property name change of model->deployment-nam…
markpollack Mar 12, 2024
4fd15b1
Add documentation for OpenAI Transcription
markpollack Mar 12, 2024
7bfe312
Convinence StreamingChatClient stream default
tzolov Mar 12, 2024
783d81b
add quotes around command in github action to upload javadocs
markpollack Mar 12, 2024
490f3cd
Milestone Release 0.8.1
markpollack Mar 12, 2024
4c617e1
Prepare next development iteration
markpollack Mar 12, 2024
9e98962
Add additional ctor for OpenAiEmbeddingClient
markpollack Mar 14, 2024
255e542
CI/CD configuration fixes
tzolov Mar 15, 2024
7d44f14
Fix typo in model name, fixed #442
abel533 Mar 14, 2024
73f9cb8
Fixed syntax in reference
Mar 12, 2024
be7e291
Fixed typo in Bedrock Titan chat option exception
pradipkhomane Mar 12, 2024
ba3e94e
Fixed typo in 'reference'
bottlerocketjonny Mar 12, 2024
152420f
Fix Typos and Grammatical Errors
mackey0225 Mar 15, 2024
7c6bbef
Allow more customization for Neo4j store (id and constraint).
meistermeier Mar 14, 2024
6638efe
fix code formatting
tzolov Mar 15, 2024
0e8b696
modified ImageMessage.java line 45: mage > Image
Mar 11, 2024
a8142b7
fixing GH document upload action
tzolov Mar 15, 2024
4e3bba7
Fix GH documenttation-upload.yml
tzolov Mar 15, 2024
cf463c8
Improve the Deploy docs steps of Docs uplaod GH action
tzolov Mar 15, 2024
c453529
Final GH doc action fixes
tzolov Mar 15, 2024
9330187
Improve auto-confg condigiton on class to prevent undesired activation
tzolov Mar 15, 2024
49a1cc6
Update Mistral AI function calling docs and layout
tzolov Mar 16, 2024
9c19dc1
Improve Antora documentation layout
tzolov Mar 16, 2024
5f0123c
Add MongoDB Atlas Vector store
Kirbstomper Nov 4, 2023
db43fe3
Add PostgresMlAutoConfiguration to AutoConfiguration.imports
izeye Mar 16, 2024
c036931
Implemented Bedrock Jurassic 2 ChatClient
hemeda3 Mar 3, 2024
c5f3502
Remove withReuse in MongoDBAtlasContainer
eddumelendez Mar 16, 2024
c2b3659
Add ElasticsearchAiSearchFilterExpressionConverter
JM-Lab Jan 9, 2024
04b25ff
Add support for Elasticsearch vector store
JM-Lab Jan 9, 2024
bdc413c
Add support for various vector functions provided by Elasticsearch
JM-Lab Jan 14, 2024
d0a185b
Add support for Elasticsearch 8 vector store using the elasticsearch-…
JM-Lab Mar 3, 2024
ba1728e
Merge branch 'elasticsearch-vector-store' of https://github.com/JM-La…
JM-Lab Mar 17, 2024
b38552c
Rebase, fix compilation and style errors add missing dependecies in p…
tzolov Mar 15, 2024
a28f245
Fix ElasticsearchVectorStoreIT FilterExpression with Date type requir…
JM-Lab Mar 17, 2024
5cb6d92
Rename Elasticsearch8VectorStoreIT to ElasticsearchVectorStoreIT
JM-Lab Mar 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions vector-stores/spring-ai-elasticsearch-store/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai</artifactId>
<version>0.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>spring-ai-elasticsearch-store</artifactId>
<packaging>jar</packaging>
<name>Spring AI Vector Store - Elasticsearch</name>
<description>Spring AI Elasticsearch Vector Store</description>
<url>https://github.com/spring-projects/spring-ai</url>

<scm>
<url>https://github.com/spring-projects/spring-ai</url>
<connection>git://github.com/spring-projects/spring-ai.git</connection>
<developerConnection>[email protected]:spring-projects/spring-ai.git</developerConnection>
</scm>

<properties>
<!-- testing -->
<hikari-cp.version>4.0.3</hikari-cp.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
<version>${parent.version}</version>
</dependency>

<dependency>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we be using the elasticsearch-java client instead?

    <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>xxx</version>
    </dependency>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose to use the Java Low Level REST Client (https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/8.12/java-rest-low.html) with minimal dependencies instead of the elasticsearch-java library's High Level Rest Client. This decision was based on the High Level Rest Client's heavy reliance on dependencies and its sensitivity to Elasticsearch server versions, requiring exact matching with versions 7, 8, and even minor releases. By implementing only the essential data classes for Vectorstore, I successfully tested compatibility with both version 7 and 8.

<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>8.11.3</version>
</dependency>

<!-- TESTING -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
<version>${parent.version}</version>
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-test</artifactId>
<version>${parent.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright 2023-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.ai.vectorstore;

import org.springframework.ai.vectorstore.filter.Filter;
import org.springframework.ai.vectorstore.filter.Filter.Expression;
import org.springframework.ai.vectorstore.filter.Filter.Key;
import org.springframework.ai.vectorstore.filter.converter.AbstractFilterExpressionConverter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.regex.Pattern;

public class ElasticsearchAiSearchFilterExpressionConverter extends AbstractFilterExpressionConverter {

private static final Pattern DATE_FORMAT_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z");

private final SimpleDateFormat dateFormat;

public ElasticsearchAiSearchFilterExpressionConverter() {
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}

@Override
protected void doExpression(Expression expression, StringBuilder context) {
if (expression.type() == Filter.ExpressionType.IN || expression.type() == Filter.ExpressionType.NIN) {
context.append(getOperationSymbol(expression));
context.append("(");
this.convertOperand(expression.left(), context);
this.convertOperand(expression.right(), context);
context.append(")");
} else {
this.convertOperand(expression.left(), context);
context.append(getOperationSymbol(expression));
this.convertOperand(expression.right(), context);
}
}

@Override
protected void doStartValueRange(Filter.Value listValue, StringBuilder context) {
}

@Override
protected void doEndValueRange(Filter.Value listValue, StringBuilder context) {
}

@Override
protected void doAddValueRangeSpitter(Filter.Value listValue, StringBuilder context) {
context.append(" OR ");
}

private String getOperationSymbol(Expression exp) {
return switch (exp.type()) {
case AND -> " AND ";
case OR -> " OR ";
case EQ, IN -> "";
case NE -> " NOT ";
case LT -> "<";
case LTE -> "<=";
case GT -> ">";
case GTE -> ">=";
case NIN -> "NOT ";
default -> throw new RuntimeException("Not supported expression type: " + exp.type());
};
}

@Override
public void doKey(Key key, StringBuilder context) {
var identifier = hasOuterQuotes(key.key()) ? removeOuterQuotes(key.key()) : key.key();
var prefixedIdentifier = withMetaPrefix(identifier);
context.append(prefixedIdentifier.trim()).append(":");
}

public String withMetaPrefix(String identifier) {
return "metadata." + identifier;
}

@Override
protected void doValue(Filter.Value filterValue, StringBuilder context) {
if (filterValue.value() instanceof List list) {
int c = 0;
for (Object v : list) {
context.append(v);
if (c++ < list.size() - 1) {
this.doAddValueRangeSpitter(filterValue, context);
}
}
} else {
this.doSingleValue(filterValue.value(), context);
}
}

@Override
protected void doSingleValue(Object value, StringBuilder context) {
if (value instanceof Date date) {
context.append(this.dateFormat.format(date));
} else if (value instanceof String text) {
if (DATE_FORMAT_PATTERN.matcher(text).matches()) {
try {
Date date = this.dateFormat.parse(text);
context.append(this.dateFormat.format(date));
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date type:" + text, e);
}
} else {
context.append(text);
}
} else {
context.append(value);
}
}

@Override
public void doStartGroup(Filter.Group group, StringBuilder context) {
context.append("(");
}

@Override
public void doEndGroup(Filter.Group group, StringBuilder context) {
context.append(")");
}

}
Loading