Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Merging psl main to dev #190

Merged
merged 34 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
579c996
fix bug #7834
UtkarshMishra-Microsoft Oct 30, 2024
9b313b1
fixissue7834
UtkarshMishra-Microsoft Oct 30, 2024
0da12b9
Update docker-build-and-push.yml
Pavan-Microsoft Oct 31, 2024
4aa8795
Update deployment.json
Pavan-Microsoft Oct 31, 2024
2055838
Merge pull request #3 from Roopan-Microsoft/PSL-Publishtodevtag
Roopan-Microsoft Oct 31, 2024
c5a0d6c
Merge branch 'microsoft:main' into main
AjitPadhi-Microsoft Nov 4, 2024
8144e24
Fix the bug 9825
Mohan-Microsoft Nov 5, 2024
57dc21e
Merge pull request #7 from Roopan-Microsoft/PSL-DG-BUG-9825
Mohan-Microsoft Nov 5, 2024
92e45e3
Merge pull request #5 from Roopan-Microsoft/bug_fix_psl_7834
UtkarshMishra-Microsoft Nov 6, 2024
b5d89b2
Update README.md
Pavan-Microsoft Nov 6, 2024
1fbb2f6
Updated the system prompt to resolve
Priyanka-Microsoft Nov 7, 2024
cdd149a
Bug10178 fix disable clear all history if there is no chat history
Nov 7, 2024
1a2e752
Merge pull request #11 from Roopan-Microsoft/Bug10178
Himanshi-Mirosoft Nov 7, 2024
2f1e57b
Merge pull request #8 from Roopan-Microsoft/psl-onclick-dev
Roopan-Microsoft Nov 7, 2024
ab935a2
fix: Chat history template name is accepting empty strings as well
Prasanjeet-Microsoft Nov 7, 2024
77eee2b
Merge pull request #12 from Roopan-Microsoft/PSL-BUG-10171
Roopan-Microsoft Nov 7, 2024
b838fa4
slightly refined prompt
Priyanka-Microsoft Nov 7, 2024
14922ff
slightly refined prompt
Priyanka-Microsoft Nov 7, 2024
3db1fc8
Bug10177 fixed Edit and Delete btn disable when message is generating
Nov 8, 2024
860bfca
Bug9825 fix for Mohan's Bug
Nov 8, 2024
d9cc353
Merge pull request #10 from Priyanka-Microsoft/feature/7571-psl-bug-r…
Roopan-Microsoft Nov 8, 2024
b0d46f1
Merge pull request #13 from Roopan-Microsoft/Bug10177
Roopan-Microsoft Nov 8, 2024
992ac8f
fix: A brand new section getting added while removing section one by …
Prasanjeet-Microsoft Nov 15, 2024
63bd46b
Merge branch 'microsoft:main' into main
AjitPadhi-Microsoft Nov 15, 2024
5948cd5
Merge pull request #14 from Roopan-Microsoft/PSL-BUG-10345
Roopan-Microsoft Nov 15, 2024
77c20bd
Added CODEOWNERS file for DocGen
UtkarshMishra-Microsoft Nov 25, 2024
07629d3
Add code quality workflow
UtkarshMishra-Microsoft Dec 5, 2024
0163531
Add code quality workflow push
UtkarshMishra-Microsoft Dec 6, 2024
41be3c4
Merge pull request #19 from Roopan-Microsoft/Pylint-Implementation
UtkarshMishra-Microsoft Dec 9, 2024
ae331d4
Merge pull request #15 from Roopan-Microsoft/add-codeowners
UtkarshMishra-Microsoft Dec 9, 2024
90c2d9a
Merge remote-tracking branch 'upstream/main'
Roopan-Microsoft Jan 2, 2025
34dc709
Reverted the unwanted changes
Roopan-Microsoft Jan 2, 2025
47c5190
updated
Roopan-Microsoft Jan 2, 2025
833a628
Merge branch 'dev' into main
Roopan-Microsoft Jan 2, 2025
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
3 changes: 2 additions & 1 deletion .github/workflows/docker-build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ jobs:
- name: Build and push Docker image
run: |
docker build -t ${{ secrets.ACR_LOGIN_SERVER }}/webapp:latest -f WebApp.Dockerfile .
docker push ${{ secrets.ACR_LOGIN_SERVER }}/webapp:latest
docker push ${{ secrets.ACR_LOGIN_SERVER }}/webapp:latest

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@ You acknowledge that the Software and Microsoft Products and Services (1) are no

You acknowledge the Software is not subject to SOC 1 and SOC 2 compliance audits. No Microsoft technology, nor any of its component technologies, including the Software, is intended or made available as a substitute for the professional advice, opinion, or judgement of a certified financial services professional. Do not use the Software to replace, substitute, or provide professional financial advice or judgment.

BY ACCESSING OR USING THE SOFTWARE, YOU ACKNOWLEDGE THAT THE SOFTWARE IS NOT DESIGNED OR INTENDED TO SUPPORT ANY USE IN WHICH A SERVICE INTERRUPTION, DEFECT, ERROR, OR OTHER FAILURE OF THE SOFTWARE COULD RESULT IN THE DEATH OR SERIOUS BODILY INJURY OF ANY PERSON OR IN PHYSICAL OR ENVIRONMENTAL DAMAGE (COLLECTIVELY, “HIGH-RISK USE”), AND THAT YOU WILL ENSURE THAT, IN THE EVENT OF ANY INTERRUPTION, DEFECT, ERROR, OR OTHER FAILURE OF THE SOFTWARE, THE SAFETY OF PEOPLE, PROPERTY, AND THE ENVIRONMENT ARE NOT REDUCED BELOW A LEVEL THAT IS REASONABLY, APPROPRIATE, AND LEGAL, WHETHER IN GENERAL OR IN A SPECIFIC INDUSTRY. BY ACCESSING THE SOFTWARE, YOU FURTHER ACKNOWLEDGE THAT YOUR HIGH-RISK USE OF THE SOFTWARE IS AT YOUR OWN RISK.
BY ACCESSING OR USING THE SOFTWARE, YOU ACKNOWLEDGE THAT THE SOFTWARE IS NOT DESIGNED OR INTENDED TO SUPPORT ANY USE IN WHICH A SERVICE INTERRUPTION, DEFECT, ERROR, OR OTHER FAILURE OF THE SOFTWARE COULD RESULT IN THE DEATH OR SERIOUS BODILY INJURY OF ANY PERSON OR IN PHYSICAL OR ENVIRONMENTAL DAMAGE (COLLECTIVELY, “HIGH-RISK USE”), AND THAT YOU WILL ENSURE THAT, IN THE EVENT OF ANY INTERRUPTION, DEFECT, ERROR, OR OTHER FAILURE OF THE SOFTWARE, THE SAFETY OF PEOPLE, PROPERTY, AND THE ENVIRONMENT ARE NOT REDUCED BELOW A LEVEL THAT IS REASONABLY, APPROPRIATE, AND LEGAL, WHETHER IN GENERAL OR IN A SPECIFIC INDUSTRY. BY ACCESSING THE SOFTWARE, YOU FURTHER ACKNOWLEDGE THAT YOUR HIGH-RISK USE OF THE SOFTWARE IS AT YOUR OWN RISK.
2 changes: 1 addition & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ async def rename_conversation():

