Skip to content

Commit 0aefc35

Browse files
committed
Neo4j example with annotation Tool
1 parent 1b49093 commit 0aefc35

File tree

4 files changed

+181
-2
lines changed

4 files changed

+181
-2
lines changed

neo4j-example/pom.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>dev.langchain4j</groupId>
88
<artifactId>neo4j-example</artifactId>
9-
<version>1.0.0-beta4</version>
9+
<version>1.0.0-beta7</version>
1010
<parent>
1111
<groupId>org.springframework.boot</groupId>
1212
<artifactId>spring-boot-starter-parent</artifactId>
@@ -29,7 +29,7 @@
2929
<dependency>
3030
<groupId>dev.langchain4j</groupId>
3131
<artifactId>langchain4j-spring-boot-starter</artifactId>
32-
<version>1.1.0-beta7</version>
32+
<version>${project.version}</version>
3333
</dependency>
3434
<dependency>
3535
<groupId>dev.langchain4j</groupId>
@@ -64,6 +64,12 @@
6464
<artifactId>langchain4j-open-ai</artifactId>
6565
<version>1.1.0</version>
6666
</dependency>
67+
<dependency>
68+
<groupId>dev.langchain4j</groupId>
69+
<artifactId>langchain4j-embeddings-all-minilm-l6-v2-q</artifactId>
70+
<version>1.1.0-beta7</version>
71+
<scope>compile</scope>
72+
</dependency>
6773

