diff --git a/.env.sample b/.env.sample index 652917074..0757696f8 100644 --- a/.env.sample +++ b/.env.sample @@ -49,4 +49,4 @@ ORCHESTRATION_STRATEGY=openai_functions #Speech-to-text feature AZURE_SPEECH_SERVICE_KEY= AZURE_SPEECH_SERVICE_REGION= -AZURE_AUTH_TYPE=rbac +AZURE_AUTH_TYPE=rbac \ No newline at end of file diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml new file mode 100644 index 000000000..ef153c6ba --- /dev/null +++ b/.github/workflows/unittests.yml @@ -0,0 +1,25 @@ +name: Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_call: + +jobs: + test_package: + name: Unit Tests + runs-on: "ubuntu-20.04" + steps: + - uses: actions/checkout@v4 + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + architecture: x64 + - name: Install dependencies + run: | + pip install -r code/requirements.txt + - name: Run Python tests + run: python -m pytest --rootdir=code -m "not azure" diff --git a/README.md b/README.md index 9e73ea663..165a121e3 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,8 @@ Learn more about deploying the Teams extension [here](./docs/TEAMS_EXTENSION.md) ![One-click Deploy](/media/oneClickDeploy.png) ## One-click deploy ### Pre-requisites -* An [Azure OpenAI resource](https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource?pivots=web-portal) and a deployment for one of the following Chat model and an embedding model: +- Azure subscription - [Create one for free](https://azure.microsoft.com/free/) with owner access. +- An [Azure OpenAI resource](https://learn.microsoft.com/azure/ai-services/openai/how-to/create-resource?pivots=web-portal) and a deployment for one of the following Chat model and an embedding model: * Chat Models * GPT-3.5 * GPT-4 @@ -105,7 +106,6 @@ Learn more about deploying the Teams extension [here](./docs/TEAMS_EXTENSION.md) **Note**: The deployment template defaults to **gpt-35-turbo** and **text-embedding-ada-002**. If your deployment names are different, update them in the deployment process. -- Azure subscription - [Create one for free](https://azure.microsoft.com/free/) with contributor access. - [Visual Studio Code](https://code.visualstudio.com/) - Extensions - [Azure Functions](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions) diff --git a/code/utilities/tests/__init__.py b/code/__init__.py similarity index 100% rename from code/utilities/tests/__init__.py rename to code/__init__.py diff --git a/code/app/app.py b/code/app/app.py index fbb45f5f2..deb08221e 100644 --- a/code/app/app.py +++ b/code/app/app.py @@ -61,7 +61,7 @@ def get_config(): AZURE_OPENAI_API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2023-06-01-preview") AZURE_OPENAI_STREAM = os.environ.get("AZURE_OPENAI_STREAM", "true") AZURE_OPENAI_MODEL_NAME = os.environ.get("AZURE_OPENAI_MODEL_NAME", "gpt-35-turbo") # Name of the model, e.g. 'gpt-35-turbo' or 'gpt-4' -AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "rbac") +AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "keys") SHOULD_STREAM = True if AZURE_OPENAI_STREAM.lower() == "true" else False diff --git a/code/app/frontend/src/components/Answer/Answer.module.css b/code/app/frontend/src/components/Answer/Answer.module.css index b8377feec..fe626ec5e 100644 --- a/code/app/frontend/src/components/Answer/Answer.module.css +++ b/code/app/frontend/src/components/Answer/Answer.module.css @@ -7,6 +7,7 @@ background: #FFFFFF; box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.14), 0px 0px 2px rgba(0, 0, 0, 0.12); border-radius: 5.419px; + max-width: 100%; } .answerText { @@ -29,11 +30,9 @@ .answerFooter { display: flex; - flex-flow: row nowrap; + flex-direction: column; width: 100%; - height: auto; box-sizing: border-box; - justify-content: space-between; } .answerDisclaimerContainer { @@ -47,7 +46,9 @@ font-weight: 400; font-size: 12px; line-height: 16px; - + margin-right: 5px; + margin-left: 10px; + padding-bottom:5px; display: flex; align-items: center; text-align: center; @@ -64,7 +65,7 @@ font-weight: 600; font-size: 12px; line-height: 16px; - + max-width: 100%; color: #115EA3; display: flex; flex-direction: row; @@ -174,4 +175,16 @@ sup { font-size: 10px; line-height: 10px; -} \ No newline at end of file +} + + +@media (max-width: 500px) { + .answerFooter { + flex-direction: column; + } + + .citationContainer { + width: 100%; + overflow-y: auto; + } + } \ No newline at end of file diff --git a/code/app/frontend/src/components/Answer/Answer.tsx b/code/app/frontend/src/components/Answer/Answer.tsx index 695b24c5b..26222761a 100644 --- a/code/app/frontend/src/components/Answer/Answer.tsx +++ b/code/app/frontend/src/components/Answer/Answer.tsx @@ -14,15 +14,19 @@ import supersub from 'remark-supersub' interface Props { answer: AskResponse; onCitationClicked: (citedDocument: Citation) => void; + index: number; } export const Answer = ({ answer, - onCitationClicked + onCitationClicked, + index, }: Props) => { const [isRefAccordionOpen, { toggle: toggleIsRefAccordionOpen }] = useBoolean(false); const filePathTruncationLimit = 50; + const messageBoxId = "message-" + index; + const parsedAnswer = useMemo(() => parseAnswer(answer), [answer]); const [chevronIsExpanded, setChevronIsExpanded] = useState(isRefAccordionOpen); @@ -57,15 +61,16 @@ export const Answer = ({ const handleCopy = () => { alert("Please consider where you paste this content."); }; - document.addEventListener("copy", handleCopy); + const messageBox = document.getElementById(messageBoxId); + messageBox?.addEventListener("copy", handleCopy); return () => { - document.removeEventListener("copy", handleCopy); + messageBox?.removeEventListener("copy", handleCopy); }; }, []); return ( <> - + - + + + AI-generated content may be incorrect + + {!!parsedAnswer.citations.length && ( @@ -92,12 +101,10 @@ export const Answer = ({ )} - - AI-generated content may be incorrect - + {chevronIsExpanded && -
+
{parsedAnswer.citations.map((citation, idx) => { return ( onCitationClicked(citation)} className={styles.citationContainer}> diff --git a/code/app/frontend/src/pages/chat/Chat.module.css b/code/app/frontend/src/pages/chat/Chat.module.css index 4423a75c5..89aa0499d 100644 --- a/code/app/frontend/src/pages/chat/Chat.module.css +++ b/code/app/frontend/src/pages/chat/Chat.module.css @@ -248,3 +248,57 @@ align-self: stretch; flex-grow: 0; } + +.MobileChatContainer{ + @media screen and (max-width: 600px) { + max-width: 100%; + margin: 0 auto; + padding: 8px; + + } +} + +.mobileStyles { + @media screen and (max-width: 600px) { + max-width: 100%; + flex-grow: 1; + max-height: 100vh; + } + } + + .mobileclearChatBroom{ + @media screen and (max-width: 600px) { + left: -30px; + + } + } + + .mobileCitationPanelTitle{ + @media screen and (max-width: 600px) { + font-weight: 400; + font-size: 12px; + margin-top: 8px; + margin-bottom: 8px; + + } + } + + .mobileCitationPanelContent{ + @media screen and (max-width: 600px){ + font-weight: 250; + font-size: 11px; + + } + } + + @media screen and (max-width: 600px){ + h1{ + font-weight: 300; + font-size: 14px; + } + + h2{ + font-weight: 300; + font-size: 12px; + } + } \ No newline at end of file diff --git a/code/app/frontend/src/pages/chat/Chat.tsx b/code/app/frontend/src/pages/chat/Chat.tsx index a1b74d9fe..eb0209936 100644 --- a/code/app/frontend/src/pages/chat/Chat.tsx +++ b/code/app/frontend/src/pages/chat/Chat.tsx @@ -265,7 +265,7 @@ const Chat = () => { return (
-
+
{!lastQuestionRef.current ? ( @@ -302,6 +302,7 @@ const Chat = () => { : [], }} onCitationClicked={(c) => onShowCitation(c)} + index={index} />
) : null} @@ -356,7 +357,7 @@ const Chat = () => { )} {
{answers.length > 0 && isCitationPanelOpen && activeCitation && ( - + { onClick={() => setIsCitationPanelOpen(false)} /> -
{activeCitation[2]}
+
{activeCitation[2]}
+ [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure-Samples%2Fchat-with-your-data-solution-accelerator%2Fmain%2Fextensions%2Finfrastructure%2Fmain.json) Note: The (p) suffix on the App Setting (below) means that you should use the same resources and services deployed during the [Chat with your data with speech-to-text deployment](../README.md) @@ -34,9 +33,9 @@ Note: The (p) suffix on the App Setting (below) means that you should use the sa |Resource group | The resource group that will contain the resources for this accelerator. You can select Create new to create a new group or use the existing resource group created with [Speech-to-text deployment](#speech-to-text-deployment). | |Resource prefix | A text string that will be appended to each resource that gets created, and used as the website name for the web app. This name cannot contain spaces or special characters. | |App Insights Connection String (p) | The Application Insights connection string to store the application logs. | -|Azure Cognitive Search (p) | The **name** of your Azure Cognitive Search resource. e.g. https://<**name**>.search.windows.net. | -|Azure Search Index (p) | The name of your Azure Cognitive Search Index. | -|Azure Search Key (p) | An admin key for your Azure Cognitive Search resource. | +|Azure AI Search (p) | The **name** of your Azure AI Search resource. e.g. https://<**name**>.search.windows.net. | +|Azure Search Index (p) | The name of your Azure AI Search Index. | +|Azure Search Key (p) | An admin key for your Azure AI Search resource. | |Azure OpenAI resource (p) | The name of your Azure OpenAI resource. This resource must have already been created previously. | |Azure OpenAI key (p) | The access key is associated with your Azure OpenAI resource. | |Orchestration strategy (p) | Use Azure OpenAI Functions (openai_functions) or LangChain (langchain) for messages orchestration. If you are using a new model version 0613 select "openai_functions" (or "langchain"), if you are using a model version 0314 select "langchain". | diff --git a/extensions/infrastructure/main.bicep b/extensions/infrastructure/main.bicep index 41849aea5..22d52530f 100644 --- a/extensions/infrastructure/main.bicep +++ b/extensions/infrastructure/main.bicep @@ -31,16 +31,16 @@ param HostingPlanSku string = 'B3' @secure() param AppInsightsConnectionString string -@description('Azure Cognitive Search Resource - Created during the "Chat with your data" Solution Accelerator') -param AzureCognitiveSearch string +@description('Azure AI Search Resource - Created during the "Chat with your data" Solution Accelerator') +param AzureSearchName string -@description('Azure Cognitive Search Index - Created during the "Chat with your data" Solution Accelerator') +@description('Azure AI Search Index - Created during the "Chat with your data" Solution Accelerator') param AzureSearchIndex string -@description('Azure Cognitive Search Conversation Log Index - Created during the "Chat with your data" Solution Accelerator') +@description('Azure AI Search Conversation Log Index - Created during the "Chat with your data" Solution Accelerator') param AzureSearchConversationLogIndex string = 'conversations' -@description('Azure Cognitive Search Key - Created during the "Chat with your data" Solution Accelerator') +@description('Azure AI Search Key - Created during the "Chat with your data" Solution Accelerator') @secure() param AzureSearchKey string @@ -154,7 +154,7 @@ resource Function 'Microsoft.Web/sites@2018-11-01' = { { name: 'FUNCTIONS_EXTENSION_VERSION', value: '~4'} { name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE', value: 'false'} { name: 'APPINSIGHTS_CONNECTION_STRING', value: AppInsightsConnectionString} - { name: 'AZURE_SEARCH_SERVICE', value: 'https://${AzureCognitiveSearch}.search.windows.net'} + { name: 'AZURE_SEARCH_SERVICE', value: 'https://${AzureSearchName}.search.windows.net'} { name: 'AZURE_SEARCH_INDEX', value: AzureSearchIndex} { name: 'AZURE_SEARCH_CONVERSATIONS_LOG_INDEX', value: AzureSearchConversationLogIndex} { name: 'AZURE_SEARCH_KEY', value: AzureSearchKey} diff --git a/extensions/infrastructure/main.json b/extensions/infrastructure/main.json index 2b69f75d7..e01afd9e7 100644 --- a/extensions/infrastructure/main.json +++ b/extensions/infrastructure/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "3711349996173669799" + "version": "0.24.24.22086", + "templateHash": "15613566963175325138" } }, "parameters": { @@ -63,29 +63,29 @@ "description": "Application Insights Connection String - Created during the \"Chat with your data\" Solution Accelerator" } }, - "AzureCognitiveSearch": { + "AzureSearchName": { "type": "string", "metadata": { - "description": "Azure Cognitive Search Resource - Created during the \"Chat with your data\" Solution Accelerator" + "description": "Azure AI Search Resource - Created during the \"Chat with your data\" Solution Accelerator" } }, "AzureSearchIndex": { "type": "string", "metadata": { - "description": "Azure Cognitive Search Index - Created during the \"Chat with your data\" Solution Accelerator" + "description": "Azure AI Search Index - Created during the \"Chat with your data\" Solution Accelerator" } }, "AzureSearchConversationLogIndex": { "type": "string", "defaultValue": "conversations", "metadata": { - "description": "Azure Cognitive Search Conversation Log Index - Created during the \"Chat with your data\" Solution Accelerator" + "description": "Azure AI Search Conversation Log Index - Created during the \"Chat with your data\" Solution Accelerator" } }, "AzureSearchKey": { "type": "securestring", "metadata": { - "description": "Azure Cognitive Search Key - Created during the \"Chat with your data\" Solution Accelerator" + "description": "Azure AI Search Key - Created during the \"Chat with your data\" Solution Accelerator" } }, "AzureSearchSemanticSearchConfig": { @@ -308,7 +308,7 @@ }, { "name": "AZURE_SEARCH_SERVICE", - "value": "[format('https://{0}.search.windows.net', parameters('AzureCognitiveSearch'))]" + "value": "[format('https://{0}.search.windows.net', parameters('AzureSearchName'))]" }, { "name": "AZURE_SEARCH_INDEX", diff --git a/infra/deployment.bicep b/infra/deployment.bicep index 32afb9d55..da644cf4f 100644 --- a/infra/deployment.bicep +++ b/infra/deployment.bicep @@ -151,7 +151,7 @@ param newGuidString string = newGuid() 'keys' 'rbac' ]) -param authType string = 'rbac' +param authType string = 'keys' @description('Id of the user or app to assign application roles') param principalId string = '' diff --git a/infra/deployment.json b/infra/deployment.json index 680aada12..505ba0d98 100644 --- a/infra/deployment.json +++ b/infra/deployment.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "1303744853928505438" + "version": "0.24.24.22086", + "templateHash": "9176113728480332345" } }, "parameters": { @@ -325,7 +325,7 @@ }, "authType": { "type": "string", - "defaultValue": "rbac", + "defaultValue": "keys", "allowedValues": [ "keys", "rbac" @@ -1163,8 +1163,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1232,8 +1232,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1301,8 +1301,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1370,8 +1370,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1439,8 +1439,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1508,8 +1508,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1574,8 +1574,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1643,8 +1643,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1712,8 +1712,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1781,8 +1781,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1850,8 +1850,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1919,8 +1919,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -1988,8 +1988,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2054,8 +2054,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2123,8 +2123,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2192,8 +2192,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2261,8 +2261,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2330,8 +2330,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2396,8 +2396,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2465,8 +2465,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2534,8 +2534,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2603,8 +2603,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2669,8 +2669,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2738,8 +2738,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2807,8 +2807,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, @@ -2876,8 +2876,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "8211880587811090337" + "version": "0.24.24.22086", + "templateHash": "2184194315885104837" }, "description": "Creates a role assignment for a service principal." }, diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..c453246ed --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +markers = + unittest: Unit Tests (relatively fast) + azure: marks tests as extended (run less frequently, relatively slow) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..e69de29bb diff --git a/code/utilities/tests/test_AzureBlobStorage.py b/tests/test_AzureBlobStorage.py similarity index 79% rename from code/utilities/tests/test_AzureBlobStorage.py rename to tests/test_AzureBlobStorage.py index f3d3a4662..33f192a0b 100644 --- a/code/utilities/tests/test_AzureBlobStorage.py +++ b/tests/test_AzureBlobStorage.py @@ -1,10 +1,11 @@ import pytest -from ..helpers.AzureBlobStorageHelper import AzureBlobStorageClient +from code.utilities.helpers.AzureBlobStorageHelper import AzureBlobStorageClient @pytest.fixture def blob_client(): return AzureBlobStorageClient() +@pytest.mark.azure("This test requires Azure Blob Storage") def test_upload_and_download_file(blob_client): # Upload a file file_name = "test_file.txt" diff --git a/code/utilities/tests/test_ContentSafetyChecker.py b/tests/test_ContentSafetyChecker.py similarity index 77% rename from code/utilities/tests/test_ContentSafetyChecker.py rename to tests/test_ContentSafetyChecker.py index 606b5d98f..a0978f95d 100644 --- a/code/utilities/tests/test_ContentSafetyChecker.py +++ b/tests/test_ContentSafetyChecker.py @@ -1,6 +1,7 @@ import pytest -from ..tools.ContentSafetyChecker import ContentSafetyChecker +from code.utilities.tools.ContentSafetyChecker import ContentSafetyChecker +@pytest.mark.azure("This test requires Azure Content Safety configured") def test_document_chunking_layout(): cut = ContentSafetyChecker() diff --git a/code/utilities/tests/test_DocumentChunking.py b/tests/test_DocumentChunking.py similarity index 95% rename from code/utilities/tests/test_DocumentChunking.py rename to tests/test_DocumentChunking.py index 2dda11c5a..9a9b4bbc4 100644 --- a/code/utilities/tests/test_DocumentChunking.py +++ b/tests/test_DocumentChunking.py @@ -1,7 +1,7 @@ import pytest from typing import List -from ..common.SourceDocument import SourceDocument -from ..helpers.DocumentChunkingHelper import DocumentChunking, ChunkingSettings, ChunkingStrategy +from code.utilities.common.SourceDocument import SourceDocument +from code.utilities.helpers.DocumentChunkingHelper import DocumentChunking, ChunkingSettings, ChunkingStrategy # Create a sample document documents = [ @@ -19,6 +19,7 @@ ) ] +@pytest.mark.unittest("DocumentChunking") def test_document_chunking_layout(): # Test layout chunking strategy chunking = ChunkingSettings({"strategy": ChunkingStrategy.LAYOUT, "size": 10, "overlap": 5}) diff --git a/code/utilities/tests/test_DocumentLoading.py b/tests/test_DocumentLoading.py similarity index 83% rename from code/utilities/tests/test_DocumentLoading.py rename to tests/test_DocumentLoading.py index 15eea5af4..07bc02770 100644 --- a/code/utilities/tests/test_DocumentLoading.py +++ b/tests/test_DocumentLoading.py @@ -1,8 +1,8 @@ import pytest from typing import List -from ..helpers.DocumentLoadingHelper import DocumentLoading, LoadingSettings - +from code.utilities.helpers.DocumentLoadingHelper import DocumentLoading, LoadingSettings +@pytest.mark.azure("This test requires Azure Document Intelligence configured") def test_document_loading_layout(): # Azure Form Recognizer Layout document_loading = DocumentLoading() @@ -15,6 +15,7 @@ def test_document_loading_layout(): assert data[4].page_number == 4 assert data[4].source == url +@pytest.mark.azure("This test requires Azure Document Intelligence configured") def test_document_loading_read(): # Azure Form Recognizer Read document_loading = DocumentLoading() @@ -34,7 +35,8 @@ def test_document_loading_web(): data = document_loading.load(url, LoadingSettings({"strategy": "web"})) assert len(data) == 1 assert data[0].source == url - + +@pytest.mark.azure("This test requires Azure Document Intelligence configured") def test_document_loading_docx(): document_loading = DocumentLoading() url = "https://csciblob.blob.core.windows.net/rag-sol-acc/What is Azure OpenAI Service.docx" diff --git a/code/utilities/tests/test_DocumentProcessor.py b/tests/test_DocumentProcessor.py similarity index 83% rename from code/utilities/tests/test_DocumentProcessor.py rename to tests/test_DocumentProcessor.py index c06100d31..b2943e269 100644 --- a/code/utilities/tests/test_DocumentProcessor.py +++ b/tests/test_DocumentProcessor.py @@ -1,12 +1,12 @@ import pytest -from ..helpers.DocumentProcessorHelper import DocumentProcessor -from ..helpers.ConfigHelper import ConfigHelper +from code.utilities.helpers.DocumentProcessorHelper import DocumentProcessor +from code.utilities.helpers.ConfigHelper import ConfigHelper document_url = "https://csciblob.blob.core.windows.net/rag-sol-acc/cognitive-services.pdf" url = "https://learn.microsoft.com/en-us/azure/search/search-what-is-azure-search" docx_url = "https://csciblob.blob.core.windows.net/rag-sol-acc/What is Azure OpenAI Service.docx" - +@pytest.mark.azure("This test requires Azure") def test_document_processor_layout(): document_processor = DocumentProcessor() processors = list(filter(lambda x : x.document_type == 'pdf', ConfigHelper.get_active_config_or_default().document_processors)) @@ -15,6 +15,7 @@ def test_document_processor_layout(): assert len(keys) > 0 +@pytest.mark.azure("This test requires Azure") def test_document_processor_read(): document_processor = DocumentProcessor() processors = list(filter(lambda x : x.document_type == 'pdf', ConfigHelper.get_active_config_or_default().document_processors)) @@ -23,6 +24,7 @@ def test_document_processor_read(): assert len(keys) > 0 +@pytest.mark.azure("This test requires Azure") def test_document_processor_web(): document_processor = DocumentProcessor() processors = list(filter(lambda x : x.document_type == 'url', ConfigHelper.get_active_config_or_default().document_processors)) @@ -30,6 +32,7 @@ def test_document_processor_web(): print(keys) assert len(keys) > 0 +@pytest.mark.azure("This test requires Azure") def test_document_processor_docx(): document_processor = DocumentProcessor() processors = list(filter(lambda x : x.document_type == 'docx', ConfigHelper.get_active_config_or_default().document_processors)) diff --git a/code/utilities/tests/test_Orchestrator.py b/tests/test_Orchestrator.py similarity index 79% rename from code/utilities/tests/test_Orchestrator.py rename to tests/test_Orchestrator.py index c9f88f63d..21e208d30 100644 --- a/code/utilities/tests/test_Orchestrator.py +++ b/tests/test_Orchestrator.py @@ -1,6 +1,7 @@ import pytest -from ..helpers.OrchestratorHelper import Orchestrator, OrchestrationSettings +from code.utilities.helpers.OrchestratorHelper import Orchestrator, OrchestrationSettings +@pytest.mark.azure("This test requires Azure Open AI configured") def test_orchestrator_openai_function(): message_orchestrator = Orchestrator() strategy = "openai_function" @@ -8,6 +9,7 @@ def test_orchestrator_openai_function(): assert messages[-1]['role'] == 'assistant' assert messages[-1]['content'] != '' +@pytest.mark.azure("This test requires Azure Open AI configured") def test_orchestrator_langchain(): message_orchestrator = Orchestrator() strategy = "langchain" diff --git a/code/utilities/tests/test_OutputParserTool.py b/tests/test_OutputParserTool.py similarity index 97% rename from code/utilities/tests/test_OutputParserTool.py rename to tests/test_OutputParserTool.py index 064bc8715..03ba08ac5 100644 --- a/code/utilities/tests/test_OutputParserTool.py +++ b/tests/test_OutputParserTool.py @@ -3,8 +3,8 @@ from typing import List -from utilities.parser.OutputParserTool import OutputParserTool -from ..common.SourceDocument import SourceDocument +from code.utilities.parser.OutputParserTool import OutputParserTool +from code.utilities.common.SourceDocument import SourceDocument def test_returns_parsed_messages():