Skip to content
Closed
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
36 changes: 0 additions & 36 deletions .github/chatmodes/debug.chatmode.md

This file was deleted.

27 changes: 27 additions & 0 deletions .github/chatmodes/fixer.chatmode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
description: 'Fix and verify issues in app'
model: GPT-5 (Preview)
tools: ['extensions', 'codebase', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'fetch', 'findTestFiles', 'searchResults', 'githubRepo', 'runTests', 'runCommands', 'runTasks', 'editFiles', 'runNotebooks', 'search', 'new', 'get_issue', 'get_issue_comments', 'get-library-docs', 'playwright', 'pylance mcp server']
---

# Fixer Mode Instructions

You are in fixer mode. When given an issue to fix, follow these steps:

• **Gather context**: Read error messages/stack traces/related code. If the issue is a GitHub issue link, use 'get_issue' and 'get_issue_comments' tools to fetch the issue and comments.
• **Make targeted fix**: Make minimal changes to fix the issue. Do not fix any issues that weren't identified. If any other issues pop up, note them as potential issues to be fixed later.
• **Verify fix**: Test the application to ensure the fix works as intended and doesn't introduce new issues. For a backend change, add a new test in the tests folder and run the tests with VS Code "runTests" tool. RUN all the tests using that tool, not just the tests you added. Try to add tests to existing test files when possible, like test_app.py. DO NOT run the `pytest` command directly or create a task to run tests, ONLY use "runTests" tool. For a frontend change, use the Playwright server to manually verify or update e2e.py tests.

## Local server setup

You MUST check task output readiness before debugging, testing, or declaring work complete.

- Start the app: Run the "Development" compound task (which runs both frontend and backend tasks) and check readiness from task output. Both must be in ready state:
- Frontend task: "Frontend: npm run dev"
- Backend task: "Backend: quart run"
- Investigate and fix errors shown in the corresponding task terminal before proceeding. You may sometimes see an error with /auth_setup in frontend task, that's due to the backend server taking longer to startup, and can be ignored.
- Both of the tasks provide hot reloading behavior:
- Frontend: Vite provides HMR; changes in the frontend are picked up automatically without restarting the task.
- Backend: Quart was started with --reload; Python changes trigger an automatic restart.
- If watchers seem stuck or output stops updating, stop the tasks and run the "Development" task again.
- To interact with a running application, use the Playwright MCP server
51 changes: 51 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Adding new data

New files should be added to the `data` folder, and then either run scripts/prepdocs.sh or script/prepdocs.ps1 to ingest the data.

# Adding a new azd environment variable

An azd environment variable is stored by the azd CLI for each environment. It is passed to the "azd up" command and can configure both provisioning options and application settings.
When adding new azd environment variables, update:

1. infra/main.parameters.json : Add the new parameter with a Bicep-friendly variable name and map to the new environment variable
1. infra/main.bicep: Add the new Bicep parameter at the top, and add it to the `appEnvVariables` object
1. azure.yaml: Add the new environment variable under pipeline config section
1. .azdo/pipelines/azure-dev.yml: Add the new environment variable under `env` section
1. .github/workflows/azure-dev.yml: Add the new environment variable under `env` section

# Adding a new setting to "Developer Settings" in RAG app

When adding a new developer setting, update:

* frontend:
* app/frontend/src/api/models.ts : Add to ChatAppRequestOverrides
* app/frontend/src/components/Settings.tsx : Add a UI element for the setting
* app/frontend/src/locales/*/translations.json: Add a translation for the setting label/tooltip for all languages
* app/frontend/src/pages/chat/Chat.tsx: Add the setting to the component, pass it to Settings
* app/frontend/src/pages/ask/Ask.tsx: Add the setting to the component, pass it to Settings

* backend:
* app/backend/approaches/chatreadretrieveread.py : Retrieve from overrides parameter
* app/backend/approaches/retrievethenread.py : Retrieve from overrides parameter
* app/backend/app.py: Some settings may need to sent down in the /config route.

# When adding tests for a new feature:

All tests are in the `tests` folder and use the pytest framework.
There are three styles of tests:

* e2e tests: These use playwright to run the app in a browser and test the UI end-to-end. They are in e2e.py and they mock the backend using the snapshots from the app tests.
* app integration tests: Mostly in test_app.py, these test the app's API endpoints and use mocks for services like Azure OpenAI and Azure Search.
* unit tests: The rest of the tests are unit tests that test individual functions and methods. They are in test_*.py files.

When adding a new feature, add tests for it in the appropriate file.
If the feature is a UI element, add an e2e test for it.
If it is an API endpoint, add an app integration test for it.
If it is a function or method, add a unit test for it.
Use mocks from conftest.py to mock external services.

When you're running tests, make sure you activate the .venv virtual environment first:

```bash
source .venv/bin/activate
```
192 changes: 106 additions & 86 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,88 +1,108 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Start App",
"type": "shell",
"command": "${workspaceFolder}/app/start.sh",
"windows": {
"command": "pwsh ${workspaceFolder}/app/start.ps1"
},
"presentation": {
"reveal": "silent"
},
"options": {
"cwd": "${workspaceFolder}/app"
},
"problemMatcher": []
},
{
"label": "Development",
"dependsOn": [
"Frontend: npm run dev",
"Backend: quart run"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Frontend: npm run dev",
"type": "npm",
"script": "dev",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}/app/frontend"
},
"presentation": {
"reveal": "always",
"group": "buildWatchers",
"panel": "dedicated",
"clear": false
},
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"activeOnStart": true,
"beginsPattern": ".*VITE v.*",
"endsPattern": ".*(?:➜\\s*)?Local:\\s+https?://.*"
}
}
},
{
"label": "Backend: quart run",
"type": "shell",
"command": "${workspaceFolder}/.venv/bin/python",
"windows": {
"command": "${workspaceFolder}\\.venv\\Scripts\\python.exe"
},
"args": ["-m", "quart", "run", "--reload", "-p", "50505"],
"options": {
"cwd": "${workspaceFolder}/app/backend",
"env": {
"QUART_APP": "main:app",
"QUART_ENV": "development",
"QUART_DEBUG": "0",
"LOADING_MODE_FOR_AZD_ENV_VARS": "override"
}
},
"isBackground": true,
"presentation": {
"reveal": "always",
"group": "buildWatchers",
"panel": "dedicated"
},
"problemMatcher": {
"pattern": { "regexp": "" },
"background": {
"activeOnStart": true,
"beginsPattern": ".*Serving Quart app.*",
"endsPattern": ".*hypercorn.*Running on http://.*"
}
}
}
]
"version": "2.0.0",
"tasks": [
{
"label": "Start App",
"type": "shell",
"command": "${workspaceFolder}/app/start.sh",
"windows": {
"command": "pwsh ${workspaceFolder}/app/start.ps1"
},
"presentation": {
"reveal": "silent"
},
"options": {
"cwd": "${workspaceFolder}/app"
},
"problemMatcher": []
},
{
"label": "Development",
"dependsOn": [
"Frontend: npm run dev",
"Backend: quart run"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Frontend: npm run dev",
"type": "npm",
"script": "dev",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}/app/frontend"
},
"presentation": {
"reveal": "always",
"group": "buildWatchers",
"panel": "dedicated",
"clear": false
},
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"activeOnStart": true,
"beginsPattern": ".*VITE v.*",
"endsPattern": ".*(?:➜\\s*)?Local:\\s+https?://.*"
}
}
},
{
"label": "Backend: quart run",
"type": "shell",
"command": "${workspaceFolder}/.venv/bin/python",
"windows": {
"command": "${workspaceFolder}\\.venv\\Scripts\\python.exe"
},
"args": [
"-m",
"quart",
"run",
"--reload",
"-p",
"50505"
],
"options": {
"cwd": "${workspaceFolder}/app/backend",
"env": {
"QUART_APP": "main:app",
"QUART_ENV": "development",
"QUART_DEBUG": "0",
"LOADING_MODE_FOR_AZD_ENV_VARS": "override"
}
},
"isBackground": true,
"presentation": {
"reveal": "always",
"group": "buildWatchers",
"panel": "dedicated"
},
"problemMatcher": {
"pattern": {
"regexp": ""
},
"background": {
"activeOnStart": true,
"beginsPattern": ".*Serving Quart app.*",
"endsPattern": ".*hypercorn.*Running on http://.*"
}
}
},
{
"label": "Typecheck Frontend",
"type": "shell",
"command": "npm run -s build",
"args": [],
"isBackground": false,
"problemMatcher": [
"$eslint-stylish"
],
"group": "build"
}
]
}
6 changes: 6 additions & 0 deletions app/backend/approaches/approach.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ def create_chat_completion(
temperature: Optional[float] = None,
n: Optional[int] = None,
reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
verbosity: Optional[str] = None,
) -> Union[Awaitable[ChatCompletion], Awaitable[AsyncStream[ChatCompletionChunk]]]:
if chatgpt_model in self.GPT_REASONING_MODELS:
params: dict[str, Any] = {
Expand All @@ -449,6 +450,11 @@ def create_chat_completion(
params["stream_options"] = {"include_usage": True}
params["reasoning_effort"] = reasoning_effort or overrides.get("reasoning_effort") or self.reasoning_effort

# Pass verbosity for reasoning models (default to "medium" if not provided)
# Only include the parameter for models that support reasoning features.
verbosity_value = verbosity or overrides.get("verbosity") or getattr(self, "verbosity", None) or "medium"
params["verbosity"] = verbosity_value

else:
# Include parameters that may not be supported for reasoning models
params = {
Expand Down
2 changes: 1 addition & 1 deletion app/backend/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from quart import jsonify

ERROR_MESSAGE = """The app encountered an error processing your request.
If you are an administrator of the app, view the full error in the logs. See aka.ms/appservice-logs for more information.
If you are an administrator of the app, check the application logs for a full traceback.
Error type: {error_type}
"""
ERROR_MESSAGE_FILTER = """Your message contains content that was flagged by the OpenAI content filter."""
Expand Down
1 change: 1 addition & 0 deletions app/frontend/src/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type ChatAppRequestOverrides = {
semantic_captions?: boolean;
query_rewriting?: boolean;
reasoning_effort?: string;
verbosity?: string;
include_category?: string;
exclude_category?: string;
seed?: number;
Expand Down
19 changes: 19 additions & 0 deletions app/frontend/src/components/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface SettingsProps {
useSemanticCaptions: boolean;
useQueryRewriting: boolean;
reasoningEffort: string;
verbosity?: string;
excludeCategory: string;
includeCategory: string;
retrievalMode: RetrievalMode;
Expand Down Expand Up @@ -64,6 +65,7 @@ export const Settings = ({
useSemanticCaptions,
useQueryRewriting,
reasoningEffort,
verbosity,
excludeCategory,
includeCategory,
retrievalMode,
Expand Down Expand Up @@ -119,6 +121,7 @@ export const Settings = ({
const semanticRankerFieldId = useId("semanticRankerField");
const queryRewritingFieldId = useId("queryRewritingField");
const reasoningEffortFieldId = useId("reasoningEffortField");
const verbosityFieldId = useId("verbosityField");
const semanticCaptionsId = useId("semanticCaptions");
const semanticCaptionsFieldId = useId("semanticCaptionsField");
const useOidSecurityFilterId = useId("useOidSecurityFilter");
Expand Down Expand Up @@ -344,6 +347,22 @@ export const Settings = ({
/>
)}

{showReasoningEffortOption && (
<Dropdown
id={verbosityFieldId}
selectedKey={verbosity || ""}
label={t("labels.verbosity")}
onChange={(_ev?: React.FormEvent<HTMLElement | HTMLInputElement>, option?: IDropdownOption) => onChange("verbosity", option?.key || "")}
aria-labelledby={verbosityFieldId}
options={[
{ key: "low", text: t("labels.verbosityOptions.low") },
{ key: "medium", text: t("labels.verbosityOptions.medium") },
{ key: "high", text: t("labels.verbosityOptions.high") }
]}
onRenderLabel={props => renderLabel(props, verbosityFieldId, verbosityFieldId, t("helpTexts.verbosity"))}
/>
)}

{useLogin && (
<>
<Checkbox
Expand Down
Loading
Loading