6874
</dependencies>
6975

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import dev.langchain4j.community.chain.RetrievalQAChain;
2+
import dev.langchain4j.community.store.embedding.neo4j.Neo4jEmbeddingStoreIngestor;
3+
import dev.langchain4j.community.store.embedding.neo4j.ParentChildGraphIngestor;
4+
import dev.langchain4j.data.document.Document;
5+
import dev.langchain4j.data.document.DocumentSplitter;
6+
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
7+
import dev.langchain4j.data.document.splitter.DocumentByRegexSplitter;
8+
import dev.langchain4j.model.embedding.onnx.allminilml6v2q.AllMiniLmL6V2QuantizedEmbeddingModel;
9+
import dev.langchain4j.model.openai.OpenAiChatModel;
10+
import dev.langchain4j.agent.tool.Tool;
11+
import dev.langchain4j.rag.content.retriever.ContentRetriever;
12+
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
13+
import dev.langchain4j.rag.query.Query;
14+
import dev.langchain4j.service.AiServices;
15+
import org.neo4j.driver.AuthTokens;
16+
import org.neo4j.driver.Driver;
17+
import org.neo4j.driver.GraphDatabase;
18+
import org.testcontainers.containers.Neo4jContainer;
19+
import util.Utils;
20+
21+
import java.time.Duration;
22+
23+
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
24+
25+
public class Neo4jRagAsAToolExample {
26+
27+
public static class RagTools {
28+
29+
private final Neo4jEmbeddingStoreIngestor ingestor;
30+
private final RetrievalQAChain qaChain;
31+
32+
public RagTools(Neo4jEmbeddingStoreIngestor ingestor, RetrievalQAChain qaChain) {
33+
this.ingestor = ingestor;
34+
this.qaChain = qaChain;
35+
}
36+
37+
@Tool("Ingest from document")
38+
public String ingest(String text) {
39+
Document document = FileSystemDocumentLoader.loadDocument(Utils.toPath(text));
40+
41+
ingestor.ingest(document);
42+
return "Document ingested";
43+
}
44+
45+
@Tool("Answer the question based only on the context provided from the ingested documents.")
46+
public String ask(String question) {
47+
return qaChain.execute(Query.from(question));
48+
}
49+
}
50+
51+
public static void main(String[] args) {
52+
try (Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5.26").withAdminPassword("pass1234")) {
53+
neo4j.start();
54+
// Setup OpenAI chat model
55+
OpenAiChatModel chatModel = OpenAiChatModel.builder()
56+
.baseUrl(System.getenv("OPENAI_BASE_URL"))
57+
.apiKey(System.getenv("OPENAI_API_KEY"))
58+
.modelName(GPT_4_O_MINI)
59+
.timeout(Duration.ofSeconds(60))
60+
.build();
61+
final AllMiniLmL6V2QuantizedEmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();
62+
63+
// MainDoc splitter splits on paragraphs (double newlines)
64+
final String expectedQuery = "\\n\\n";
65+
int maxSegmentSize = 250;
66+
DocumentSplitter parentSplitter = new DocumentByRegexSplitter(expectedQuery, expectedQuery, maxSegmentSize, 0);
67+
68+
// Child splitter splits on periods (sentences)
69+
final String expectedQueryChild = "\\. ";
70+
DocumentSplitter childSplitter =
71+
new DocumentByRegexSplitter(expectedQueryChild, expectedQuery, maxSegmentSize, 0);
72+
73+
final Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "pass1234"));
74+
75+
Neo4jEmbeddingStoreIngestor ingestor = ParentChildGraphIngestor.builder()
76+
.driver(driver)
77+
.documentSplitter(parentSplitter)
78+
.documentSplitter(childSplitter)
79+
.embeddingModel(embeddingModel)
80+
.build();
81+
82+
// Retriever from Neo4j embeddings
83+
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
84+
.embeddingStore(ingestor.getEmbeddingStore())
85+
.embeddingModel(embeddingModel)
86+
.maxResults(5)
87+
.minScore(0.4)
88+
.build();
89+
90+
// Retrieval QA chain using retriever and LLM
91+
RetrievalQAChain retrievalQAChain = RetrievalQAChain.builder()
92+
.contentRetriever(retriever)
93+
.chatModel(chatModel)
94+
.build();
95+
96+
97+
RagTools tools = new RagTools(ingestor, retrievalQAChain);
98+
99+
// Build assistant with ingestion tool and retrieval QA tool
100+
Utils.Assistant assistant = AiServices.builder(Utils.Assistant.class)
101+
.tools(tools)
102+
.chatModel(chatModel)
103+
.build();
104+
105+
106+
// Ask a question answered by retrieval QA chain
107+
String chat = assistant.chat("""
108+
Ingest from document 'myname.txt', and then return the answer for the question 'What is the cancellation policy?'""");
109+
System.out.println("ANSWER: " + chat);
110+
// example output:
111+
// `ANSWER: John Doe is a Super Saiyan`
112+
}
113+
}
114+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package util;
2+
3+
import dev.langchain4j.service.UserMessage;
4+
5+
import java.net.URISyntaxException;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
9+
public class Utils {
10+
11+
public interface Assistant {
12+
String chat(@UserMessage String userMessage);
13+
}
14+
15+
public static Path toPath(String fileName) {
16+
try {
17+
return Paths.get(Utils.class.getClassLoader().getResource(fileName).toURI());
18+
} catch (URISyntaxException e) {
19+
throw new RuntimeException(e);
20+
}
21+
}
22+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Miles of Smiles Car Rental Services Terms of Use
2+
3+
1. Introduction
4+
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.
5+
6+
2. The Services
7+
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.
8+
9+
3. Bookings
10+
3.1 Users may make a booking through our website or mobile application.
11+
3.2 You must provide accurate, current and complete information during the reservation process. You are responsible for all charges incurred under your account.
12+
3.3 All bookings are subject to vehicle availability.
13+
14+
4. Cancellation Policy
15+
4.1 Reservations can be cancelled up to 7 days prior to the start of the booking period.
16+
4.2 If the booking period is less than 3 days, cancellations are not permitted.
17+
18+
5. Use of Vehicle
19+
5.1 All cars rented from Miles of Smiles must not be used:
20+
for any illegal purpose or in connection with any criminal offense.
21+
for teaching someone to drive.
22+
in any race, rally or contest.
23+
while under the influence of alcohol or drugs.
24+
25+
6. Liability
26+
6.1 Users will be held liable for any damage, loss, or theft that occurs during the rental period.
27+
6.2 We do not accept liability for any indirect or consequential loss, damage, or expense including but not limited to loss of profits.
28+
29+
7. Governing Law
30+
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.
31+
32+
8. Changes to These Terms
33+
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.
34+
35+
9. Acceptance of These Terms
36+
By using the Services, you acknowledge that you have read and understand these Terms and agree to be bound by them.
37+
If you do not agree to these Terms, please do not use or access our Services.

0 commit comments

Comments
 (0)