Skip to content

Commit fd5fc89

Browse files
committed
Adding Langchain4J + MCP support
1 parent f44aad4 commit fd5fc89

File tree

94 files changed

+2455
-6822
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+2455
-6822
lines changed

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ products:
1919
- azure-monitor
2020
- azure-pipelines
2121
urlFragment: agent-openai-java-banking-assistant
22-
name: Multi Agents Banking Assistant with Java and Semantic Kernel
22+
name: Multi Agents Banking Assistant with Java and Langchain4j
2323
description: A Java sample app emulating a personal banking AI-powered assistant to inquire about account balances, review recent transactions, or initiate payments
2424
---
2525
<!-- YAML front-matter schema: https://review.learn.microsoft.com/en-us/help/contribute/samples/process/onboarding?branch=main#supported-metadata-fields-for-readmemd -->
@@ -28,7 +28,7 @@ description: A Java sample app emulating a personal banking AI-powered assistant
2828

2929
![](./docs/assets/robot-agents-small.png)
3030

31-
# Multi Agents Banking Assistant with Java and Semantic Kernel
31+
# Multi Agents Banking Assistant with Java and Langchain4j
3232

3333
[![Open project in GitHub Codespaces](https://img.shields.io/badge/Codespaces-Open-blue?style=flat-square&logo=github)](https://codespaces.new/azure-samples/agent-openai-java-banking-assistant?hide_repo_select=true&ref=main&quickstart=true)
3434
[![Build Status](https://img.shields.io/github/actions/workflow/status/azure-samples/agent-openai-java-banking-assistant/azure-dev.yaml?style=flat-square&label=Build)](https://github.com/azure-samples/agent-openai-java-banking-assistant/actions)
@@ -44,7 +44,8 @@ description: A Java sample app emulating a personal banking AI-powered assistant
4444
![](./docs/assets/ui.gif)
4545
</div>
4646

47-
This project is designed as a Proof of Concept (PoC) to explore the innovative realm of generative AI within the context of multi-agent architectures. By leveraging Java and Microsoft Semantic Kernel AI orchestration framework, our aim is to build a chat web app to demonstrate the feasibility and reliability of using generative AI agents to transform user experience from web clicks to natural language conversations while maximizing reuse of the existing workload data and APIs.
47+
> [!NOTE]
48+
> Java Semantic Kernel version has been moved in a dedicated [branch](https://github.com/Azure-Samples/agent-openai-java-banking-assistant/tree/semantic-kernel)
4849
4950

5051

@@ -53,36 +54,35 @@ The core use case of this Proof of Concept (PoC) revolves around a banking perso
5354

5455
Instead of navigating through traditional web interfaces and menus, users can simply converse with the AI-powered assistant to inquire about their account balances, review recent transactions, or initiate payments. This approach not only enhances user experience by making financial management more intuitive and accessible but also leverages the existing workload data and APIs to ensure a reliable and secure service.
5556

56-
Invoices samples are included in the data folder to make it easy to explore payments feature. The payment agent equipped with OCR tools ( Azure Document Intelligence) will lead the conversation with the user to extract the invoice data and initiate the payment process. Other account fake data as transactions, payment methods and account balance are also available to be queried by the user. All data and services are exposed as external REST APIs and consumed by the agents to provide the user with the requested information.
57+
Invoices samples are included in the data folder to make it easy to explore payments feature. The payment agent equipped with OCR tools ( Azure Document Intelligence) will lead the conversation with the user to extract the invoice data and initiate the payment process. Other account fake data as transactions, payment methods and account balance are also available to be queried by the user. All data and services are exposed as external REST APIs and **MCP tools** consumed by the agents to provide the user with the requested information.
5758

5859
## Features
5960
This project provides the following features and technical patterns:
60-
- Simple multi ai agents Java implementation using *gpt-4o-mini* on Azure Open AI.
61+
- Simple multi-agent supervisor architecture using *gpt-4o-mini* or *gpt-4o* on Azure Open AI.
62+
- Exposing your business API as MCP tools for your agents using [spring-ai-mcp](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html)
6163
- Chat intent extraction and agent routing.
62-
- Agents tools configuration and automatic tools invocations with [Java Semantic Kernel](https://github.com/microsoft/semantic-kernel-java/).
63-
- Tools output cache scoped at chat conversation level.It improves functions call planning and parameters extraction for long chat.
64+
- Agents tools configuration and automatic tools invocations with [Langchain4j](https://github.com/langchain4j/langchain4j).
6465
- Chat based conversation implemented as [React Single Page Application](https://react.fluentui.dev/?path=/docs/concepts-introduction--docs) with support for images upload.Supported images are invoices, receipts, bills jpeg/png files you want your virtual banking assistant to pay on your behalf.
6566
- Images scanning and data extraction with Azure Document Intelligence using [prebuilt-invoice](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/concept-invoice?view=doc-intel-4.0.0) model.
66-
- Import REST api contracts (OpenAPI yaml files) as agent tools, providing automatic rest client call. It uses code from Java Semantic Kernel [open-api-plugin code sample](https://github.com/microsoft/semantic-kernel-java/tree/main/samples/semantickernel-sample-plugins/semantickernel-openapi-plugin).
6767
- Add a copilot app side-by-side to your existing business microservices hosted on [Azure Container Apps](https://azure.microsoft.com/en-us/products/container-apps).
6868
- Automated Azure resources creation and solution deployment leveraging [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/).
6969

7070
For complex agents conversation implementation, read more about [Autogen framework](https://github.com/microsoft/autogen).
7171

7272
### Architecture
73-
![HLA](docs/assets/HLA.png)
73+
![HLA](docs/assets/HLA-MCP.png)
7474
The personal banking assistant is designed as a [vertical multi-agent system](./docs/multi-agents/introduction.md), with each agent specializing in a specific functional domain (e.g., account management, transaction history, payments). The architecture consists of the following key components:
7575

7676
- **Copilot Assistant Copilot App (Microservice)**: Serves as the central hub for processing user requests. It's a spring boot application implementing a vertical multi-agent architectures using Java Semantic Kernel to create Agents equipped with tools. in Java the Agent Router to understand user intent from chat interactions and routes the request to the appropriate domain-specific agent.
77-
- **Agent Router**: Acts as a user proxy, interpreting user intent based on chat inputs and directing the request to the specific domain agent. This component ensures that user queries are efficiently handled by the relevant agent. It uses **IntentExtractor** tool backed by GPT4 model to extract the user intent in a json format. If intent is 'None' clarifying questions are provided.
78-
77+
- **Supervisor Agent**: Acts as a user proxy, interpreting user intent based on chat inputs and directing the request to the specific domain agent. This component ensures that user queries are efficiently handled by the relevant agent. Agents are engaged byt the supervisor in a single turn conversation meaning that only one is selected by the supervisor to answer to user task. It’s just doing routing logic, assuming the domain agent will either carry-on the task in one shot or will involve user feedback if data oversight or action approval (like payment submit) is required.
78+
7979
- **Account Agent**: Specializes in handling tasks related to banking account information, credit balance, and registered payment methods. It leverages specific Account service APIs to fetch and manage account-related data. Semantic Kernel HTTP plugin is used to create a tool definition from the rest api yaml contract (Open API specification) and automatically call the HTTP endpoint with input parameters extracted by gpt4 model from the chat conversation.
8080

8181
- **Transactions Agent**: Focuses on tasks related to querying user bank movements, including income and outcome payments. This agent accesses account api to retrieve accountid and transaction history service to search for transactions and present them to the user.
8282

8383
- **Payments Agent**: Dedicated to managing tasks related to submitting payments. It interacts with multiple APIs and tools, such as ScanInvoice (backed by Azure Document Intelligence), Account Service to retrieve account and payment methods info, Payment Service to submit payment processing and Transaction History service to check for previous paid invoices.
8484

85-
- **Existing Business APIs**: Interfaces with the backend systems to perform operations related to personal banking accounts, transactions, and invoice payments. These APIs are implemented as external spring boot microservices providing the necessary data and functionality consumed by agents to execute their tasks.
85+
- **Existing Business APIs**: Interfaces with the backend systems to perform operations related to personal banking accounts, transactions, and invoice payments. These APIs are implemented as external spring boot microservices providing the necessary data and functionality consumed by agents to execute their tasks. They are exposed both as traditional RESTs API and as MCP tools to be consumed by agents.
8686
- **Account Service (Microservice)**: Provides functionalities like retrieving account details by username, fetching payment methods, and getting registered beneficiaries. This microservice supports all 3 agents.
8787

8888
- **Payments Service (Microservice)**: Offers capabilities to submit payments and notify transactions. It is a critical component for the Payments Agent to execute payment-related tasks efficiently.

app/business-api/account/pom.xml

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>2.7.13</version>
8+
<version>3.3.6</version>
99
</parent>
1010

1111
<groupId>com.microsoft.openai.samples.assistant.business</groupId>
@@ -18,8 +18,24 @@
1818
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1919

2020
</properties>
21-
21+
22+
<dependencyManagement>
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.springframework.ai</groupId>
26+
<artifactId>spring-ai-bom</artifactId>
27+
<version>1.0.0-SNAPSHOT</version>
28+
<type>pom</type>
29+
<scope>import</scope>
30+
</dependency>
31+
</dependencies>
32+
</dependencyManagement>
33+
2234
<dependencies>
35+
<dependency>
36+
<groupId>org.springframework.ai</groupId>
37+
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
38+
</dependency>
2339
<dependency>
2440
<groupId>org.springframework.boot</groupId>
2541
<artifactId>spring-boot-starter-web</artifactId>
@@ -35,4 +51,33 @@
3551
</plugins>
3652
</build>
3753

54+
<repositories>
55+
<repository>
56+
<name>Central Portal Snapshots</name>
57+
<id>central-portal-snapshots</id>
58+
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
59+
<releases>
60+
<enabled>false</enabled>
61+
</releases>
62+
<snapshots>
63+
<enabled>true</enabled>
64+
</snapshots>
65+
</repository>
66+
<repository>
67+
<id>spring-milestones</id>
68+
<name>Spring Milestones</name>
69+
<url>https://repo.spring.io/milestone</url>
70+
<snapshots>
71+
<enabled>false</enabled>
72+
</snapshots>
73+
</repository>
74+
<repository>
75+
<id>spring-snapshots</id>
76+
<name>Spring Snapshots</name>
77+
<url>https://repo.spring.io/snapshot</url>
78+
<releases>
79+
<enabled>false</enabled>
80+
</releases>
81+
</repository>
82+
</repositories>
3883
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.microsoft.openai.samples.assistant.business.mcp.config;
2+
3+
4+
import com.microsoft.openai.samples.assistant.business.mcp.server.AccountMCPService;
5+
import com.microsoft.openai.samples.assistant.business.mcp.server.UserMCPService;
6+
import org.springframework.ai.tool.ToolCallbackProvider;
7+
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
8+
import org.springframework.context.annotation.Bean;
9+
import org.springframework.context.annotation.Configuration;
10+
11+
@Configuration
12+
public class MCPServerConfiguration {
13+
14+
@Bean
15+
public ToolCallbackProvider accountTools(AccountMCPService accountMCPService) {
16+
return MethodToolCallbackProvider.builder().toolObjects(accountMCPService).build();
17+
}
18+
19+
@Bean
20+
public ToolCallbackProvider userTools(UserMCPService userMCPService) {
21+
return MethodToolCallbackProvider.builder().toolObjects(userMCPService).build();
22+
}
23+
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.microsoft.openai.samples.assistant.business.mcp.server;
2+
3+
import com.microsoft.openai.samples.assistant.business.models.Account;
4+
import com.microsoft.openai.samples.assistant.business.models.Beneficiary;
5+
import com.microsoft.openai.samples.assistant.business.models.PaymentMethod;
6+
import com.microsoft.openai.samples.assistant.business.service.AccountService;
7+
import org.springframework.stereotype.Service;
8+
import org.springframework.ai.tool.annotation.Tool;
9+
10+
import java.util.List;
11+
12+
@Service
13+
public class AccountMCPService {
14+
15+
private final AccountService accountService;
16+
public AccountMCPService(AccountService accountService) {
17+
this.accountService = accountService;
18+
}
19+
20+
@Tool(description = "Get account details and available payment methods")
21+
public Account getAccountDetails(String accountId) {
22+
return this.accountService.getAccountDetails(accountId);
23+
24+
}
25+
26+
@Tool(description = "Get payment method detail with available balance")
27+
public PaymentMethod getPaymentMethodDetails(String paymentMethodId) {
28+
return this.accountService.getPaymentMethodDetails(paymentMethodId);
29+
}
30+
31+
@Tool(description = "Get list of registered beneficiaries for a specific account")
32+
public List<Beneficiary> getRegisteredBeneficiary(String accountId) {
33+
return this.accountService.getRegisteredBeneficiary(accountId);
34+
}
35+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.microsoft.openai.samples.assistant.business.mcp.server;
2+
3+
import com.microsoft.openai.samples.assistant.business.models.Account;
4+
import com.microsoft.openai.samples.assistant.business.service.UserService;
5+
import org.springframework.ai.tool.annotation.Tool;
6+
import org.springframework.ai.tool.annotation.ToolParam;
7+
import org.springframework.stereotype.Service;
8+
9+
import java.util.Arrays;
10+
import java.util.HashMap;
11+
import java.util.List;
12+
import java.util.Map;
13+
14+
15+
@Service
16+
public class UserMCPService {
17+
private final UserService userService;
18+
19+
public UserMCPService(UserService userService) {
20+
this.userService = userService;
21+
}
22+
23+
@Tool(description = "Get the list of all accounts for a specific user")
24+
public List<Account> getAccountsByUserName(@ToolParam( description ="userName once the user has logged" ) String userName) {
25+
return userService.getAccountsByUserName(userName);
26+
}
27+
28+
29+
}
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package com.microsoft.openai.samples.assistant.business.models;
22

33

4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
45
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
57

68
import java.util.List;
79

810
@JsonInclude(JsonInclude.Include.NON_NULL)
11+
@JsonIgnoreProperties(ignoreUnknown = true)
912
public record Account(
10-
String id,
11-
String userName,
12-
String accountHolderFullName,
13-
String currency,
14-
String activationDate,
15-
String balance,
13+
@JsonProperty("id") String id,
14+
@JsonProperty("userName") String userName,
15+
@JsonProperty("accountHolderFullName") String accountHolderFullName,
16+
@JsonProperty("currency") String currency,
17+
@JsonProperty("activationDate") String activationDate,
18+
@JsonProperty("balance") String balance,
1619
List<PaymentMethodSummary> paymentMethods
1720
) {}
1821

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.microsoft.openai.samples.assistant.business.models;
22

33

4-
import java.util.List;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
56

7+
8+
@JsonIgnoreProperties(ignoreUnknown = true)
69
public record Beneficiary(
7-
String id,
8-
String fullName,
9-
String bankCode,
10-
String bankName
10+
@JsonProperty("id") String id,
11+
@JsonProperty("fullName") String fullName,
12+
@JsonProperty("bankCode") String bankCode,
13+
@JsonProperty("bankName") String bankName
1114
) {}
1215

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
package com.microsoft.openai.samples.assistant.business.models;
22

33

4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
45
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
57

68
@JsonInclude(JsonInclude.Include.NON_NULL)
9+
@JsonIgnoreProperties(ignoreUnknown = true)
710
public record PaymentMethod(
8-
String id,
9-
String type,
10-
String activationDate,
11-
String expirationDate,
12-
String availableBalance,
11+
@JsonProperty("id") String id,
12+
@JsonProperty("type") String type,
13+
@JsonProperty("activationDate") String activationDate,
14+
@JsonProperty("expirationDate") String expirationDate,
15+
@JsonProperty("availableBalance") String availableBalance,
1316
// card number is valued only for credit card type
14-
String cardNumber
17+
@JsonProperty("cardNumber") String cardNumber
1518
) {}
1619

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.microsoft.openai.samples.assistant.business.models;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
35

6+
@JsonIgnoreProperties(ignoreUnknown = true)
47
public record PaymentMethodSummary(
5-
String id,
6-
String type,
7-
String activationDate,
8-
String expirationDate
8+
@JsonProperty("id") String id,
9+
@JsonProperty("type") String type,
10+
@JsonProperty("activationDate") String activationDate,
11+
@JsonProperty("expirationDate") String expirationDate
912
) {}
1013

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
server.port=8070
1+
server.port=8070

0 commit comments

Comments
 (0)