Skip to content

Mmeckes spring ai frontend #711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
70 changes: 70 additions & 0 deletions samples/spring-ai-simple-chat-client-with-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Spring AI Simple Chat Client

A lightweight Spring Boot application demonstrating the integration of Spring AI with Amazon Bedrock to create a simple chat API.

## Features

- REST API endpoints for AI chat interactions
- Support for both synchronous and streaming responses
- Custom tool integration
- Integration with Amazon Bedrock's Claude 3 Sonnet model

## Prerequisites

- Java 21
- Maven
- AWS account with access to Amazon Bedrock
- AWS credentials configured locally

## Configuration

The application is configured to use Amazon Bedrock's Claude 3 Sonnet model in the EU West 1 region. You can modify these settings in `application.properties`:

```properties
spring.application.name=agents
spring.ai.bedrock.aws.region=eu-west-1
spring.ai.bedrock.converse.chat.options.model=eu.anthropic.claude-3-7-sonnet-20250219-v1:0
```

## Building and Running

```bash
mvn spring-boot:run
```

The application will start on port 8080 by default.

## API Endpoints

### 1. Synchronous Chat Endpoint

Send a prompt and receive a complete response:

```bash
curl -XPOST 'http://localhost:8080/ai' \
-H "Content-Type: application/json" \
-d '{"prompt":"Tell me about Spring AI in 2 sentences."}'
```

### 2. Streaming Chat Endpoint

Send a prompt and receive the response as a stream (useful for real-time UI updates):

```bash
curl -XPOST -N 'http://localhost:8080/ai/stream' \
-H "Content-Type: application/json" \
-d '{"prompt":"Who is George Mallory?"}'
```

### 3. With tool use

curl -XPOST -N 'http://localhost:8080/ai/stream' \
-H "Content-Type: application/json" \
-d '{"prompt":"What is the current date and time?"}'

## Project Structure

- `ChatController.java`: Defines the REST endpoints for chat interactions
- `PromptRequest.java`: Simple record class for the request payload
- `DateTimeTools.java`: Custom tool that provides date/time information to the AI
- `AgentsApplication.java`: Spring Boot application entry point
61 changes: 61 additions & 0 deletions samples/spring-ai-simple-chat-client-with-ui/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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.unicorn</groupId>
<artifactId>agents</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>agents</name>
<description>Simple Bedrock Chat Client for Spring AI</description>
<properties>
<java.version>21</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-bedrock-converse</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</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>
</dependencies>

</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

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

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

@SpringBootApplication
public class AgentsApplication {

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.unicorn.agents;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api")
public class ChatController {

private final ChatClient chatClient;

public ChatController (ChatClient.Builder chatClient){
this.chatClient = chatClient
.defaultTools(new DateTimeTools())
.build();
}

@PostMapping("/ai")
public String myAgent(@RequestBody PromptRequest promptRequest){
return chatClient.prompt().user(promptRequest.prompt()).call().chatResponse().getResult().getOutput().getText();
}

@PostMapping("/ai/stream")
public Flux<String> myStreamingAgent(@RequestBody PromptRequest promptRequest){
return chatClient.prompt().user(promptRequest.prompt()).stream().content();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.unicorn.agents;

import java.time.LocalDateTime;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.context.i18n.LocaleContextHolder;

class DateTimeTools {

@Tool(description = "Get the current date and time in the user's timezone")
String getCurrentDateTime(String param) {
return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.unicorn.agents;

public record PromptRequest(String prompt){};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.unicorn.agents;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class WebController {

@GetMapping("/")
public String home() {
return "redirect:/chat";
}

@GetMapping("/chat")
public String chatPage() {
return "chat";
}

@GetMapping("/stream-chat")
public String streamChatPage() {
return "stream-chat";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
spring.application.name=unicorn-store
spring.ai.bedrock.aws.region=eu-west-1
spring.ai.bedrock.converse.chat.options.model=eu.anthropic.claude-3-7-sonnet-20250219-v1:0
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* Custom styles for Unicorn Store */
.unicorn-gradient {
background: linear-gradient(135deg, #f5f3ff, #fce7f3);
}

.unicorn-shadow {
box-shadow: 0 4px 14px rgba(156, 39, 176, 0.1);
}

/* Any additional custom styles can be added here */
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading