Skip to content

Commit

Permalink
Merge branch 'microsoft:main' into azure-ad-allowed-principals
Browse files Browse the repository at this point in the history
  • Loading branch information
yaegashi authored Oct 4, 2023
2 parents e3515ed + 5a54d51 commit 81424e0
Show file tree
Hide file tree
Showing 46 changed files with 1,131 additions and 497 deletions.
File renamed without changes.
28 changes: 16 additions & 12 deletions docs/3-run-locally.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,21 @@ Clone this repository locally or fork to your Github account. Run all of the the

- **History Database**: If you didn't [provision the Azure resources](2-provision-azure-resources.md), you **must** at least deploy an instance of Cosmos DB in your Azure Subscription to store chat history.

- **Identity Provider**: Follow the [instructions](3-run-locally.md) to add one.
- **Identity Provider**: For local development, you have the option of using a username / password. If you prefer to use an Identity Provider, follow the [instructions](3-run-locally.md) to add one.

## Steps

1. Change directory to the `src` folder
2. Create a new file named `.env.local` to store the environment variables add the following variables.

> **Note**
> Do not use double-quotes and do not delete any of the variables.
> **Note**
> Make sure that `NEXTAUTH_URL=http://localhost:3000` has no comments in the same line.
3. <details><summary>Set the following environmnet variables</summary>
2. Copy the file `.env.example` and rename it to `.env.local`.
3. Populate the environment variables in this file.
<details><summary>Environment Variables (ref src/.env.example)</summary>

```bash
# Set your environment details
# NOTES:
# - Do not use double-quotes and do not delete any of the variables.
# - Make sure that NEXTAUTH_URL=http://localhost:3000 has no comments in the same line.

# Update your Azure OpenAI details
# AZURE_OPENAI_API_INSTANCE_NAME should be just the name of azure openai resource and not the full url;
# AZURE_OPENAI_API_DEPLOYMENT_NAME should be deployment name from your azure openai studio and not the model name.
# AZURE_OPENAI_API_VERSION should be Supported versions checkout docs https://learn.microsoft.com/en-us/azure/ai-services/openai/reference
Expand Down Expand Up @@ -71,7 +69,13 @@ Clone this repository locally or fork to your Github account. Run all of the the
5. Start the app by running `npm run dev`
6. Access the app on [http://localhost:3000](http://localhost:3000)

You should now be prompted to login with your chosen OAuth provider. Once successfully logged in, you can start creating new conversations.
You should now be prompted to login with your chosen OAuth provider.
> NOTE: If using Basic Auth (DEV ONLY) any username you enter will create a new user id (hash of username@localhost). You can use this to simulate multiple users.

![Chat Login (DEV)](/images/chat-login-dev.png)


Once successfully logged in, you can start creating new conversations.

![Chat Home](/images/chat-home.png)
![Chat history](/images/chat-history.png)
Expand Down
6 changes: 4 additions & 2 deletions docs/7-environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ Below are the required environment variables, to be added to the Azure Portal or
| `AZURE_SEARCH_NAME` | `https://AZURE_SEARCH_NAME.search.windows.net` | The deployment name of your Azure Cognitive Search |
| `AZURE_SEARCH_INDEX_NAME` | | The index name with [vector search](https://learn.microsoft.com/en-us/azure/search/vector-search-overview) enabled |
| `AZURE_SEARCH_API_VERSION` | `2023-07-01-Preview` | API version which supports vector search `2023-07-01-Preview` |
| `AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT` | `https://REGION.api.cognitive.microsoft.com/` | Endpoint url of the Azure document intelligence. The REGION is specific to your Azure resource location |
| `AZURE_DOCUMENT_INTELLIGENCE_KEY` | | API keys of your Azure Document intelligence resource |
| `AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT` | `https://NAME.api.cognitive.microsoft.com/` | Endpoint url of the Azure document intelligence. The REGION is specific to your Azure resource location |
| `AZURE_SPEECH_REGION` | australiaeast | Region of your Azure Speech service |
| `AZURE_SPEECH_KEY` | | API Key of Azure Speech service |
| |
Binary file added images/chat-login-dev.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 33 additions & 1 deletion infra/resources.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ param embeddingDeploymentName string = 'text-embedding-ada-002'
param embeddingDeploymentCapacity int = 30
param embeddingModelName string = 'text-embedding-ada-002'

param speechServiceSkuName string = 'S0'
param formRecognizerSkuName string = 'S0'
param searchServiceSkuName string = 'standard'
param searchServiceIndexName string = 'azure-chat'
Expand All @@ -27,6 +28,7 @@ param tags object = {}

var openai_name = toLower('${name}ai${resourceToken}')
var form_recognizer_name = toLower('${name}-form-${resourceToken}')
var speech_service_name = toLower('${name}-speech-${resourceToken}')
var cosmos_name = toLower('${name}-cosmos-${resourceToken}')
var search_name = toLower('${name}search${resourceToken}')
var webapp_name = toLower('${name}-webapp-${resourceToken}')
Expand Down Expand Up @@ -127,7 +129,7 @@ resource webApp 'Microsoft.Web/sites@2020-06-01' = {
}
{
name: 'AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT'
value: 'https://${location}.api.cognitive.microsoft.com/'
value: 'https://${form_recognizer_name}.cognitiveservices.azure.com/'
}
{
name: 'SCM_DO_BUILD_DURING_DEPLOYMENT'
Expand Down Expand Up @@ -161,6 +163,14 @@ resource webApp 'Microsoft.Web/sites@2020-06-01' = {
name: 'NEXTAUTH_URL'
value: 'https://${webapp_name}.azurewebsites.net'
}
{
name: 'AZURE_SPEECH_REGION'
value: resourceGroup().location
}
{
name: 'AZURE_SPEECH_KEY'
value: '@Microsoft.KeyVault(VaultName=${kv.name};SecretName=${kv::AZURE_SPEECH_KEY.name})'
}
]
}
}
Expand Down Expand Up @@ -236,6 +246,15 @@ resource kv 'Microsoft.KeyVault/vaults@2021-06-01-preview' = {
}
}

resource AZURE_SPEECH_KEY 'secrets' = {
name: 'AZURE-SPEECH-KEY'
properties: {
contentType: 'text/plain'
value: speechService.listKeys().key1
}
}


resource AZURE_SEARCH_API_KEY 'secrets' = {
name: 'AZURE-SEARCH-API-KEY'
properties: {
Expand Down Expand Up @@ -351,5 +370,18 @@ resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2023-05-01
}
}]

resource speechService 'Microsoft.CognitiveServices/accounts@2023-05-01' = {
name: speech_service_name
location: location
tags: tags
kind: 'SpeechServices'
properties: {
customSubDomainName: speech_service_name
publicNetworkAccess: 'Enabled'
}
sku: {
name: speechServiceSkuName
}
}

output url string = 'https://${webApp.properties.defaultHostName}'
14 changes: 11 additions & 3 deletions src/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# NOTES:
# - Do not use double-quotes and do not delete any of the variables.
# - Make sure that NEXTAUTH_URL=http://localhost:3000 has no comments in the same line.

# Update your Azure OpenAI details
# AZURE_OPENAI_API_INSTANCE_NAME should be just the name of azure openai resource and not the full url;
# AZURE_OPENAI_API_DEPLOYMENT_NAME should be deployment name from your azure openai studio and not the model name.
Expand All @@ -11,7 +15,7 @@ AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME=
# Update your admin email addresses - comma separated
ADMIN_EMAIL_ADDRESS="[email protected],[email protected]"

# You must have atleast one of the following auth providers configured
# Identity provider is optional if you are running in development mode locally (npm run dev)
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=

Expand All @@ -38,5 +42,9 @@ AZURE_SEARCH_INDEX_NAME=
AZURE_SEARCH_API_VERSION="2023-07-01-Preview"

# Azure AI Document Intelligence to extract content from your data
AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT="https://REGION.api.cognitive.microsoft.com/"
AZURE_DOCUMENT_INTELLIGENCE_KEY=
AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT="https://NAME.api.cognitive.microsoft.com/"
AZURE_DOCUMENT_INTELLIGENCE_KEY=

# Azure Speech to Text to convert audio to text
AZURE_SPEECH_REGION=""
AZURE_SPEECH_KEY=""
4 changes: 2 additions & 2 deletions src/app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PromptGPT } from "@/features/chat/chat-services/chat-api";
import { chatAPIEntry } from "@/features/chat/chat-services/chat-api-entry";

export async function POST(req: Request) {
const body = await req.json();
return await PromptGPT(body);
return await chatAPIEntry(body);
}
7 changes: 6 additions & 1 deletion src/app/chat/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FindAllChats } from "@/features/chat/chat-services/chat-service";
import { FindChatThreadByID } from "@/features/chat/chat-services/chat-thread-service";
import { ChatProvider } from "@/features/chat/chat-ui/chat-context";
import { ChatUI } from "@/features/chat/chat-ui/chat-ui";
import { notFound } from "next/navigation";

Expand All @@ -15,5 +16,9 @@ export default async function Home({ params }: { params: { id: string } }) {
notFound();
}

return <ChatUI chats={items} chatThread={thread[0]} />;
return (
<ChatProvider id={params.id} chats={items} chatThread={thread[0]}>
<ChatUI />
</ChatProvider>
);
}
2 changes: 1 addition & 1 deletion src/app/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Card } from "@/components/ui/card";
import { StartNewChat } from "@/features/chat/chat-ui/start-new-chat";
import { StartNewChat } from "@/features/chat/chat-ui/chat-empty-state/start-new-chat";

export const dynamic = "force-dynamic";

Expand Down
94 changes: 0 additions & 94 deletions src/components/chat/chat-input.tsx

This file was deleted.

3 changes: 3 additions & 0 deletions src/components/login/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export const LogIn = () => {
<CardContent className="grid gap-4">
<Button onClick={() => signIn("github")}>GitHub</Button>
<Button onClick={() => signIn("azure-ad")}> Microsoft 365</Button>
{process.env.NODE_ENV === "development" && (
<Button onClick={() => signIn("localdev")}>Basic Auth (DEV ONLY)</Button>
)}
</CardContent>
</Card>
);
Expand Down
35 changes: 35 additions & 0 deletions src/features/auth/auth-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import NextAuth, { NextAuthOptions } from "next-auth";
import { Provider } from "next-auth/providers";
import AzureADProvider from "next-auth/providers/azure-ad";
import GitHubProvider from "next-auth/providers/github";
import CredentialsProvider from "next-auth/providers/credentials";
import { hashValue } from "./helpers";

const configureIdentityProvider = () => {
const providers: Array<Provider> = [];
Expand Down Expand Up @@ -96,6 +98,39 @@ const configureIdentityProvider = () => {
})
);
}

// If we're in local dev, add a basic credential provider option as well
// (Useful when a dev doesn't have access to create app registration in their tenant)
// This currently takes any username and makes a user with it, ignores password
// Refer to: https://next-auth.js.org/configuration/providers/credentials
if (process.env.NODE_ENV === "development") {
providers.push(
CredentialsProvider({
name: "localdev",
credentials: {
username: { label: "Username", type: "text", placeholder: "dev" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req): Promise<any> {
// You can put logic here to validate the credentials and return a user.
// We're going to take any username and make a new user with it
// Create the id as the hash of the email as per userHashedId (helpers.ts)
const username = credentials?.username || "dev";
const email = username + "@localhost";
const user = {
id: hashValue(email),
name: username,
email: email,
isAdmin: false,
image: "",
};
console.log("=== DEV USER LOGGED IN:\n", JSON.stringify(user, null, 2));
return user;
}
})
);
}

return providers;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
SystemMessagePromptTemplate,
} from "langchain/prompts";
import { AzureCogSearch } from "../../langchain/vector-stores/azure-cog-search/azure-cog-vector-store";
import { insertPromptAndResponse } from "../chat-services/chat-service";
import { initAndGuardChatSession } from "../chat-services/chat-thread-service";
import { FaqDocumentIndex, PromptGPTProps } from "../chat-services/models";
import { transformConversationStyleToTemperature } from "../chat-services/utils";
import { insertPromptAndResponse } from "./chat-service";
import { initAndGuardChatSession } from "./chat-thread-service";
import { FaqDocumentIndex, PromptGPTProps } from "./models";
import { transformConversationStyleToTemperature } from "./utils";

export const ChatData = async (props: PromptGPTProps) => {
export const ChatAPIData = async (props: PromptGPTProps) => {
const { lastHumanMessage, id, chatThread } = await initAndGuardChatSession(
props
);
Expand Down
15 changes: 15 additions & 0 deletions src/features/chat/chat-services/chat-api-entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ChatAPIData } from "./chat-api-data";
import { ChatAPISimple } from "./chat-api-simple";
import { PromptGPTProps } from "./models";

export const chatAPIEntry = async (props: PromptGPTProps) => {
if (props.chatType === "simple") {
return await ChatAPISimple(props);
} else if (props.chatType === "data") {
return await ChatAPIData(props);
} else if (props.chatType === "mssql") {
return await ChatAPIData(props);
} else {
return await ChatAPISimple(props);
}
};
Loading

0 comments on commit 81424e0

Please sign in to comment.