# update the title
title = request_json.get("title", None)
if not title:
if not title or title.strip() == "":
return jsonify({"error": "title is required"}), 400
conversation["title"] = title
updated_conversation = await cosmos_conversation_client.upsert_conversation(
Expand Down
6 changes: 4 additions & 2 deletions backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ class _AzureSearchSettings(BaseSettings, DatasourcePayloadConstructor):
_type: Literal["azure_search"] = PrivateAttr(default="azure_search")
top_k: int = Field(default=5, serialization_alias="top_n_documents")
strictness: int = 3
enable_in_domain: bool = Field(default=True, serialization_alias="in_scope")
enable_in_domain: bool = Field(
default=True, serialization_alias="in_scope")
service: str = Field(exclude=True)
endpoint_suffix: str = Field(default="search.windows.net", exclude=True)
index: str = Field(serialization_alias="index_name")
Expand Down Expand Up @@ -300,7 +301,8 @@ def set_query_type(self) -> Self:
def _set_filter_string(self, request: Request) -> str:
if self.permitted_groups_column:
user_token = request.headers.get("X-MS-TOKEN-AAD-ACCESS-TOKEN", "")
logging.debug(f"USER TOKEN is {'present' if user_token else 'not present'}")
logging.debug(
f"USER TOKEN is {'present' if user_token else 'not present'}")
if not user_token:
raise ValueError(
"Document-level access control is enabled, but user access token could not be fetched."
Expand Down
9 changes: 6 additions & 3 deletions backend/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ async def format_as_ndjson(r):
async for event in r:
yield json.dumps(event, cls=JSONEncoder) + "\n"
except Exception as error:
logging.exception("Exception while generating response stream: %s", error)
logging.exception(
"Exception while generating response stream: %s", error)
yield json.dumps({"error": str(error)})


Expand All @@ -55,7 +56,8 @@ def fetchUserGroups(userToken, nextLink=None):
try:
r = requests.get(endpoint, headers=headers)
if r.status_code != 200:
logging.error(f"Error fetching user groups: {r.status_code} {r.text}")
logging.error(
f"Error fetching user groups: {r.status_code} {r.text}")
return []

r = r.json()
Expand Down Expand Up @@ -128,7 +130,8 @@ def format_stream_response(chatCompletionChunk, history_metadata, apim_request_i
delta = chatCompletionChunk.choices[0].delta
if delta:
if hasattr(delta, "context"):
messageObj = {"role": "tool", "content": json.dumps(delta.context)}
messageObj = {"role": "tool",
"content": json.dumps(delta.context)}
response_obj["choices"][0]["messages"].append(messageObj)
return response_obj
if delta.role == "assistant" and hasattr(delta, "context"):
Expand Down
23 changes: 22 additions & 1 deletion frontend/src/components/ChatHistory/ChatHistoryListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { AppStateContext } from '../../state/AppProvider'
import { GroupedChatHistory } from './ChatHistoryList'

import styles from './ChatHistoryPanel.module.css'
import _ from 'lodash'

interface ChatHistoryListItemCellProps {
item?: Conversation
Expand Down Expand Up @@ -59,7 +60,8 @@ export const ChatHistoryListItemCell: React.FC<ChatHistoryListItemCellProps> = (
const [errorRename, setErrorRename] = useState<string | undefined>(undefined)
const [textFieldFocused, setTextFieldFocused] = useState(false)
const textFieldRef = useRef<ITextField | null>(null)

const [isButtonDisabled, setIsButtonDisabled] = useState<boolean>(false);

const appStateContext = React.useContext(AppStateContext)
const isSelected = item?.id === appStateContext?.state.currentChat?.id
const dialogContentProps = {
Expand Down Expand Up @@ -94,6 +96,12 @@ export const ChatHistoryListItemCell: React.FC<ChatHistoryListItemCellProps> = (
}
}, [appStateContext?.state.currentChat?.id, item?.id])

useEffect(()=>{
let v = appStateContext?.state.isRequestInitiated;
if(v!=undefined)
setIsButtonDisabled(v && isSelected)
},[appStateContext?.state.isRequestInitiated])

const onDelete = async () => {
const response = await historyDelete(item.id)
if (!response.ok) {
Expand Down Expand Up @@ -125,6 +133,17 @@ export const ChatHistoryListItemCell: React.FC<ChatHistoryListItemCellProps> = (
if (errorRename || renameLoading) {
return
}
if (_.trim(editTitle) === "") {
setErrorRename('Error: Title is required.')
setTimeout(() => {
setErrorRename(undefined)
setTextFieldFocused(true)
if (textFieldRef.current) {
textFieldRef.current.focus()
}
}, 5000)
return
}
if (editTitle == item.title) {
setErrorRename('Error: Enter a new title to proceed.')
setTimeout(() => {
Expand Down Expand Up @@ -255,13 +274,15 @@ export const ChatHistoryListItemCell: React.FC<ChatHistoryListItemCellProps> = (
iconProps={{ iconName: 'Delete' }}
title="Delete"
onClick={toggleDeleteDialog}
disabled={isButtonDisabled}
onKeyDown={e => (e.key === ' ' ? toggleDeleteDialog() : null)}
/>
<IconButton
className={styles.itemButton}
iconProps={{ iconName: 'Edit' }}
title="Edit"
onClick={onEdit}
disabled={isButtonDisabled}
onKeyDown={e => (e.key === ' ' ? onEdit() : null)}
/>
</Stack>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ChatHistory/ChatHistoryPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function ChatHistoryPanel(_props: ChatHistoryPanelProps) {
const [hideClearAllDialog, { toggle: toggleClearAllDialog }] = useBoolean(true)
const [clearing, setClearing] = React.useState(false)
const [clearingError, setClearingError] = React.useState(false)

const hasChatHistory = appStateContext?.state.chatHistory && appStateContext.state.chatHistory.length > 0;
const clearAllDialogContentProps = {
type: DialogType.close,
title: !clearingError ? 'Are you sure you want to clear all chat history?' : 'Error deleting all of chat history',
Expand All @@ -67,7 +67,7 @@ export function ChatHistoryPanel(_props: ChatHistoryPanelProps) {
}

const menuItems: IContextualMenuItem[] = [
{ key: 'clearAll', text: 'Clear all chat history', iconProps: { iconName: 'Delete' } }
{ key: 'clearAll', text: 'Clear all chat history',disabled: !hasChatHistory, iconProps: { iconName: 'Delete' }}
]

const handleHistoryClick = () => {
Expand Down
137 changes: 107 additions & 30 deletions frontend/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import React, { useEffect, useState, useContext } from 'react'
import { Stack, Text } from '@fluentui/react'
import { Book28Regular, Book32Regular, BookRegular, News28Regular, NewsRegular, Notepad28Regular, Notepad32Regular } from '@fluentui/react-icons'
import {
Book28Regular,
Book32Regular,
BookRegular,
News28Regular,
NewsRegular,
Notepad28Regular,
Notepad32Regular
} from '@fluentui/react-icons'
import { Button, Avatar } from '@fluentui/react-components'
import styles from './Sidebar.module.css'
import { AppStateContext } from '../../state/AppProvider'
import { getUserInfo } from '../../api'
import { useNavigate, useLocation } from 'react-router-dom'


enum NavigationButtonStates {
Active = 'active',
Inactive = 'inactive',
Expand All @@ -28,9 +35,24 @@ const NavigationButton = ({ text, buttonState, onClick }: NavigationButtonProps)
}[buttonState]

const iconElements: { [key: string]: JSX.Element } = {
'Browse': <News28Regular color={fontColor}/>,
'Generate': <Book28Regular color={fontColor}/>,
'Draft': <Notepad28Regular color={fontColor}/>
Browse: (
<News28Regular
color={fontColor}
cursor={buttonState === NavigationButtonStates.Disabled ? 'not-allowed' : 'pointer'}
/>
),
Generate: (
<Book28Regular
color={fontColor}
cursor={buttonState === NavigationButtonStates.Disabled ? 'not-allowed' : 'pointer'}
/>
),
Draft: (
<Notepad28Regular
color={fontColor}
cursor={buttonState === NavigationButtonStates.Disabled ? 'not-allowed' : 'pointer'}
/>
)
}

const buttonStyle = {
Expand All @@ -42,37 +64,54 @@ const NavigationButton = ({ text, buttonState, onClick }: NavigationButtonProps)
const icon = iconElements[text]

return (
<Stack onClick={buttonState === NavigationButtonStates.Inactive ? onClick : () => {}} className={buttonStyle}>
<Button appearance="transparent"
size="large"
icon={icon}
style={{ padding: '0' }}
/>
<Text style={{ color: fontColor }}>{text}</Text>
<Stack
onClick={buttonState === NavigationButtonStates.Inactive ? onClick : () => {}}
className={buttonStyle}
style={{ cursor: buttonState === NavigationButtonStates.Disabled ? 'not-allowed' : 'pointer' }}>
<Button appearance="transparent" size="large" icon={icon} style={{ padding: '0' }} />
<Text
style={{
color: fontColor,
cursor: buttonState === NavigationButtonStates.Disabled ? 'not-allowed' : 'pointer'
}}>
{text}
</Text>
</Stack>
)
}

const Sidebar = (): JSX.Element => {
const appStateContext = useContext(AppStateContext)
const navigate = useNavigate()
const location = useLocation();
const [name, setName] = useState<string>("")
const location = useLocation()
const [name, setName] = useState<string>('')
useEffect(() => {
if(appStateContext?.state.isRequestInitiated == true){
NavigationButtonStates.Disabled
}
else{
NavigationButtonStates.Active
}
})

useEffect(() => {
if (!appStateContext) { throw new Error('useAppState must be used within a AppStateProvider') }
if (!appStateContext) {
throw new Error('useAppState must be used within a AppStateProvider')
}

if (appStateContext.state.frontendSettings?.auth_enabled) {
getUserInfo().then((res) => {
const name: string = res[0].user_claims.find((claim: any) => claim.typ === 'name')?.val ?? ''
setName(name)
}).catch((err) => {
console.error('Error fetching user info: ', err)
})
getUserInfo()
.then(res => {
const name: string = res[0].user_claims.find((claim: any) => claim.typ === 'name')?.val ?? ''
setName(name)
})
.catch(err => {
console.error('Error fetching user info: ', err)
})
}
}, [])
}, [appStateContext])

// determine url from react-router-dom
// determine url from react-router-dom
const determineView = () => {
const url = location.pathname

Expand All @@ -82,20 +121,58 @@ const Sidebar = (): JSX.Element => {
}

const currentView = determineView()

// inactive, disabled, active
var draftButtonState = NavigationButtonStates.Disabled
if (appStateContext?.state.draftedDocument) { draftButtonState = currentView === 'draft' ? NavigationButtonStates.Active : NavigationButtonStates.Inactive }
// inactive, disabled, active
var draftButtonState = NavigationButtonStates.Disabled
if (appStateContext?.state.draftedDocument) {
draftButtonState = currentView === 'draft' ? NavigationButtonStates.Active : NavigationButtonStates.Inactive
}
const isGenerating = appStateContext?.state.isRequestInitiated

return (
<Stack className={styles.sidebarContainer}>
<Stack horizontal className={styles.avatarContainer}>
<Avatar color="colorful" name={name} />
</Stack>
<Stack className={styles.sidebarNavigationContainer}>
<NavigationButton text={"Browse"} buttonState={currentView === 'chat' ? NavigationButtonStates.Active : NavigationButtonStates.Inactive} onClick={() => { navigate("/chat") }} />
<NavigationButton text={"Generate"} buttonState={currentView === 'generate' ? NavigationButtonStates.Active : NavigationButtonStates.Inactive} onClick={() => { navigate("/generate") }} />
<NavigationButton text={"Draft"} buttonState={draftButtonState} onClick={() => { navigate("/draft") }} />
<NavigationButton
text={'Browse'}
buttonState={
currentView === 'chat'
? NavigationButtonStates.Active
: appStateContext?.state.isRequestInitiated
? NavigationButtonStates.Disabled
: NavigationButtonStates.Inactive
}
onClick={() => {
if (!isGenerating) {
navigate('/chat')
}
}}
/>
<NavigationButton
text={'Generate'}
buttonState={
currentView === 'generate'
? NavigationButtonStates.Active
: appStateContext?.state.isRequestInitiated
? NavigationButtonStates.Disabled
: NavigationButtonStates.Inactive

}
onClick={() => {
if (!isGenerating) {
navigate('/generate')
}
}}
/>
<NavigationButton
text={'Draft'}
buttonState={draftButtonState}

onClick={() => {
navigate('/draft')
}}
/>
</Stack>
</Stack>
)
Expand Down
Loading
Loading