-
Notifications
You must be signed in to change notification settings - Fork 703
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### Motivation and Context <!-- Thank you for your contribution to the copilot-chat repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> This PR adds support for Stepwise Planner to enable MRKL style planning in Chat Copilot. See microsoft/semantic-kernel#1468 for details on how Stepwise Planner works. - Stepwise Planner will only be called if a plugin has been enabled. This follows the same logic as Action/Sequential Planner. - Added `StepwiseStepView` and `StepwiseThoughtProcess` components to render friendly view of Stepwise thought process in prompt dialog. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> If Planner returns with thought process: ![image](https://github.com/microsoft/chat-copilot/assets/125500434/ef8b2dee-4bfb-44f8-a363-b8469196ebce) ![image](https://github.com/microsoft/chat-copilot/assets/125500434/88cdc5a9-ba9f-4341-bd13-80d3f1532951) ![image](https://github.com/microsoft/chat-copilot/assets/125500434/72027814-7085-4346-944d-999284e84a12) If Planner returns with suggested response or information ![image](https://github.com/microsoft/chat-copilot/assets/125500434/31a2b011-7590-4d82-86a3-a1e5799e019b) Specific Changes: - CopilotChatPlanner class: - The planner now includes support for the new Stepwise Planner and StepwiseStep model. - The planner now includes bailout functionality, which allows the planner to request additional user input if needed. - ProposedPlan model: - Updated to include a new PlanType called Stepwise. - PlannerOptions: - Updated to include a new StepwisePlannerConfig property. - ChatMemoryController: - Updated to sanitize log input by removing new line characters. - ExternalInformationSkill class: - Updated to use the Stepwise Planner if the PlannerOptions.Type is set to Stepwise. - appsettings.json file: - Updated to include a new configuration section, StepwisePlannerConfig, which includes settings for the Stepwise Planner feature. - TextUtils file: - Added utility function to format text containing `\n` line breaks into paragraphs. ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [Contribution Guidelines](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md#development-scripts) raises no violations ~~- [ ] All unit tests pass, and I have added new tests where possible~~ - [x] I didn't break anyone 😄
- Loading branch information
1 parent
2913d1d
commit 49b8d3a
Showing
14 changed files
with
286 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
webapp/src/components/chat/prompt-dialog/stepwise-planner/StepwiseStepView.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { | ||
AccordionHeader, | ||
AccordionItem, | ||
AccordionPanel, | ||
Body1, | ||
makeStyles, | ||
shorthands, | ||
tokens, | ||
} from '@fluentui/react-components'; | ||
import { StepwiseStep } from '../../../../libs/models/StepwiseStep'; | ||
import { formatParagraphTextContent } from '../../../utils/TextUtils'; | ||
|
||
const useClasses = makeStyles({ | ||
root: { | ||
display: 'flex', | ||
...shorthands.gap(tokens.spacingHorizontalM), | ||
}, | ||
accordionItem: { | ||
width: '99%', | ||
}, | ||
header: { | ||
width: '100%', | ||
/* Styles for the button within the header */ | ||
'& button': { | ||
alignItems: 'flex-start', | ||
minHeight: '-webkit-fill-available', | ||
paddingLeft: tokens.spacingHorizontalNone, | ||
}, | ||
}, | ||
}); | ||
|
||
interface IStepwiseStepViewProps { | ||
step: StepwiseStep; | ||
index: number; | ||
} | ||
|
||
export const StepwiseStepView: React.FC<IStepwiseStepViewProps> = ({ step, index }) => { | ||
const classes = useClasses(); | ||
|
||
let header = `[OBSERVATION] ${step.observation}`; | ||
let details: string | undefined; | ||
|
||
if (step.thought) { | ||
const thoughtRegEx = /\[(THOUGHT|QUESTION|ACTION)](\s*(.*))*/g; | ||
let thought = step.thought.match(thoughtRegEx)?.[0] ?? `[THOUGHT] ${step.thought}`; | ||
|
||
// Only show the first sentence of the thought in the header. | ||
// Show the rest as details. | ||
const firstSentenceIndex = thought.indexOf('. '); | ||
if (firstSentenceIndex > 0) { | ||
details = thought.substring(firstSentenceIndex + 2); | ||
thought = thought.substring(0, firstSentenceIndex + 1); | ||
} | ||
|
||
header = thought; | ||
} | ||
|
||
if (step.action) { | ||
header = `[ACTION] ${step.action}`; | ||
|
||
// Format the action variables and observation. | ||
const variables = step.action_variables | ||
? 'Action variables: \n' + | ||
Object.entries(step.action_variables) | ||
.map(([key, value]) => `\r${key}: ${value}`) | ||
.join('\n') | ||
: ''; | ||
|
||
// Remove the [ACTION] tag from the thought and remove any code block formatting. | ||
details = step.thought.replace('[ACTION]', '').replaceAll('```', '') + '\n'; | ||
|
||
// Parse any unicode quotation characters in the observation. | ||
const observation = step.observation?.replaceAll(/\\{0,2}u0022/g, '"'); | ||
details = details.concat(variables, `\nObservation: \n\r${observation}`); | ||
} | ||
|
||
return ( | ||
<div className={classes.root}> | ||
<Body1>{index + 1}.</Body1> | ||
<AccordionItem value={index} className={classes.accordionItem}> | ||
{details ? ( | ||
<> | ||
<AccordionHeader expandIconPosition="end" className={classes.header}> | ||
<Body1>{header}</Body1> | ||
</AccordionHeader> | ||
<AccordionPanel>{formatParagraphTextContent(details)}</AccordionPanel> | ||
</> | ||
) : ( | ||
<Body1>{header}</Body1> | ||
)} | ||
</AccordionItem> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.