Skip to content

Commit

Permalink
Add chatbot feature
Browse files Browse the repository at this point in the history
  • Loading branch information
pacphi committed Oct 22, 2024
1 parent 9c03c2c commit 5ea12f9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/ENDPOINTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* [Endpoints](#endpoints)
* [Upload](#upload)
* [Chat](#chat)
* [Get Metadata](#get-metadata)
* [Search](#search)
* [Summarize](#summarize)
Expand Down Expand Up @@ -55,6 +56,31 @@ You will need to adjust startup arguments, e.g., you could add the following to
-Dspring.servlet.multipart.max-file-size=250MB
```
### Chat
Converse with an AI chatbot who is aware of all uploaded content. Ask a question, get a response.
```python
GET /chat
```
**Sample interaction**
```bash
❯ http :8080/api/files/chat q=="Tell me something about the character Hermia from A Midsummer Night's Dream"
HTTP/1.1 200
Connection: keep-alive
Content-Length: 795
Content-Type: text/plain;charset=UTF-8
Date: Tue, 22 Oct 2024 12:24:58 GMT
Keep-Alive: timeout=60

Hermia is a key character in "A Midsummer Night's Dream," portrayed as the daughter of Egeus. She is in love with Lysander, but her father wishes her to marry Demetrius, which creates conflict in the story. Hermia is depicted as strong-willed and defiant; she boldly asserts her feelings and desires, expressing her wish that her father could see things from her perspective (Act I).

She passionately defends her love for Lysander and is determined to be with him despite the obstacles posed by her father and societal expectations. Hermia's character embodies themes of love, rebellion, and the struggle for autonomy within the constraints of Athenian law. Her determination to follow her heart leads her to plan an escape with Lysander, showcasing her bravery and commitment to love (Act I).
```
### Get Metadata
Retrieve metadata for all files in an S3-compliant object store's bucket
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/cftoolsuite/controller/DocumentController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.apache.commons.lang3.StringUtils;
import org.cftoolsuite.domain.FileMetadata;
import org.cftoolsuite.service.ChatService;
import org.cftoolsuite.service.DocumentIngestionService;
import org.cftoolsuite.service.DocumentSearchService;
import org.cftoolsuite.service.DocumentSummarizationService;
Expand All @@ -24,14 +25,17 @@
@RequestMapping("/api/files")
public class DocumentController {

private final ChatService chatService;
private final FileService fileService;
private final DocumentIngestionService documentIngestionService;
private final DocumentSearchService documentSearchService;
private final DocumentSummarizationService documentSummarizationService;

public DocumentController(
ChatService chatService,
FileService fileService, DocumentIngestionService documentIngestionService,
DocumentSearchService documentSearchService, DocumentSummarizationService documentSummarizationService) {
this.chatService = chatService;
this.fileService = fileService;
this.documentIngestionService = documentIngestionService;
this.documentSearchService = documentSearchService;
Expand All @@ -45,6 +49,12 @@ public ResponseEntity<FileMetadata> uploadFile(@RequestParam("fileName") Multipa
return ResponseEntity.ok(fileMetadata);
}

@GetMapping("/chat")
public ResponseEntity<String> chat(@RequestParam("q") String message) {
String response = chatService.askQuestion(message);
return ResponseEntity.ok(response);
}

@GetMapping
public ResponseEntity<List<FileMetadata>> getFileMetadata(@RequestParam(value = "fileName", required = false) String fileName) {
if (StringUtils.isBlank(fileName)) {
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/org/cftoolsuite/service/ChatService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.cftoolsuite.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

@Service
public class ChatService {

private final ChatClient chatClient;

public ChatService(ChatModel model, VectorStore vectorStore) {
ChatMemory chatMemory = new InMemoryChatMemory();
this.chatClient = ChatClient.builder(model)
.defaultSystem("""
You are an AI assistant with access to a specific knowledge base
Follow these guidelines:
Only use information from the provided context.
If the answer is not in the context, state that you don't have sufficient information.
Do not use any external knowledge or make assumptions beyond the given data.
Cite the relevant parts of the context in your responses including the source and origin.
Respond in a clear, concise manner without editorializing.
"""
)
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory),
new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()),
new SimpleLoggerAdvisor())
.build();
}

public String askQuestion(String question) {
return chatClient
.prompt()
.user(question)
.call()
.content();
}
}

0 comments on commit 5ea12f9

Please sign in to comment.