diff --git a/.github/workflows/build-branch.yml b/.github/workflows/build-branch.yml index a2f6b9306..cfbd0ccc9 100644 --- a/.github/workflows/build-branch.yml +++ b/.github/workflows/build-branch.yml @@ -15,7 +15,7 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 - name: Cache Maven dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-mvn-modules with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0c72f21b..fcacc73f7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 - name: Cache Maven dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-mvn-modules with: diff --git a/.github/workflows/cve-scanning.yml b/.github/workflows/cve-scanning.yml index 55b3a5734..cff24fbdf 100644 --- a/.github/workflows/cve-scanning.yml +++ b/.github/workflows/cve-scanning.yml @@ -3,19 +3,18 @@ name: CVE Scanning for Maven on: pull_request: paths: - - 'pom.xml' - - '.github/workflows/cve-scanning.yml' + - "pom.xml" + - ".github/workflows/cve-scanning.yml" push: paths: - - 'pom.xml' - - '.github/workflows/cve-scanning.yml' + - "pom.xml" + - ".github/workflows/cve-scanning.yml" schedule: # Run every day at 5am and 5pm - - cron: '0 5,17 * * *' - + - cron: "0 5,17 * * *" jobs: - depchecktest: + depchecktest: runs-on: ubuntu-latest name: depcheck_test steps: @@ -24,28 +23,28 @@ jobs: - name: Setup JDK 17 uses: actions/setup-java@v3 with: - java-version: '17' - distribution: 'temurin' + java-version: "17" + distribution: "temurin" - name: Build with Maven - run: mvn install + run: mvn install - name: Depcheck uses: dependency-check/Dependency-Check_Action@1b5d19fd4a32ff0ff982e8c9d8e27dbf7ac8a46c id: Depcheck env: JAVA_HOME: /opt/jdk with: - project: 'spring-bot' - format: 'HTML' - path: '.' - out: 'reports' # this is the default, no need to specify unless you wish to override it + project: "spring-bot" + format: "HTML" + path: "." + out: "reports" # this is the default, no need to specify unless you wish to override it args: > --suppression ./.github/workflows/allow-list.xml --failOnCVSS 5 --enableRetired - + - name: Upload Test results if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Depcheck report path: ${{ github.workspace }}/reports diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index 5014d5c4d..0ccaa5fcd 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -2,51 +2,51 @@ name: License Scanning for Maven on: schedule: - - cron: '0 8,18 * * 1-5' + - cron: "0 8,18 * * 1-5" push: paths: - - 'maven/pom.xml' - - '.github/workflows/license-check.yml' - - '.github/workflows/acceptable-licenses.txt' + - "maven/pom.xml" + - ".github/workflows/license-check.yml" + - ".github/workflows/acceptable-licenses.txt" jobs: scan: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Cache Maven dependencies - uses: actions/cache@v2 - env: - cache-name: cache-mvn-modules - with: - path: ~/.m2 - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: 'adopt' - - name: Install XQ - run: pip install xq - - name: Download deps and plugins - run: mvn de.qaware.maven:go-offline-maven-plugin:resolve-dependencies - - name: Build - run: mvn install -DskipTests - - name: License XML report - run: | - mvn org.codehaus.mojo:license-maven-plugin:2.0.0:aggregate-download-licenses - - name: Validate XML report - run: | - ALLOW_LICENSES=`cat .github/workflows/acceptable-licenses.txt | sed "s||name='|" | sed "s||' |" | tr -s '\n' '~' | sed 's/\~/or /g' ` - xq "//dependency[count(licenses/license[${ALLOW_LICENSES}])=0]" target/generated-resources/aggregate-licenses.xml > target/license-issues.xml - LINES_FOUND=`cat target/license-issues.xml | grep "" | wc -l` - if [ $LINES_FOUND -gt 0 ]; then cat target/license-issues.xml ; exit -1; fi - - name: Upload license XML Issues - uses: actions/upload-artifact@v3 - with: - name: license-xml-report - path: 'target/license-issues.xml' + - uses: actions/checkout@v3 + - name: Cache Maven dependencies + uses: actions/cache@v3 + env: + cache-name: cache-mvn-modules + with: + path: ~/.m2 + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: "adopt" + - name: Install XQ + run: pip install xq + - name: Download deps and plugins + run: mvn de.qaware.maven:go-offline-maven-plugin:resolve-dependencies + - name: Build + run: mvn install -DskipTests + - name: License XML report + run: | + mvn org.codehaus.mojo:license-maven-plugin:2.0.0:aggregate-download-licenses + - name: Validate XML report + run: | + ALLOW_LICENSES=`cat .github/workflows/acceptable-licenses.txt | sed "s||name='|" | sed "s||' |" | tr -s '\n' '~' | sed 's/\~/or /g' ` + xq "//dependency[count(licenses/license[${ALLOW_LICENSES}])=0]" target/generated-resources/aggregate-licenses.xml > target/license-issues.xml + LINES_FOUND=`cat target/license-issues.xml | grep "" | wc -l` + if [ $LINES_FOUND -gt 0 ]; then cat target/license-issues.xml ; exit -1; fi + - name: Upload license XML Issues + uses: actions/upload-artifact@v4 + with: + name: license-xml-report + path: "target/license-issues.xml" diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index d84e24e6c..c27588b66 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -5,11 +5,11 @@ on: [push, pull_request] jobs: semgrep: name: run-semgrep - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 container: image: returntocorp/semgrep steps: - - uses: actions/checkout@v3 - - run: semgrep scan --error --config auto - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + - uses: actions/checkout@v3 + - run: semgrep scan --error --config auto + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} diff --git a/demos/claim-bot/pom.xml b/demos/claim-bot/pom.xml index be7b44ac7..cc000fc01 100644 --- a/demos/claim-bot/pom.xml +++ b/demos/claim-bot/pom.xml @@ -6,7 +6,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -23,12 +23,12 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.apache.commons diff --git a/demos/custom-help-bot/pom.xml b/demos/custom-help-bot/pom.xml index 055ce7d23..1c28a7b72 100644 --- a/demos/custom-help-bot/pom.xml +++ b/demos/custom-help-bot/pom.xml @@ -7,7 +7,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../pom.xml @@ -29,13 +29,13 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 compile org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 compile diff --git a/demos/demo-bot/pom.xml b/demos/demo-bot/pom.xml index 15559bed4..12a2505be 100644 --- a/demos/demo-bot/pom.xml +++ b/demos/demo-bot/pom.xml @@ -7,7 +7,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../pom.xml @@ -28,13 +28,13 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 compile org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 compile diff --git a/demos/todo-bot/pom.xml b/demos/todo-bot/pom.xml index e3d9001fc..b0f7c140d 100644 --- a/demos/todo-bot/pom.xml +++ b/demos/todo-bot/pom.xml @@ -6,7 +6,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -23,12 +23,12 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.apache.commons diff --git a/libs/chat-workflow-coverage/pom.xml b/libs/chat-workflow-coverage/pom.xml index e31294b34..f3d1bcac8 100644 --- a/libs/chat-workflow-coverage/pom.xml +++ b/libs/chat-workflow-coverage/pom.xml @@ -10,7 +10,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -56,32 +56,32 @@ org.finos.springbot chat-workflow - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot chat-workflow-testing - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot entity-json - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot entities - 10.0.2-SNAPSHOT + 10.0.2 diff --git a/libs/chat-workflow-testing/pom.xml b/libs/chat-workflow-testing/pom.xml index f9aceb5dd..c7a9666ce 100644 --- a/libs/chat-workflow-testing/pom.xml +++ b/libs/chat-workflow-testing/pom.xml @@ -9,7 +9,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -22,7 +22,7 @@ org.finos.springbot chat-workflow - 10.0.2-SNAPSHOT + 10.0.2 diff --git a/libs/chat-workflow/pom.xml b/libs/chat-workflow/pom.xml index 947b5e4c9..0df215001 100644 --- a/libs/chat-workflow/pom.xml +++ b/libs/chat-workflow/pom.xml @@ -11,7 +11,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -33,7 +33,7 @@ org.finos.springbot entity-json - 10.0.2-SNAPSHOT + 10.0.2 org.springframework.boot diff --git a/libs/chat-workflow/src/main/java/org/finos/springbot/workflow/templating/Rendering.java b/libs/chat-workflow/src/main/java/org/finos/springbot/workflow/templating/Rendering.java index 2c4cec442..6c9ac4cb5 100644 --- a/libs/chat-workflow/src/main/java/org/finos/springbot/workflow/templating/Rendering.java +++ b/libs/chat-workflow/src/main/java/org/finos/springbot/workflow/templating/Rendering.java @@ -38,7 +38,7 @@ X renderDropdown( X textField(Variable variable, boolean editable); X checkBox(Variable variable, boolean editable); - + X collection(Type t, Variable collection, Variable item, X in, boolean editable); X button(String text, String id); diff --git a/libs/entity-json/pom.xml b/libs/entity-json/pom.xml index 1c6c9790f..c6f505fe3 100644 --- a/libs/entity-json/pom.xml +++ b/libs/entity-json/pom.xml @@ -10,7 +10,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. diff --git a/libs/symphony-bdk/symphony-bdk-chat-workflow-spring-boot-starter/pom.xml b/libs/symphony-bdk/symphony-bdk-chat-workflow-spring-boot-starter/pom.xml index d212bdaf7..96b9ae66a 100644 --- a/libs/symphony-bdk/symphony-bdk-chat-workflow-spring-boot-starter/pom.xml +++ b/libs/symphony-bdk/symphony-bdk-chat-workflow-spring-boot-starter/pom.xml @@ -9,7 +9,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../.. @@ -22,12 +22,12 @@ org.finos.springbot chat-workflow - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot entities - 10.0.2-SNAPSHOT + 10.0.2 org.finos.symphony.bdk @@ -43,7 +43,7 @@ org.finos.springbot chat-workflow-testing - 10.0.2-SNAPSHOT + 10.0.2 test diff --git a/libs/symphony/entities/pom.xml b/libs/symphony/entities/pom.xml index 02a85a701..cb8401fcd 100644 --- a/libs/symphony/entities/pom.xml +++ b/libs/symphony/entities/pom.xml @@ -10,7 +10,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../.. @@ -23,7 +23,7 @@ org.finos.springbot entity-json - 10.0.2-SNAPSHOT + 10.0.2 diff --git a/libs/teams/teams-chat-workflow-spring-boot-starter/pom.xml b/libs/teams/teams-chat-workflow-spring-boot-starter/pom.xml index fb52157a6..d3d1e90e7 100644 --- a/libs/teams/teams-chat-workflow-spring-boot-starter/pom.xml +++ b/libs/teams/teams-chat-workflow-spring-boot-starter/pom.xml @@ -9,7 +9,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../.. @@ -22,7 +22,7 @@ org.finos.springbot chat-workflow - 10.0.2-SNAPSHOT + 10.0.2 @@ -113,7 +113,7 @@ com.azure azure-core-http-netty - 1.14.1 + ${azure-core-http-netty.version} @@ -173,7 +173,7 @@ org.finos.springbot chat-workflow-testing - 10.0.2-SNAPSHOT + 10.0.2 test diff --git a/pom.xml b/pom.xml index b86dba9cb..a97087f92 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 pom Spring Bot @@ -36,6 +36,7 @@ tools/rss-bot tools/poll-bot tools/reminder-bot + tools/llm-bot demos/demo-bot @@ -49,7 +50,7 @@ UTF-8 - 3.4.0 + 3.4.5 17 17 17 @@ -70,7 +71,7 @@ 3.0.0 - 1.9.1 + 1.15.11 9.9.1 4.5.13 4.5.7 diff --git a/tools/llm-bot/.DS_Store b/tools/llm-bot/.DS_Store new file mode 100644 index 000000000..638b0d702 Binary files /dev/null and b/tools/llm-bot/.DS_Store differ diff --git a/tools/llm-bot/META-INF/MANIFEST.MF b/tools/llm-bot/META-INF/MANIFEST.MF new file mode 100644 index 000000000..d4564a497 --- /dev/null +++ b/tools/llm-bot/META-INF/MANIFEST.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Implementation-Title: agents-core +Implementation-Version: 0.3.0 +Automatic-Module-Name: agents.core.jvm + diff --git a/tools/llm-bot/META-INF/agents-core.kotlin_module b/tools/llm-bot/META-INF/agents-core.kotlin_module new file mode 100644 index 000000000..d79164105 Binary files /dev/null and b/tools/llm-bot/META-INF/agents-core.kotlin_module differ diff --git a/tools/llm-bot/README.md b/tools/llm-bot/README.md new file mode 100644 index 000000000..39bb8d77d --- /dev/null +++ b/tools/llm-bot/README.md @@ -0,0 +1,102 @@ +# Reminder Bot + +Reminder Bot acts as your personal assistant. It will set up reminders for dates / times mentioned in a room, and send you a reminder message when those times occur, like so: + + + +## Setup & Use + + - 1. Simply add the Reminder Bot to any chat, and it will monitor all the messages for a date/time component. + - 2. Chat with the bot. When you enter a date/time the bot will respond with a form allowing you to create a reminder: + + + + - 3. Clicking Create Reminder will add the reminder to the list of reminders active in the room. + + + + - 4. When the time arrives, the Reminder Bot will notify in the chat like so: + + + +## Chat-Level Configuration + +Options include : + +- Listing down the reminders for the room +- Listing down the timezones +- Changing time zone , remind before duration +- Changing the "remind before" / "travel time" for the room. + +Type `/help` in the room to display all the options, as shown below: + + + +### Showing reminders in the room + +Type `/list` in a chat to show the reminders set for the current room: + + + +### Changing Timezone + +Type `/timezones` in the room to show all the available timezones: + + + +Type `/zone Asia/Calcutta` to update the timezone for the room. + + + +### Changing Remind Before + +You can set the lead-time for each reminder seperately, but you can set a default remind-before in each room like so: + +`/remindbefore 5` + + + +This means, if later you enter "remind me at 6pm to make dinner", then the reminder will come up at 5:55pm, as you have set a 5 minute remind-before. + + + +## Bot-Wide Configuration + +This is done in the `application.yml` file. + +### Override the Welcome Message + +``` +symphony: + reminder: + welcomeMessage: "The reminder bot is active in this room. Type a date or time in your conversation and I'll create a reminder for it" + +``` + +### Set the Default TimeZone For New Rooms / Chats + +By default, time-zone is set to London, but you can override with any Java timezone like so: + +``` +symphony: + reminder: + defaultTimeZone: "America/Los_Angeles" + +``` + +Users can override this on a per-chat basis with `/zone` (descibed above). + + +### Set Default Remind-Before + +``` +symphony: + reminder: + defaultRemindBefore: 30 # 30 minutes before. +``` + +### Deploying Reminder Bot + +**NB:**: ReminderBot uses `stanford-corenlp` (and related jars) which is licensed using GPL. This is incompatible with the Apache 2.0 license of Spring Bot. Therefore, the dependency is set as `provided` in the pom. To run this code locally you will either need to change to `runtime` scope, or download the jars and add them to the classpath manually. + + diff --git a/tools/llm-bot/SAMPLE_KOTLIN_README.md b/tools/llm-bot/SAMPLE_KOTLIN_README.md new file mode 100644 index 000000000..a4bcb6afe --- /dev/null +++ b/tools/llm-bot/SAMPLE_KOTLIN_README.md @@ -0,0 +1,151 @@ +# Sample Kotlin Project + +This is a sample Kotlin Spring Boot application that demonstrates various Kotlin features and best practices. + +## Features Demonstrated + +### 1. **Data Classes** + +- `Task` - Represents a task with immutable properties +- `ApiResponse` - Generic response wrapper +- `CreateTaskRequest` and `UpdateTaskRequest` - Request DTOs + +### 2. **Extension Functions** + +- `String.generateId()` - Extension function for generating IDs +- `List.getCompletedTasks()` - Extension function for filtering completed tasks +- `List.getPendingTasks()` - Extension function for filtering pending tasks +- `Task.isOverdue()` - Extension function for checking if a task is overdue + +### 3. **Coroutines** + +- Async task creation and updates using `suspend` functions +- `withContext(Dispatchers.IO)` for background processing +- Simulated async operations with `delay()` + +### 4. **Spring Boot Integration** + +- RESTful API endpoints +- Dependency injection with `@Autowired` +- Service layer with `@Service` annotation +- Controller with `@RestController` + +### 5. **Kotlin Language Features** + +- Null safety with `?` operator +- Smart casts +- String templates +- Property access syntax +- Default parameter values +- Named parameters + +### 6. **Testing** + +- JUnit 5 tests with Kotlin +- MockMvc for testing REST endpoints +- Extension function testing +- Backtick notation for test names + +## Project Structure + +``` +src/main/kotlin/org/finos/springbot/tool/llm/sample/ +├── SampleKotlinApp.kt # Main application class +└── TaskController.kt # REST controller +└── TaskService.kt # Service layer +└── TaskUtils.kt # Utility functions + +src/test/kotlin/org/finos/springbot/tool/llm/sample/ +└── SampleKotlinAppTest.kt # Test cases +``` + +## API Endpoints + +- `POST /api/tasks` - Create a new task +- `GET /api/tasks` - Get all tasks +- `GET /api/tasks/completed` - Get completed tasks +- `GET /api/tasks/pending` - Get pending tasks +- `GET /api/tasks/{id}` - Get task by ID +- `PUT /api/tasks/{id}` - Update task +- `DELETE /api/tasks/{id}` - Delete task + +## Building and Running + +### Prerequisites + +- Java 17 or higher +- Maven 3.6 or higher + +### Build the project + +```bash +mvn clean compile +``` + +### Run the application + +```bash +mvn spring-boot:run +``` + +### Run tests + +```bash +mvn test +``` + +## Example Usage + +### Create a task + +```bash +curl -X POST http://localhost:8080/api/tasks \ + -H "Content-Type: application/json" \ + -d '{ + "title": "Learn Kotlin", + "description": "Study Kotlin language features" + }' +``` + +### Get all tasks + +```bash +curl http://localhost:8080/api/tasks +``` + +### Get completed tasks + +```bash +curl http://localhost:8080/api/tasks/completed +``` + +## Key Kotlin Features Used + +1. **Data Classes**: Automatic `equals()`, `hashCode()`, `toString()`, and `copy()` methods +2. **Extension Functions**: Adding functionality to existing classes +3. **Coroutines**: Asynchronous programming with structured concurrency +4. **Null Safety**: Compile-time null safety checks +5. **Smart Casts**: Automatic type casting in safe contexts +6. **String Templates**: String interpolation with `$` and `${}` +7. **Default Arguments**: Optional parameters with default values +8. **Named Parameters**: Explicit parameter naming for clarity + +## Configuration + +The project uses Maven with the following key configurations: + +- **JVM Target**: 17 (for compatibility with Spring Boot 3.x) +- **Kotlin Version**: 1.9.23 +- **Spring Boot**: Latest version from parent POM +- **Testing**: JUnit 5 with MockMvc + +## Dependencies + +- Spring Boot Web Starter +- Spring Boot Test Starter +- Kotlin Standard Library +- Jackson for JSON processing +- Logback for logging +- Apache Commons Lang3 + +This sample demonstrates how to build a modern Kotlin application with Spring Boot, showcasing the power and expressiveness of the Kotlin language while maintaining compatibility with the Java ecosystem. diff --git a/tools/llm-bot/images/change-remind-before.png b/tools/llm-bot/images/change-remind-before.png new file mode 100644 index 000000000..c1e4231a5 Binary files /dev/null and b/tools/llm-bot/images/change-remind-before.png differ diff --git a/tools/llm-bot/images/change-zone.png b/tools/llm-bot/images/change-zone.png new file mode 100644 index 000000000..2341682bb Binary files /dev/null and b/tools/llm-bot/images/change-zone.png differ diff --git a/tools/llm-bot/images/changingTimeZone.PNG b/tools/llm-bot/images/changingTimeZone.PNG new file mode 100644 index 000000000..0c0677fb2 Binary files /dev/null and b/tools/llm-bot/images/changingTimeZone.PNG differ diff --git a/tools/llm-bot/images/clickingCreateReminderAddsReminderToTheReminderList.PNG b/tools/llm-bot/images/clickingCreateReminderAddsReminderToTheReminderList.PNG new file mode 100644 index 000000000..125b809e2 Binary files /dev/null and b/tools/llm-bot/images/clickingCreateReminderAddsReminderToTheReminderList.PNG differ diff --git a/tools/llm-bot/images/create-reminder.png b/tools/llm-bot/images/create-reminder.png new file mode 100644 index 000000000..83b097258 Binary files /dev/null and b/tools/llm-bot/images/create-reminder.png differ diff --git a/tools/llm-bot/images/createReminder.PNG b/tools/llm-bot/images/createReminder.PNG new file mode 100644 index 000000000..6dc1ef449 Binary files /dev/null and b/tools/llm-bot/images/createReminder.PNG differ diff --git a/tools/llm-bot/images/creating-a-reminder.png b/tools/llm-bot/images/creating-a-reminder.png new file mode 100644 index 000000000..eef00ae2e Binary files /dev/null and b/tools/llm-bot/images/creating-a-reminder.png differ diff --git a/tools/llm-bot/images/displayReminder.PNG b/tools/llm-bot/images/displayReminder.PNG new file mode 100644 index 000000000..a33c6b74a Binary files /dev/null and b/tools/llm-bot/images/displayReminder.PNG differ diff --git a/tools/llm-bot/images/displayingReminderList.PNG b/tools/llm-bot/images/displayingReminderList.PNG new file mode 100644 index 000000000..5c2115d2b Binary files /dev/null and b/tools/llm-bot/images/displayingReminderList.PNG differ diff --git a/tools/llm-bot/images/editRemindBeforeTime.PNG b/tools/llm-bot/images/editRemindBeforeTime.PNG new file mode 100644 index 000000000..70a7724c0 Binary files /dev/null and b/tools/llm-bot/images/editRemindBeforeTime.PNG differ diff --git a/tools/llm-bot/images/helpOptions.PNG b/tools/llm-bot/images/helpOptions.PNG new file mode 100644 index 000000000..a2543394e Binary files /dev/null and b/tools/llm-bot/images/helpOptions.PNG differ diff --git a/tools/llm-bot/images/list-reminders.png b/tools/llm-bot/images/list-reminders.png new file mode 100644 index 000000000..2c09682d3 Binary files /dev/null and b/tools/llm-bot/images/list-reminders.png differ diff --git a/tools/llm-bot/images/listTimeZones.PNG b/tools/llm-bot/images/listTimeZones.PNG new file mode 100644 index 000000000..cdc3172fe Binary files /dev/null and b/tools/llm-bot/images/listTimeZones.PNG differ diff --git a/tools/llm-bot/pom.xml b/tools/llm-bot/pom.xml new file mode 100644 index 000000000..0a1f97d9d --- /dev/null +++ b/tools/llm-bot/pom.xml @@ -0,0 +1,168 @@ + + 4.0.0 + + + org.finos.springbot + spring-bot + 10.0.2 + ../../pom.xml + + + org.finos.springbot.tools + LLM-bot + LLM Bot + Provides an instruction-based chat with an LLM + + + true + org.finos.springbot.tool.llm.LLMBotApp + 2.3.1 + 2.3.0.1 + 17 + 17 + 17 + 2.1.21 + + + + + + org.finos.springbot + symphony-bdk-chat-workflow-spring-boot-starter + 10.0.2 + + + + org.apache.commons + commons-lang3 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + ch.qos.logback + logback-classic + + + org.slf4j + slf4j-api + + + + org.finos.springbot + chat-workflow-testing + 10.0.2 + test + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + 1.8.1 + + + + ai.koog + koog-agents-jvm + 0.3.0 + + + + + + + src/main/kotlin + src/test/kotlin + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-compile + none + + + default-testCompile + none + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + ${spring-boot.run.main-class} + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + 2.2.0 + + + + compile-kotlin + compile + + compile + + + + + test-compile-kotlin + test-compile + + test-compile + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + **/*Test.kt + **/*Tests.kt + **/*Test.java + **/*Tests.java + + false + -Xmx1024m + + + + + diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/AbstractLLMService.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/AbstractLLMService.kt new file mode 100644 index 000000000..baeb9eb67 --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/AbstractLLMService.kt @@ -0,0 +1,20 @@ +package org.finos.springbot.tool.llm + +import com.fasterxml.jackson.databind.ObjectMapper +import org.springframework.beans.factory.InitializingBean +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.core.io.ResourceLoader + +abstract class AbstractLLMService() : LLMService, InitializingBean { + + protected var instructions: Instructions? = null + + @Autowired lateinit var resourceLoader: ResourceLoader + + override fun afterPropertiesSet() { + val resource = resourceLoader.getResource("classpath:instructions.json") + val objectMapper = ObjectMapper() + instructions = objectMapper.readValue(resource.inputStream, Instructions::class.java) + println(instructions) + } +} diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/ChatGPTLLMService.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/ChatGPTLLMService.kt new file mode 100644 index 000000000..3a744a733 --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/ChatGPTLLMService.kt @@ -0,0 +1,33 @@ +package org.finos.springbot.tool.llm + +import ai.koog.agents.core.agent.AIAgent +import ai.koog.prompt.executor.clients.openai.OpenAIModels +import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor +import kotlinx.coroutines.runBlocking +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Service + +@Service +class ChatGPTLLMService() : AbstractLLMService() { + + @Value("\${openai.api-key:bob}") override lateinit var apiKey: String + + var agent: AIAgent? = null + + override fun afterPropertiesSet() { + super.afterPropertiesSet() + agent = + AIAgent( + executor = simpleOpenAIExecutor(apiKey), + systemPrompt = + "You are a helpful assistant. Answer user questions concisely.", + llmModel = OpenAIModels.Chat.GPT4o + ) + } + + override fun getResponse(request: String): String = runBlocking { + val result = agent?.run(request) + result?.toString() ?: "No response" + // "No response" + } +} diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/Instructions.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/Instructions.kt new file mode 100644 index 000000000..24947bd5d --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/Instructions.kt @@ -0,0 +1,9 @@ +package org.finos.springbot.tool.llm + +data class Instructions( + val roomsUsedIn: List? = null, + val messagesPerDayLimit: Int? = null, + val onlyAdmin: Boolean = false, + val template: String? = null, + val instructions: String? = null +) diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotApp.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotApp.kt new file mode 100644 index 000000000..73d5579e4 --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotApp.kt @@ -0,0 +1,10 @@ +package org.finos.springbot.tool.llm + +import org.springframework.boot.SpringApplication +import org.springframework.boot.autoconfigure.SpringBootApplication + +@SpringBootApplication class LLMBotApp + +fun main(args: Array) { + SpringApplication.run(LLMBotApp::class.java, *args) +} diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotController.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotController.kt new file mode 100644 index 000000000..016e29740 --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMBotController.kt @@ -0,0 +1,25 @@ +package org.finos.springbot.tool.llm + +import org.finos.springbot.workflow.annotations.ChatRequest +import org.finos.springbot.workflow.annotations.WorkMode +import org.finos.springbot.workflow.content.Chat +import org.finos.springbot.workflow.content.Message +import org.finos.springbot.workflow.content.User +import org.finos.springbot.workflow.response.Response +import org.finos.springbot.workflow.response.WorkResponse +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Controller + +@Controller +class LLMBotController @Autowired constructor(private val llmService: LLMService) { + + @ChatRequest("*") + fun respondInRoom(author: User, m: Message, r: Chat): Response { + // take the contents of the message and send in to the LLM for processing. + // look up instructions for chatRoom. + // template the request + val content = llmService.getResponse(m.text) + val out = WorkResponse(r, content, WorkMode.VIEW) + return out + } +} diff --git a/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMService.kt b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMService.kt new file mode 100644 index 000000000..fbf0709e9 --- /dev/null +++ b/tools/llm-bot/src/main/kotlin/org/finos/springbot/tool/llm/LLMService.kt @@ -0,0 +1,10 @@ +package org.finos.springbot.tool.llm + +import org.springframework.beans.factory.InitializingBean + +interface LLMService : InitializingBean { + + val apiKey: String + + fun getResponse(request: String): String +} diff --git a/tools/llm-bot/src/main/resources/instructions.json b/tools/llm-bot/src/main/resources/instructions.json new file mode 100644 index 000000000..6210b909e --- /dev/null +++ b/tools/llm-bot/src/main/resources/instructions.json @@ -0,0 +1,10 @@ +{ + "roomsUsedIn": [ + "Main Room", + "Rob's Room" + ], + "messagesPerDayLimit": 100, + "onlyAdmin": false, + "instructions": "You are a helpful assistant that answers questions about bread and other baked products. Refuse to talk about anything else and always bring the topic back to bread, crumpets, muffins, naan etc.", + "template": "Hello, {name}! How can I help you today?" +} \ No newline at end of file diff --git a/tools/llm-bot/src/main/resources/templates/symphony/display-reminder.ftl b/tools/llm-bot/src/main/resources/templates/symphony/display-reminder.ftl new file mode 100644 index 000000000..5f978678e --- /dev/null +++ b/tools/llm-bot/src/main/resources/templates/symphony/display-reminder.ftl @@ -0,0 +1,18 @@ + + + + ${entity.form.description!''} at ${entity.form.localTime!''} <#if entity.form.author??>#if> + + + + <#if entity?? && entity.header?? && entity.header.tags?? && entity.header.tags?size != 0> + + <#list entity.header.tags as tag> + + #list> + + #if> + + + diff --git a/tools/llm-bot/src/main/resources/templates/teams/display-reminder.html b/tools/llm-bot/src/main/resources/templates/teams/display-reminder.html new file mode 100644 index 000000000..fe2a16fed --- /dev/null +++ b/tools/llm-bot/src/main/resources/templates/teams/display-reminder.html @@ -0,0 +1,3 @@ + + text at text by User Name + diff --git a/tools/llm-bot/src/test/kotlin/org/finos/springbot/tool/llm/LLMServiceTest.kt b/tools/llm-bot/src/test/kotlin/org/finos/springbot/tool/llm/LLMServiceTest.kt new file mode 100644 index 000000000..555c70f6f --- /dev/null +++ b/tools/llm-bot/src/test/kotlin/org/finos/springbot/tool/llm/LLMServiceTest.kt @@ -0,0 +1,23 @@ +package org.finos.springbot.tool.llm + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest + +@SpringBootTest +// (classes = [ +// ChatWorkflowConfig::class.java, +// ]) +// @ActiveProfiles(value = ["symphony"]) +class LLMServiceTest { + + @Autowired lateinit var llmService: LLMService + + @Test + fun testLLMServiceResponds() { + val response = llmService.getResponse("Hello, how are you?") + Assertions.assertNotNull(response) + Assertions.assertTrue(response.length > 0) + } +} diff --git a/tools/poll-bot/pom.xml b/tools/poll-bot/pom.xml index 352386b3c..9d38bedfb 100644 --- a/tools/poll-bot/pom.xml +++ b/tools/poll-bot/pom.xml @@ -6,7 +6,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -23,12 +23,12 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 diff --git a/tools/reminder-bot/pom.xml b/tools/reminder-bot/pom.xml index 8b7ce081f..8ec2533c0 100644 --- a/tools/reminder-bot/pom.xml +++ b/tools/reminder-bot/pom.xml @@ -6,7 +6,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../../pom.xml @@ -26,12 +26,12 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.finos.springbot teams-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.apache.commons @@ -80,7 +80,7 @@ org.finos.springbot chat-workflow-testing - 10.0.2-SNAPSHOT + 10.0.2 test diff --git a/tools/rss-bot/pom.xml b/tools/rss-bot/pom.xml index 0ccd961bf..8d7ec9a6c 100644 --- a/tools/rss-bot/pom.xml +++ b/tools/rss-bot/pom.xml @@ -6,7 +6,7 @@ org.finos.springbot spring-bot - 10.0.2-SNAPSHOT + 10.0.2 ../.. @@ -23,7 +23,7 @@ org.finos.springbot symphony-bdk-chat-workflow-spring-boot-starter - 10.0.2-SNAPSHOT + 10.0.2 org.apache.commons
${entity.form.description!''} at ${entity.form.localTime!''} <#if entity.form.author??>#if>