Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@

<modules>
<module>springboot-modules</module>
<module>springboot-modules2</module>
<module>testContainers</module>
</modules>

Expand Down
61 changes: 61 additions & 0 deletions springboot-modules2/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.kodesastra</groupId>
<artifactId>kodesastra_blog</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<groupId>com.ks</groupId>
<artifactId>springboot-modules2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>


<modules>
<module>springai-opensearch</module>
</modules>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.maven.plugin.version}</version>
</plugin>
</plugins>
</build>

<properties>
<spring-boot.version>3.5.11</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<springboot.maven.plugin.version>3.5.11</springboot.maven.plugin.version>
</properties>

</project>
65 changes: 65 additions & 0 deletions springboot-modules2/springai-opensearch/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.ks</groupId>
<artifactId>springboot-modules2</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<groupId>com.kodesastra</groupId>
<artifactId>springai-opensearch</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version>
<spring-ai.version>1.1.2</spring-ai.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-opensearch</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
</dependency>
<!-- Source:
https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-pdf-document-reader -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>
</dependencies>


<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.19.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ks.opensearch;

import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenSearchAppConfiguration {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ks.opensearch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OpenSearchSpringAiApplication {
public static void main(String[] args) {
SpringApplication.run(OpenSearchSpringAiApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.ks.opensearch.service;

import java.util.List;

import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;

public class PdfDocumentCreator {

public static List<Document>fetchDocumentChunksFromPdf(String pdfFilePath) {
PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(pdfFilePath);
TokenTextSplitter splitter = new TokenTextSplitter();
return splitter.transform(pdfReader.get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
spring:
application:
name: spring-ai-azureopenai

ai:
azure:
openai:
api-key: <<AZURE OPENAI DEPLOYMENT API KEY>>
endpoint: <<AZURE OPENAI DEPLOYMENT ENDPOINT>>
chat:
options:
user: springai-azureopenai-user
deployment-name: gpt-5-mini
temperature: 1
embedding:
options:
deployment-name: text-embedding-ada-002
model: text-embedding-ada-002

vectorstore:
opensearch:
uris: http://192.168.1.36:9200
index-name: book-index
initialize-schema: true
similarity-function: cosinesimil
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.ks.opensearch;


import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.pdf.ParagraphPdfDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.opensearch.OpenSearchVectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class OpenSearchLiveTest {

private static final Logger logger = LoggerFactory.getLogger(OpenSearchLiveTest.class);

@Autowired
private OpenSearchVectorStore vectorStore;

@Value("classpath:/rag/spring-framework.pdf")
private String filePath;

@Autowired
private AzureOpenAiChatModel azureOpenAiChatModel;

@Test
@Order(1)
void whenSaveDocChunks_thenDocumentsAddedToVectorStore() {
ParagraphPdfDocumentReader paragraphPdfDocumentReader = new ParagraphPdfDocumentReader(filePath);
TokenTextSplitter tokenTextSplitter = new TokenTextSplitter();

List<Document> documentChunks = tokenTextSplitter.apply(paragraphPdfDocumentReader.read());
assertThat(documentChunks).isNotEmpty();
assertThat(documentChunks.size()).isGreaterThan(0);

vectorStore.add(documentChunks);
}


@ParameterizedTest
@ValueSource(strings = {
"What is Inversion of Control in Spring Framework?",
"What happens in Autumn season?"
})
@Order(2)
void whenSearch_thenRelevantDocumentsReturned(String userQuery) {
Message userMessage = new UserMessage(userQuery);

SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate("""

You are a helpful assistant for answering questions related to Spring Framework.
You will answer the questions strictly based on the context provided to you:
{context}
If you don't know the answer, say you don't know.

""");

List<Document> relevantDocuments = vectorStore.similaritySearch(userQuery);

assertThat(relevantDocuments).isNotEmpty().hasSizeGreaterThan(0);

String contextContent = relevantDocuments.stream()
.map(Document::getText)
.reduce((a, b) -> a + "\n" + b)
.orElse("");

Message systemMessage = systemPromptTemplate
.createMessage(Map.of("context", contextContent));

Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
ChatResponse chatResponse = azureOpenAiChatModel.call(prompt);

assertThat(chatResponse.getResult().getOutput().getText()).isNotEmpty();

logger.info("User query: {}", userQuery);
logger.info("Chat Response: {}", chatResponse.getResult().getOutput().getText());
}
}
Loading