Skip to content

Commit 58d3a99

Browse files
committed
first MVP draft
1 parent 590d587 commit 58d3a99

File tree

19 files changed

+86
-92
lines changed

19 files changed

+86
-92
lines changed

.devcontainer/Dockerfile

-6
This file was deleted.

.devcontainer/devcontainer.json

+14-15
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,32 @@
11
{
2-
"name": "Azure Developer CLI",
3-
"build": {
4-
"dockerfile": "Dockerfile",
5-
"args": {
6-
"VARIANT": "bullseye"
7-
}
8-
},
2+
"name": "Java 17 and maven 3.8.8 DevContainer to build Java RAG example with Azure AI",
3+
"image": "mcr.microsoft.com/devcontainers/java:1-17-bullseye",
94
"features": {
10-
"ghcr.io/devcontainers/features/python:1": {
11-
"version": "os-provided"
5+
"azure-cli": "latest",
6+
"ghcr.io/azure/azure-dev/azd:latest": {},
7+
"ghcr.io/devcontainers/features/java:1": {
8+
"version": "none",
9+
"installMaven": true,
10+
"mavenVersion": "3.8.8"
1211
},
1312
"ghcr.io/devcontainers/features/node:1": {
14-
"version": "16",
15-
"nodeGypDependencies": false
13+
"version": "20.5.0"
1614
},
17-
"ghcr.io/devcontainers/features/powershell:1.1.0": {},
18-
"ghcr.io/devcontainers/features/azure-cli:1.0.8": {}
15+
"ghcr.io/devcontainers-contrib/features/typescript:2": {}
1916
},
2017
"customizations": {
2118
"vscode": {
2219
"extensions": [
20+
"GitHub.vscode-github-actions",
2321
"ms-azuretools.azure-dev",
2422
"ms-azuretools.vscode-bicep",
25-
"ms-python.python"
23+
"vscjava.vscode-java-pack",
24+
"amodio.tsl-problem-matcher"
2625
]
2726
}
2827
},
2928
"forwardPorts": [
30-
5000
29+
// Forward ports if needed for local development
3130
],
3231
"postCreateCommand": "",
3332
"remoteUser": "vscode",

README.md

+48-45
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
# ChatGPT + Enterprise data with Azure OpenAI and Cognitive Search
2-
3-
[![Open in GitHub Codespaces](https://img.shields.io/static/v1?style=for-the-badge&label=GitHub+Codespaces&message=Open&color=brightgreen&logo=github)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=599293758&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=WestUs2)
4-
[![Open in Remote - Containers](https://img.shields.io/static/v1?style=for-the-badge&label=Remote%20-%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/azure-samples/azure-search-openai-demo)
5-
6-
This sample demonstrates a few approaches for creating ChatGPT-like experiences over your own data using the Retrieval Augmented Generation pattern. It uses Azure OpenAI Service to access the ChatGPT model (gpt-35-turbo), and Azure Cognitive Search for data indexing and retrieval.
1+
# ChatGPT + Enterprise data with Azure OpenAI and Cognitive Search - Java Version
2+
This repo is the java conversion of the well known [chatGPT + Enterprise data code sample](https://github.com/Azure-Samples/azure-search-openai-demo) originally written in python.
3+
It demonstrates a few approaches for creating ChatGPT-like experiences over your own data using the Retrieval Augmented Generation pattern. It uses Azure OpenAI Service to access the ChatGPT model (gpt-35-turbo), and Azure Cognitive Search for data indexing and retrieval.
74

85
The repo includes sample data so it's ready to try end to end. In this sample application we use a fictitious company called Contoso Electronics, and the experience allows its employees to ask questions about the benefits, internal policies, as well as job descriptions and roles.
96

@@ -18,6 +15,18 @@ The repo includes sample data so it's ready to try end to end. In this sample ap
1815

1916
![Chat screen](docs/chatscreen.png)
2017

18+
## Python Converstion Status
19+
While this first version is MVP showcasing semantic search scenario with java and azure open AI, It is still under active development. Below you can find the status of the conversation and the planned features.
20+
21+
Python Approach | Java Open AI SDK | Java Semantic Kernel |
22+
:------------ | :-------------| :-------------|
23+
RetrieveThenRead | :white_check_mark: | :x:
24+
ChatReadRetrieveRead| :white_check_mark: | :x:
25+
ReadRetrieveRead | :x: | :soon:
26+
ReadDecomposeAsk | :x: | :soon:
27+
28+
29+
2130
## Getting Started
2231

2332
> **IMPORTANT:** In order to deploy and run this example, you'll need an **Azure subscription with access enabled for the Azure OpenAI service**. You can request access [here](https://aka.ms/oaiapply). You can also visit [here](https://azure.microsoft.com/free/cognitive-search/) to get some free Azure credits to get you started.
@@ -26,8 +35,8 @@ The repo includes sample data so it's ready to try end to end. In this sample ap
2635
2736
### Prerequisites
2837

29-
#### To Run Locally
30-
38+
* [Java 17](https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-17)
39+
* [Maven 3.8.x](https://maven.apache.org/download.cgi)
3140
* [Azure Developer CLI](https://aka.ms/azure-dev/install)
3241
* [Python 3+](https://www.python.org/downloads/)
3342
* **Important**: Python and the pip package manager must be in the path in Windows for the setup scripts to work.
@@ -37,25 +46,12 @@ The repo includes sample data so it's ready to try end to end. In this sample ap
3746
* [Powershell 7+ (pwsh)](https://github.com/powershell/powershell) - For Windows users only.
3847
* **Important**: Ensure you can run `pwsh.exe` from a PowerShell command. If this fails, you likely need to upgrade PowerShell.
3948

40-
>NOTE: Your Azure Account must have `Microsoft.Authorization/roleAssignments/write` permissions, such as [User Access Administrator](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#user-access-administrator) or [Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#owner).
41-
42-
#### To Run in GitHub Codespaces or VS Code Remote Containers
43-
44-
You can run this repo virtually by using GitHub Codespaces or VS Code Remote Containers. Click on one of the buttons below to open this repo in one of those options.
4549

46-
[![Open in GitHub Codespaces](https://img.shields.io/static/v1?style=for-the-badge&label=GitHub+Codespaces&message=Open&color=brightgreen&logo=github)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=599293758&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=WestUs2)
47-
[![Open in Remote - Containers](https://img.shields.io/static/v1?style=for-the-badge&label=Remote%20-%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/azure-samples/azure-search-openai-demo)
50+
>NOTE: The initial cognitive search documents indexing process (triggered as post provision task by azd) is still using the original python scripts. That's why python is still required to run this java example.
4851
49-
### Installation
50-
51-
#### Project Initialization
52-
53-
1. Create a new folder and switch to it in the terminal
54-
1. Run `azd auth login`
55-
1. Run `azd init -t azure-search-openai-demo`
56-
* note that this command will initialize a git repository and you do not need to clone this repository
52+
>NOTE: Your Azure Account must have `Microsoft.Authorization/roleAssignments/write` permissions, such as [User Access Administrator](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#user-access-administrator) or [Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#owner).
5753
58-
#### Starting from scratch
54+
### Starting from scratch
5955

6056
Execute the following command, if you don't have any pre-existing Azure services and want to start from a fresh deployment.
6157

@@ -67,7 +63,7 @@ It will look like the following:
6763

6864
!['Output from running azd up'](assets/endpoint.png)
6965

70-
> NOTE: It may take a minute for the application to be fully deployed. If you see a "Python Developer" welcome screen, then wait a minute and refresh the page.
66+
> NOTE: It may take a minute for the application to be fully deployed.
7167
7268
#### Use existing resources
7369

@@ -79,29 +75,17 @@ It will look like the following:
7975

8076
> NOTE: You can also use existing Search and Storage Accounts. See `./infra/main.parameters.json` for list of environment variables to pass to `azd env set` to configure those existing resources.
8177
82-
#### Deploying or re-deploying a local clone of the repo
83-
84-
* Simply run `azd up`
85-
86-
#### Running locally
78+
### Running locally
8779

8880
1. Run `azd login`
8981
2. Change dir to `app`
9082
3. Run `./start.ps1` or `./start.sh` or run the "VS Code Task: Start App" to start the project locally.
83+
4. Wait for the spring boot server to start and refresh your browser to localhost:8080
9184

92-
#### Sharing Environments
93-
94-
Run the following if you want to give someone else access to completely deployed and existing environment.
95-
96-
1. Install the [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
97-
1. Run `azd init -t azure-search-openai-demo`
98-
1. Run `azd env refresh -e {environment name}` - Note that they will need the azd environment name, subscription Id, and location to run this command - you can find those values in your `./azure/{env name}/.env` file. This will populate their azd environment's .env file with all the settings needed to run the app locally.
99-
1. Run `pwsh ./scripts/roles.ps1` - This will assign all of the necessary roles to the user so they can run the app locally. If they do not have the necessary permission to create roles in the subscription, then you may need to run this script for them. Just be sure to set the `AZURE_PRINCIPAL_ID` environment variable in the azd .env file or in the active shell to their Azure Id, which they can get with `az account show`.
100-
101-
### Quickstart
85+
### UI Navigation
10286

10387
* In Azure: navigate to the Azure WebApp deployed by azd. The URL is printed out when azd completes (as "Endpoint"), or you can find it in the Azure portal.
104-
* Running locally: navigate to 127.0.0.1:5000
88+
* Running locally: navigate to localhost:8080
10589

10690
Once in the web app:
10791

@@ -121,12 +105,31 @@ Once in the web app:
121105
122106
### FAQ
123107

124-
***Question***: Why do we need to break up the PDFs into chunks when Azure Cognitive Search supports searching large documents?
108+
<details>
109+
<summary>Why do we need to break up the PDFs into chunks when Azure Cognitive Search supports searching large documents?</summary>
110+
111+
Chunking allows us to limit the amount of information we send to OpenAI due to token limits. By breaking up the content, it allows us to easily find potential chunks of text that we can inject into OpenAI. The method of chunking we use leverages a sliding window of text such that sentences that end one chunk will start the next. This allows us to reduce the chance of losing the context of the text.
112+
</details>
125113

126-
***Answer***: Chunking allows us to limit the amount of information we send to OpenAI due to token limits. By breaking up the content, it allows us to easily find potential chunks of text that we can inject into OpenAI. The method of chunking we use leverages a sliding window of text such that sentences that end one chunk will start the next. This allows us to reduce the chance of losing the context of the text.
114+
<details>
115+
<summary>How can we upload additional PDFs without redeploying everything?</summary>
116+
117+
To upload more PDFs, put them in the data/ folder and run `./scripts/prepdocs.sh` or `./scripts/prepdocs.ps1`. To avoid reuploading existing docs, move them out of the data folder. You could also implement checks to see whats been uploaded before; our code doesn't yet have such checks.
118+
</details>
127119

128120
### Troubleshooting
129121

130-
If you see this error while running `azd deploy`: `read /tmp/azd1992237260/backend_env/lib64: is a directory`, then delete the `./app/backend/backend_env folder` and re-run the `azd deploy` command. This issue is being tracked here: <https://github.com/Azure/azure-dev/issues/1237>
122+
Here are the most common failure scenarios and solutions:
123+
124+
1. The subscription (`AZURE_SUBSCRIPTION_ID`) doesn't have access to the Azure OpenAI service. Please ensure `AZURE_SUBSCRIPTION_ID` matches the ID specified in the [OpenAI access request process](https://aka.ms/oai/access).
125+
126+
1. You're attempting to create resources in regions not enabled for Azure OpenAI (e.g. East US 2 instead of East US), or where the model you're trying to use isn't enabled. See [this matrix of model availability](https://aka.ms/oai/models).
127+
128+
1. You've exceeded a quota, most often number of resources per region. See [this article on quotas and limits](https://aka.ms/oai/quotas).
129+
130+
1. You're getting "same resource name not allowed" conflicts. That's likely because you've run the sample multiple times and deleted the resources you've been creating each time, but are forgetting to purge them. Azure keeps resources for 48 hours unless you purge from soft delete. See [this article on purging resources](https://learn.microsoft.com/azure/cognitive-services/manage-resources?tabs=azure-portal#purge-a-deleted-resource).
131+
132+
1. You see `CERTIFICATE_VERIFY_FAILED` when the `prepdocs.py` script runs. That's typically due to incorrect SSL certificates setup on your machine. Try the suggestions in this [StackOverflow answer](https://stackoverflow.com/questions/35569042/ssl-certificate-verify-failed-with-python3/43855394#43855394).
131133

132-
If the web app fails to deploy and you receive a '404 Not Found' message in your browser, run `azd deploy`.
134+
1. After running `azd up` and visiting the website, you see a '404 Not Found' in the browser. Wait 10 minutes and try again, as it might be still starting up. Then try running `azd deploy` and wait again. If you still encounter errors with the deployed app, consult these [tips for debugging Flask app deployments](http://blog.pamelafox.org/2023/06/tips-for-debugging-flask-deployments-to.html)
135+
and file an issue if the error logs don't help you resolve the issue.
-17 Bytes
Binary file not shown.
Binary file not shown.

app/backend/.gradle/7.4.2/dependencies-accessors/gc.properties

Whitespace-only changes.
Binary file not shown.
Binary file not shown.

app/backend/.gradle/7.4.2/gc.properties

Whitespace-only changes.

app/backend/.gradle/vcs-1/gc.properties

Whitespace-only changes.
-58.4 KB
Binary file not shown.

app/backend/gradle/wrapper/gradle-wrapper.properties

-5
This file was deleted.

app/backend/src/main/java/com/microsoft/openai/samples/rag/config/CognitiveSearchConfiguration.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class CognitiveSearchConfiguration {
2525

2626
@Bean
2727
@ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "true")
28-
public SearchClient tracingEnabledClient() {
28+
public SearchClient searchTracingEnabledClient() {
2929
String endpoint = "https://%s.search.windows.net".formatted(searchServiceName);
3030

3131
var httpLogOptions = new HttpLogOptions();
@@ -44,7 +44,7 @@ public SearchClient tracingEnabledClient() {
4444

4545
@Bean
4646
@ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "false")
47-
public SearchClient productionEnabledClient() {
47+
public SearchClient searchDefaultClient() {
4848
String endpoint = "https://%s.search.windows.net".formatted(searchServiceName);
4949
return new SearchClientBuilder()
5050
.endpoint(endpoint)

app/backend/src/main/java/com/microsoft/openai/samples/rag/config/OpenAIConfiguration.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class OpenAIConfiguration {
2424

2525
@Bean
2626
@ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "true")
27-
public OpenAIClient tracingEnabledClient() {
27+
public OpenAIClient openAItracingEnabledClient() {
2828
String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName);
2929

3030
var httpLogOptions = new HttpLogOptions();
@@ -42,7 +42,7 @@ public OpenAIClient tracingEnabledClient() {
4242

4343
@Bean
4444
@ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "false")
45-
public OpenAIClient defaultClient() {
45+
public OpenAIClient openAIDefaultClient() {
4646
String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName);
4747
return new OpenAIClientBuilder()
4848
.endpoint(endpoint)

app/backend/src/main/resources/application.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ spring.main.lazy-initialization=true
44
openai.service=${AZURE_OPENAI_SERVICE:cog-hxy5hdyir5eaa}
55
openai.chatgpt.deployment=${AZURE_OPENAI_CHATGPT_DEPLOYMENT:chat}
66
openai.gpt.deployment=${AZURE_OPENAI_GPT_DEPLOYMENT:davinci}
7-
openai.tracing.enabled=${AZURE_OPENAI_TRACING_ENABLED:false}
7+
openai.tracing.enabled=${AZURE_OPENAI_TRACING_ENABLED:true}
88

99
cognitive.search.service=${AZURE_SEARCH_SERVICE:gptkb-hxy5hdyir5eaa}
1010
cognitive.search.index=${AZURE_SEARCH_INDEX:gptkbindex}

app/backend/src/test/java/com/microsoft/openai/samples/rag/AskAPITests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
/**
3535
* This class tests the Ask API showcasing how you can mock azure services using mockito.
3636
* CognitiveSearch and OpenAI models are immutable from the client usage perspective, so in order to create when/then condition with mockito
37-
* we used a reflection hack to make some model constructor public. @see CognitiveSearchUnitTestUtils and @see OpenAIUnitTestUtils for more info.
37+
* we used a reflection hack to make some model private constructor public. @see CognitiveSearchUnitTestUtils and @see OpenAIUnitTestUtils for more info.
3838
*/
3939
@ActiveProfiles("test")
4040
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

app/start.sh

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
#!/bin/sh
22

3-
#echo ""
4-
#echo "Loading azd .env file from current environment"
5-
#echo ""
3+
echo ""
4+
echo "Loading azd .env file from current environment"
5+
echo ""
66

7-
#while IFS='=' read -r key value; do
8-
# value=$(echo "$value" | sed 's/^"//' | sed 's/"$//')
9-
# export "$key=$value"
10-
#done <<EOF
11-
#$(azd env get-values)
12-
#EOF
7+
while IFS='=' read -r key value; do
8+
value=$(echo "$value" | sed 's/^"//' | sed 's/"$//')
9+
export "$key=$value"
10+
echo "export $key=$value"
11+
done <<EOF
12+
$(azd env get-values)
13+
EOF
1314

14-
#if [ $? -ne 0 ]; then
15-
# echo "Failed to load environment variables from azd environment"
16-
# exit $?
17-
#fi
15+
if [ $? -ne 0 ]; then
16+
echo "Failed to load environment variables from azd environment"
17+
exit $?
18+
fi
1819

1920
echo ""
2021
echo "Restoring frontend npm packages"
@@ -39,6 +40,7 @@ fi
3940

4041
echo ""
4142
echo "Starting spring boot api backend and react spa from backend/public static content"
43+
echo "Spring-boot application.properties use values from azd .env file which have been exported as environment variables"
4244
echo ""
4345

4446
cd ../backend

docs/appcomponents.png

28.7 KB
Loading

infra/main.bicep

+3-2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ resource openAi 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = if
8181
}
8282
*/
8383

84+
8485
// Create an App Service Plan to group applications under the same payment plan and SKU
8586
module appServicePlan 'core/host/appserviceplan.bicep' = {
8687
name: 'appserviceplan'
@@ -125,6 +126,7 @@ module backend 'core/host/appservice.bicep' = {
125126
}
126127

127128

129+
128130
module openAi 'core/ai/cognitiveservices.bicep' = {
129131
name: 'openai'
130132
scope: openAiResourceGroup
@@ -136,7 +138,6 @@ module openAi 'core/ai/cognitiveservices.bicep' = {
136138
name: openAiSkuName
137139
}
138140
deployments: [
139-
/** text-davinci-003 is not available anymore. need to wait for gpt-35-turbo-instruct to become available and update the below deployment
140141
{
141142
name: gptDeploymentName
142143
model: {
@@ -149,7 +150,7 @@ module openAi 'core/ai/cognitiveservices.bicep' = {
149150
capacity: gptDeploymentCapacity
150151
}
151152
}
152-
*/
153+
153154
{
154155
name: chatGptDeploymentName
155156
model: {

0 commit comments

Comments
 (0)