Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion infra/main_custom.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,10 @@ module keyvault 'br/public:avm/res/key-vault/vault:0.12.1' = {
{name: 'AZURE-OPENAI-PREVIEW-API-VERSION', value: azureOpenaiAPIVersion}
{name: 'AZURE-OPEN-AI-DEPLOYMENT-MODEL', value: gptModelName}
{name: 'TENANT-ID', value: subscription().tenantId}
{
name: 'AZURE-AI-AGENT-ENDPOINT'
value: aiFoundryAiProjectEndpoint
}
]
}
dependsOn:[
Expand Down Expand Up @@ -1160,7 +1164,8 @@ module webSite 'modules/web-sites.bicep' = {
{
name: 'appsettings'
properties: {
SCM_DO_BUILD_DURING_DEPLOYMENT: 'false'
SCM_DO_BUILD_DURING_DEPLOYMENT: 'True'
ENABLE_ORYX_BUILD: 'True'
AUTH_ENABLED: 'false'
AZURE_SEARCH_SERVICE: aiSearch.outputs.name
AZURE_SEARCH_INDEX: azureSearchIndex
Expand Down
2 changes: 1 addition & 1 deletion infra/scripts/index_scripts/02_process_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,6 @@ def prepare_search_doc(content, document_id):
docs = []

if docs != []:
results = search_client.upload_documents(documents=docs)
search_client.upload_documents(documents=docs)

print(f'{str(counter)} files processed.')
15 changes: 12 additions & 3 deletions scripts/data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,13 @@ def extract_caption(self, text):

def mask_urls_and_imgs(self, text) -> Tuple[Dict[str, str], str]:
def find_urls(string):
regex = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^()\s<>]+|\(([^()\s<>]+|(\([^()\s<>]+\)))*\))+(?:\(([^()\s<>]+|(\([^()\s<>]+\)))*\)|[^()\s`!()\[\]{};:'\".,<>?«»“”‘’]))"
regex = (
r"(?i)\b("
r"(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)"
r"(?:[^()\s<>]+|\(([^()\s<>]+|(\([^()\s<>]+\)))*\))+"
r"(?:\(([^()\s<>]+|(\([^()\s<>]+\)))*\)|[^()\s`!()\[\]{};:'\".,<>?«»“”‘’])"
r")"
)
urls = re.findall(regex, string)
return [x[0] for x in urls]

Expand Down Expand Up @@ -693,7 +699,9 @@ def extract_pdf_content(file_path, form_recognizer_client, use_layout=False):
page_map = []
model = "prebuilt-layout" if use_layout else "prebuilt-read"

base64file = base64.b64encode(open(file_path, "rb").read()).decode()
with open(file_path, "rb") as f:
file_bytes = f.read()
base64file = base64.b64encode(file_bytes).decode()
poller = form_recognizer_client.begin_analyze_document(
model, AnalyzeDocumentRequest(bytes_source=base64file)
)
Expand Down Expand Up @@ -1048,7 +1056,8 @@ def image_content_to_tag(image_content: str) -> str:


def get_caption(image_path, captioning_model_endpoint, captioning_model_key):
encoded_image = base64.b64encode(open(image_path, "rb").read()).decode("ascii")
with open(image_path, "rb") as image_file:
encoded_image = base64.b64encode(image_file.read()).decode("ascii")
file_ext = image_path.split(".")[-1]
headers = {
"Content-Type": "application/json",
Expand Down
131 changes: 0 additions & 131 deletions src/.env.sample

This file was deleted.

2 changes: 0 additions & 2 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ async def init_ai_foundry_client():
return ai_foundry_client
except Exception as e:
logging.exception("Exception in AI Foundry initialization", e)
ai_foundry_client = None
raise e


Expand Down Expand Up @@ -197,7 +196,6 @@ def init_cosmosdb_client():
if span is not None:
span.record_exception(e)
span.set_status(Status(StatusCode.ERROR, str(e)))
cosmos_conversation_client = None
raise e
else:
logging.debug("CosmosDB not configured")
Expand Down
2 changes: 1 addition & 1 deletion src/backend/history/cosmosdbservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async def delete_messages(self, conversation_id, user_id):
item=message["id"], partition_key=user_id
)
response_list.append(resp)
return response_list
return response_list

async def get_conversations(self, user_id, limit, sort_order="DESC", offset=0):
parameters = [{"name": "@userId", "value": user_id}]
Expand Down
10 changes: 8 additions & 2 deletions src/backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,9 @@ def split_contexts(
class DatasourcePayloadConstructor(BaseModel, ABC):
_settings: "_AppSettings" = PrivateAttr()

def __init__(self, settings: "_AppSettings", **data):
super().__init__(**data)
def __init__(self, *args, settings: "_AppSettings", **data):
# Call next __init__ in MRO to allow cooperative multiple inheritance
super().__init__(*args, **data)
self._settings = settings

@abstractmethod
Expand Down Expand Up @@ -302,6 +303,10 @@ class _AzureSearchSettings(BaseSettings, DatasourcePayloadConstructor):
fields_mapping: Optional[dict] = None
filter: Optional[str] = Field(default=None, exclude=True)

def __init__(self, settings: "_AppSettings", **data):
# Ensure both BaseSettings and DatasourcePayloadConstructor are initialized
super().__init__(settings=settings, **data)

@field_validator("content_columns", "vector_columns", mode="before")
@classmethod
def split_columns(cls, comma_separated_string: str) -> List[str]:
Expand Down Expand Up @@ -439,6 +444,7 @@ def set_datasource_settings(self) -> Self:
logging.warning(
"No datasource configuration found in the environment -- calls will be made to Azure OpenAI without grounding data."
)
return self


app_settings = _AppSettings()
8 changes: 1 addition & 7 deletions src/frontend/__mocks__/react-markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

import React from 'react';

// Mock implementation of react-markdown
const mockNode = {
children: [{ value: 'console.log("Test Code");' }]
};
const mockProps = { className: 'language-javascript' };

const ReactMarkdown: React.FC<{ children: React.ReactNode , components: any }> = ({ children,components }) => {
return <div data-testid="reactMockDown">
{/* {components && components.code({ node: mockNode, ...mockProps })} */}
{/* {components && components.code({ node: { children: [{ value: 'console.log("Test Code");' }] }, ...mockProps })} */}
{children}</div>; // Simply render the children
};

Expand Down
2 changes: 0 additions & 2 deletions src/frontend/src/api/models.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Plotly from 'react-plotly.js'

export type AskResponse = {
answer: string
citations: Citation[]
Expand Down
25 changes: 4 additions & 21 deletions src/frontend/src/components/Answer/Answer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { renderWithContext, screen, waitFor, fireEvent, act, logRoles } from '../../test/test.utils';
import { renderWithContext, screen, waitFor, fireEvent, act } from '../../test/test.utils';
import { Answer } from './Answer'
import { AppStateContext } from '../../state/AppProvider'
import {AskResponse, Citation, Feedback, historyMessageFeedback } from '../../api';
//import { Feedback, AskResponse, Citation } from '../../api/models'
import { cloneDeep } from 'lodash'
import userEvent from '@testing-library/user-event';
import { CitationPanel } from '../../pages/chat/Components/CitationPanel';

// Mock required modules and functions
jest.mock('../../api/api', () => ({
Expand All @@ -27,9 +25,6 @@ jest.mock('remark-gfm', () => jest.fn());
jest.mock('rehype-raw', () => jest.fn());
jest.mock('remark-supersub', () => jest.fn());

const mockDispatch = jest.fn();
const mockOnCitationClicked = jest.fn();

// Mock context provider values
let mockAppState = {
frontendSettings: { feedback_enabled: true, sanitize_answer: true },
Expand Down Expand Up @@ -360,15 +355,14 @@ describe('Answer Component', () => {
it('should open and submit negative feedback dialog', async () => {
userEvent.setup();
renderComponent();
const handleChange = jest.fn();
const dislikeButton = screen.getByLabelText('Dislike this response');

// Click dislike to open dialog
await fireEvent.click(dislikeButton);
expect(screen.getByText("Why wasn't this response helpful?")).toBeInTheDocument();

// Select feedback and submit
const checkboxEle = await screen.findByLabelText(/Citations are wrong/i)
const checkboxEle = await screen.findByLabelText(/Citations are wrong/i);
//logRoles(checkboxEle)
await waitFor(() => {
userEvent.click(checkboxEle);
Expand All @@ -382,12 +376,8 @@ describe('Answer Component', () => {

it('calls resetFeedbackDialog and setFeedbackState with Feedback.Neutral on dialog dismiss', async () => {

const resetFeedbackDialogMock = jest.fn();
const setFeedbackStateMock = jest.fn();

userEvent.setup();
renderComponent();
const handleChange = jest.fn();
const dislikeButton = screen.getByLabelText('Dislike this response');

// Click dislike to open dialog
Expand All @@ -410,7 +400,6 @@ describe('Answer Component', () => {
it('Dialog Options should be able to select and unSelect', async () => {
userEvent.setup();
renderComponent();
const handleChange = jest.fn();
const dislikeButton = screen.getByLabelText('Dislike this response');

// Click dislike to open dialog
Expand All @@ -419,15 +408,15 @@ describe('Answer Component', () => {
expect(screen.getByText("Why wasn't this response helpful?")).toBeInTheDocument();

// Select feedback and submit
const checkboxEle = await screen.findByLabelText(/Citations are wrong/i)
const checkboxEle = await screen.findByLabelText(/Citations are wrong/i);
expect(checkboxEle).not.toBeChecked();

await userEvent.click(checkboxEle);
await waitFor(() => {
expect(checkboxEle).toBeChecked();
});

const checkboxEle1 = await screen.findByLabelText(/Citations are wrong/i)
const checkboxEle1 = await screen.findByLabelText(/Citations are wrong/i);

await userEvent.click(checkboxEle1);
await waitFor(() => {
Expand All @@ -439,7 +428,6 @@ describe('Answer Component', () => {
it('Should able to show ReportInappropriateFeedbackContent form while click on "InappropriateFeedback" button ', async () => {
userEvent.setup();
renderComponent();
const handleChange = jest.fn();
const dislikeButton = screen.getByLabelText('Dislike this response');

// Click dislike to open dialog
Expand Down Expand Up @@ -514,7 +502,6 @@ describe('Answer Component', () => {
feedbackState: { '123': Feedback.OtherHarmful },
}
renderComponent(answerWithMissingFeedback, extraMockState);
const handleChange = jest.fn();
const dislikeButton = screen.getByLabelText('Dislike this response');

// Click dislike to open dialog
Expand All @@ -529,10 +516,6 @@ describe('Answer Component', () => {

tempMockCitation[0].filepath = '';
tempMockCitation[0].reindex_id = '';
const answerWithMissingFeedback = {
...mockAnswerProps,
CitationPanel: [...tempMockCitation]
}

renderComponent();

Expand Down
Loading