Skip to content

Commit

Permalink
Java Spring boot middle-tier sample (#106)
Browse files Browse the repository at this point in the history
* Added spring boot template project

* Downgraded to java 17, added more .gitignore entries, successfully imported rt sdk

* Spring boot ws is hitable with python script

* Improved readme

* Reading application.properties correctly

* Merge branch 'main' into jpalvarezl/spring_backend

* Renamed project folder

* Added azure service toggle

* Setup everything with dependency injection

* WIP

* Written conversation works

* Audio successfully sent to the frontend

* Moved stuff around

* Updated readme and env var names

* Moved folder after cherry pick

* Added support for transcription messages

* Added support for TranscriptionMessages for feature parity with other samples

* Clarified README

* Added comment

* Added more specific error logging

* Added logging

* Added log config

* Added error handler for sending events

* Final adjustments to docs
  • Loading branch information
jpalvarezl authored Dec 19, 2024
1 parent a05ac17 commit 0c8c36a
Show file tree
Hide file tree
Showing 26 changed files with 1,105 additions and 4 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,9 @@ FodyWeavers.xsd
# Binary archives
*.tgz
*.zip

# MacOS
.DS_Store

# Env files
.env
10 changes: 6 additions & 4 deletions samples/middle-tier/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ When building applications that leverage Azure OpenAI or OpenAI's Realtime APIs,

```
samples/middle-tier/
├── node-express/ # Node.js backend implementation
├── python-fastapi/ # Python backend implementation
└── generic-frontend/ # React-based frontend application
├── node-express/ # Node.js backend implementation
├── python-fastapi/ # Python backend implementation
├── spring-boot/ # Spring boot Java backend implementation
├── dotnet-aspnetcore-mvc/ # ASP.NET Core MVC C# backend implementation
└── generic-frontend/ # React-based frontend application
```

## Available Samples
Expand Down Expand Up @@ -157,4 +159,4 @@ Feel free to contribute additional implementations or improvements:
- These samples are intended for demonstration purposes
- Adjust security settings and implement proper authentication for production use
- The protocol can be extended to support additional features
- Consider implementing error handling and recovery mechanisms for production
- Consider implementing error handling and recovery mechanisms for production
3 changes: 3 additions & 0 deletions samples/middle-tier/spring-boot/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
43 changes: 43 additions & 0 deletions samples/middle-tier/spring-boot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/

### Python ###
/venv

### Logs ###
/logs
102 changes: 102 additions & 0 deletions samples/middle-tier/spring-boot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Realtime Backend FastAPI Sample

This Spring Boot application serves as a middle-tier service to mediate connections with the Azure OpenAI or OpenAI Realtime API. It introduces a simplified protocol for backend communication, covering only the necessary functionalities and allowing easy extensions.

## Overview

The service establishes a WebSocket server that communicates with clients using a custom protocol. It translates client messages into the appropriate format for the backend API (Azure OpenAI or OpenAI Realtime API) and handles responses, forwarding them back to the client.

## Features

- **Simplified Protocol**: Uses a custom, lightweight communication protocol.
- **Backend Support**: Works with both Azure OpenAI and OpenAI Realtime APIs.
- **Extendable**: Easily extend the protocol to cover additional functionalities.
-
## Environment Variables

Set the following environment variables in a `.env` file at the root of the project:

### Common Variables

- `BACKEND`: Specify the backend to use (`azure` or `openai`).
- `PORT` (optional): Port number for the server (default is `8080`).
- `ADDRESS` (optional): Server host (default is `localhost`).

### Using Azure OpenAI Backend

- `AZURE_OPENAI_ENDPOINT`: Your Azure OpenAI endpoint URL.
- `AZURE_OPENAI_DEPLOYMENT`: The name of your Azure OpenAI deployment.

### Using OpenAI Realtime API Backend

- `OPENAI_API_KEY`: Your OpenAI API key.
- `OPENAI_MODEL`: The model to use (e.g., `gpt-3.5-turbo`).

## Setup and Run

- Get Java version 17 (recommended tooling: [sdkman](https://sdkman.io/usage/))
- (Recommended) Install Intellij IDE and run/debug using their tooling.

### Command line

To run the server `./gradlew bootRun`

### Intellij

Find the `bootRun` task in the gradle task panel and run it:

![alt text](gradle-task-panel.png)

If you have setup a `.env` file in the root of the project, `application->bootRun` should launch the application with the values you've specified.

Alternatively, if you prefer not having a `.env` file, modify the IDE's launch configuration like shown in the image:

![alt text](run-config.png)

## Custom Protocol

The application defines its own protocol for client-server communication:

- **Control Messages**: Manage connection status and actions (e.g., connected, speech_started, text_done).
- **User Messages**: Send user text inputs (user_message).
- **Transcriptions**: Receive transcribed text from audio inputs (transcription).
- **Text Deltas**: Stream partial text responses (text_delta).

This protocol focuses on essential features and can be extended as needed.

## Type Definitions

The protocol messages are defined using Python's typing system:

```java
class TextDelta {
String id;
MessageType type = MessageType.TEXT_DELTA;
String delta;
}

class UserMessage {
String id;
MessageType type = MessageType.USER_MESSAGE;
String text;
}

class TranscriptionMessage {
String id;
MessageType type = MessageType.TRANSCRIPTION;
String text;
}

class ControlMessage {
MessageType type = MessageType.CONTROL;
String action;
String greeting;
String id;
}
```

## Notes

- Ensure that the required environment variables are set correctly for your chosen backend.
- Logging is configured using slf4j and can be adjusted through its configuration.
- The server implements CORS middleware with permissive settings for development. Adjust these settings for production use.
35 changes: 35 additions & 0 deletions samples/middle-tier/spring-boot/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.0'
id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.azure.sample.openai.realtime'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

repositories {
mavenCentral()
maven {
url = uri("https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-java/maven/v1")
name = "azure-sdk-for-java"
}
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'me.paulschwarz:spring-dotenv:4.0.0'
implementation 'com.azure:azure-ai-openai-realtime:1.0.0-alpha.20241205.3'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 0c8c36a

Please sign in to comment.