Skip to content
Open
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
10 changes: 8 additions & 2 deletions neo4j-example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>dev.langchain4j</groupId>
<artifactId>neo4j-example</artifactId>
<version>1.0.0-beta4</version>
<version>1.1.0-beta7</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
Expand All @@ -29,7 +29,7 @@
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>1.1.0-beta7</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
Expand Down Expand Up @@ -64,6 +64,12 @@
<artifactId>langchain4j-open-ai</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2-q</artifactId>
<version>1.1.0-beta7</version>
<scope>compile</scope>
</dependency>

</dependencies>

Expand Down
114 changes: 114 additions & 0 deletions neo4j-example/src/main/java/Neo4jRagAsAToolExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import dev.langchain4j.community.chain.RetrievalQAChain;
import dev.langchain4j.community.store.embedding.neo4j.Neo4jEmbeddingStoreIngestor;
import dev.langchain4j.community.store.embedding.neo4j.ParentChildGraphIngestor;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.splitter.DocumentByRegexSplitter;
import dev.langchain4j.model.embedding.onnx.allminilml6v2q.AllMiniLmL6V2QuantizedEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.rag.query.Query;
import dev.langchain4j.service.AiServices;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.testcontainers.containers.Neo4jContainer;
import util.Utils;

import java.time.Duration;

import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;

public class Neo4jRagAsAToolExample {

public static class RagTools {

private final Neo4jEmbeddingStoreIngestor ingestor;
private final RetrievalQAChain qaChain;

public RagTools(Neo4jEmbeddingStoreIngestor ingestor, RetrievalQAChain qaChain) {
this.ingestor = ingestor;
this.qaChain = qaChain;
}

@Tool("Ingest from document")
public String ingest(String text) {
Document document = FileSystemDocumentLoader.loadDocument(Utils.toPath(text));

ingestor.ingest(document);
return "Document ingested";
}

@Tool("Answer the question based only on the context provided from the ingested documents.")
public String ask(String question) {
return qaChain.execute(Query.from(question));
}
}

public static void main(String[] args) {
try (Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5.26").withAdminPassword("pass1234")) {
neo4j.start();
// Setup OpenAI chat model
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.baseUrl(System.getenv("OPENAI_BASE_URL"))
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.timeout(Duration.ofSeconds(60))
.build();
final AllMiniLmL6V2QuantizedEmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();

// MainDoc splitter splits on paragraphs (double newlines)
final String expectedQuery = "\\n\\n";
int maxSegmentSize = 250;
DocumentSplitter parentSplitter = new DocumentByRegexSplitter(expectedQuery, expectedQuery, maxSegmentSize, 0);

// Child splitter splits on periods (sentences)
final String expectedQueryChild = "\\. ";
DocumentSplitter childSplitter =
new DocumentByRegexSplitter(expectedQueryChild, expectedQuery, maxSegmentSize, 0);

final Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "pass1234"));

Neo4jEmbeddingStoreIngestor ingestor = ParentChildGraphIngestor.builder()
.driver(driver)
.documentSplitter(parentSplitter)
.documentSplitter(childSplitter)
.embeddingModel(embeddingModel)
.build();

// Retriever from Neo4j embeddings
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(ingestor.getEmbeddingStore())
.embeddingModel(embeddingModel)
.maxResults(5)
.minScore(0.4)
.build();

// Retrieval QA chain using retriever and LLM
RetrievalQAChain retrievalQAChain = RetrievalQAChain.builder()
.contentRetriever(retriever)
.chatModel(chatModel)
.build();


RagTools tools = new RagTools(ingestor, retrievalQAChain);

// Build assistant with ingestion tool and retrieval QA tool
Utils.Assistant assistant = AiServices.builder(Utils.Assistant.class)
.tools(tools)
.chatModel(chatModel)
.build();


// Ask a question answered by retrieval QA chain
String chat = assistant.chat("""
Ingest from document 'miles-of-smiles-terms-of-use.txt', and then return the answer for the question 'What is the cancellation policy?'""");
System.out.println("ANSWER: " + chat);
// example output:
// `ANSWER: Reservations can be cancelled up to 7 days prior to the start of the booking period.
}
}
}
22 changes: 22 additions & 0 deletions neo4j-example/src/main/java/util/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package util;

import dev.langchain4j.service.UserMessage;

import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Utils {

public interface Assistant {
String chat(@UserMessage String userMessage);
}

public static Path toPath(String fileName) {
try {
return Paths.get(Utils.class.getClassLoader().getResource(fileName).toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}
37 changes: 37 additions & 0 deletions neo4j-example/src/main/resources/miles-of-smiles-terms-of-use.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Miles of Smiles Car Rental Services Terms of Use

1. Introduction
These Terms of Service (“Terms”) govern the access or use by you, an individual, from within any country in the world, of applications, websites, content, products, and services (“Services”) made available by Miles of Smiles Car Rental Services, a company registered in the United States of America.

2. The Services
Miles of Smiles rents out vehicles to the end user. We reserve the right to temporarily or permanently discontinue the Services at any time and are not liable for any modification, suspension or discontinuation of the Services.

3. Bookings
3.1 Users may make a booking through our website or mobile application.
3.2 You must provide accurate, current and complete information during the reservation process. You are responsible for all charges incurred under your account.
3.3 All bookings are subject to vehicle availability.

4. Cancellation Policy
4.1 Reservations can be cancelled up to 7 days prior to the start of the booking period.
4.2 If the booking period is less than 3 days, cancellations are not permitted.

5. Use of Vehicle
5.1 All cars rented from Miles of Smiles must not be used:
for any illegal purpose or in connection with any criminal offense.
for teaching someone to drive.
in any race, rally or contest.
while under the influence of alcohol or drugs.

6. Liability
6.1 Users will be held liable for any damage, loss, or theft that occurs during the rental period.
6.2 We do not accept liability for any indirect or consequential loss, damage, or expense including but not limited to loss of profits.

7. Governing Law
These terms will be governed by and construed in accordance with the laws of the United States of America, and any disputes relating to these terms will be subject to the exclusive jurisdiction of the courts of United States.

8. Changes to These Terms
We may revise these terms of use at any time by amending this page. You are expected to check this page from time to time to take notice of any changes we made.

9. Acceptance of These Terms
By using the Services, you acknowledge that you have read and understand these Terms and agree to be bound by them.
If you do not agree to these Terms, please do not use or access our Services.