Skip to content

Commit cc8da0b

Browse files
authored
Chat demo (#848)
* Adding chat demo Fixing AI generated logic Lots of bugs... Clean not used files Fix server, adding logger Kind of working, remaining work: logger, cacellation, user/conn Add connect hook, user logic User to be set through url too, and simply client logic Fix issue that user should receive the message sent to themselves simply client, a dd a message reducer update wording add rooms sidebar Async handler UPdate readme and remove user related logic Update readme and script temp temp2 Fix the client bug Minor updates Update to include history when sending to ai, and add azure related skeleton WebPubSub works when running locally with tunnel tool Naming refactor Simplify the client side code Cleanup server a bit and it is working Move files Refactor temp Webpage works but negotiate 500 Now works, one last thing is the blob -> table Changing to azure table works Fix some bugs and add ut Fix webpubsub bug when send to group, not need to stringify A clean room management approach using rest api Add more tests Fix package failure and add more tests * Improve UI azd and local run works * little refactors done by codex refactor room store, transport, and rest api Improve code and test * document update
1 parent 7f5b61b commit cc8da0b

File tree

112 files changed

+7583
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+7583
-0
lines changed

samples/ai/chat-demo.zip

110 KB
Binary file not shown.

samples/ai/chat-demo/.azureignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Exclusions for azd source upload (App Service code deploy)
2+
client/node_modules
3+
node_modules
4+
**/.git
5+
**/.venv
6+
**/__pycache__
7+
*.log
8+
client/.vite
9+
client/dist
10+
# We re-copy fresh dist into python_server/static during hook
11+
python_server/static

samples/ai/chat-demo/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.env
2+
__pycache__/
3+
.vscode/
4+
python_server/static/
5+
.azure/

samples/ai/chat-demo/README.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# AI Chat Demo
2+
3+
Multi‑room real‑time chat with optional AI answers. Start locally in a minute. Move to Azure when you're ready—no code changes.
4+
5+
> Want architecture diagrams, CloudEvents/tunnel details, RBAC & env matrix? See **[docs/ADVANCED.md](./docs/ADVANCED.md)**.
6+
> Release history: **[RELEASE_NOTES.md](./RELEASE_NOTES.md)**
7+
8+
## What You Get
9+
- Real‑time rooms (create / join instantly)
10+
- AI bot responses (GitHub Models via your PAT)
11+
- Persistence + scale when on Azure Web PubSub
12+
- Same React UI + Python backend in all modes
13+
14+
## Quick Start
15+
16+
Prereqs:
17+
* Python 3.12+
18+
* Node 18+
19+
20+
1. Create a PAT with **Models – Read**: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
21+
2. Install backend + frontend deps:
22+
```bash
23+
pip install -r requirements.txt
24+
# optional (tests, typing): pip install -r requirements-dev.txt
25+
```
26+
3. (Set token if you want AI answers)
27+
```bash
28+
export GITHUB_TOKEN=<your_pat> # bash/zsh
29+
# PowerShell
30+
$env:GITHUB_TOKEN="<your_pat>"
31+
```
32+
4. Start everything (serves React build automatically):
33+
```bash
34+
python start_dev.py
35+
```
36+
5. Open http://localhost:5173
37+
38+
Running services:
39+
* HTTP API :5000
40+
* Local WebSocket :5001 (self transport)
41+
42+
## Using the App
43+
1. Browse to http://localhost:5173
44+
2. You're placed in room `public`
45+
3. Create / join a room: type a name → Enter
46+
4. Ask something; the AI bot replies (uses your GitHub token)
47+
5. Open a second window to watch live streaming & room isolation
48+
49+
### Tests
50+
51+
Install dev extras first:
52+
```bash
53+
pip install -r requirements-dev.txt
54+
```
55+
56+
Backend (pytest):
57+
```bash
58+
python -m pytest python_server/tests -q
59+
```
60+
Single file:
61+
```bash
62+
python -m pytest python_server/tests/test_runtime_config.py -q
63+
```
64+
Verbose / timing:
65+
```bash
66+
python -m pytest -vv
67+
```
68+
69+
Frontend (Vitest + RTL):
70+
```bash
71+
npm --prefix client test
72+
```
73+
Selected coverage areas (backend): config merge, room store limits, transport factory, room lifecycle, streaming send path.
74+
Coverage snapshot:
75+
* Runtime config validation & merging
76+
* In‑memory room store behavior / limits
77+
* Chat service builder (self vs webpubsub path & credential preconditions)
78+
* Room lifecycle (add/remove)
79+
* Streaming send path basic invariants
80+
81+
#### Frontend (Vitest + RTL)
82+
Location: `client/src/__tests__`
83+
84+
Run:
85+
```
86+
npm --prefix client test
87+
```
88+
Included tests:
89+
* Room switching: cached messages isolated & textarea present after switch
90+
* Sender fallback: history messages without `from` show `AI Assistant`
91+
92+
Add more ideas:
93+
* Mid‑stream room switch preserves previous room’s partial content when returning
94+
* Simulated error banner rendering
95+
* Theme / avatar contexts snapshot
96+
97+
98+
## Core Environment Variables
99+
| Variable | Purpose |
100+
|----------|---------|
101+
| `GITHUB_TOKEN` | Enables AI responses (GitHub Models) |
102+
| `TRANSPORT_MODE` | `self` (default) or `webpubsub` to use Azure Web PubSub service |
103+
| `STORAGE_MODE` | `memory` (default) or `table` for Azure Table / Azurite persistence |
104+
| `WEBPUBSUB_ENDPOINT` or `WEBPUBSUB_CONNECTION_STRING` | The Azure Web PubSub endpoint when transport_mode is `webpubsub` |
105+
| `AZURE_STORAGE_ACCOUNT` or `AZURE_STORAGE_CONNECTION_STRING`| The Azure Storage endpoint when storage_mode is `table` |
106+
| `WEBPUBSUB_HUB` | (Optional) Override the hub name used for the chat app when using Web PubSub (default: demo_ai_chat) |
107+
| `CHAT_TABLE_NAME` | (Optional) Override Azure Table name (default: chatmessages) |
108+
109+
Notes:
110+
- In Azure deployment the Bicep sets `TRANSPORT_MODE=webpubsub` and `STORAGE_MODE=table`.
111+
- Locally you can mix and match (e.g. `self+table` with Azurite or `webpubsub+memory`).
112+
113+
## Custom Resource Names (Optional)
114+
Want predictable names? Provide overrides (must be globally unique where required):
115+
```bash
116+
azd provision --set webPubSubNameOverride=mywps1234 --set webAppNameOverride=mychatweb1234
117+
```
118+
119+
## Iteration Cheatsheet
120+
| Change | Command |
121+
|--------|---------|
122+
| Backend / frontend code | `azd deploy` |
123+
| Infra (Bicep) changes | `azd provision && azd deploy` |
124+
| New environment | `azd env new <name> --location <region>` then `azd up` |
125+
126+
## Hybrid Local + Azure (Short Version)
127+
Run the backend locally while using a real Web PubSub instance (and optionally Table storage) in Azure:
128+
1. `azd up` (once) provisions resources.
129+
2. Create a local `.env` with:
130+
```
131+
TRANSPORT_MODE=webpubsub
132+
WEBPUBSUB_ENDPOINT=https://<name>.webpubsub.azure.com
133+
# optional persistence
134+
STORAGE_MODE=table
135+
```
136+
3. `python start_dev.py`
137+
4. (Optional) Tunnel for CloudEvents (see ADVANCED.md §2.3)
138+
139+
More: **[ADVANCED.md](./docs/ADVANCED.md#2-local-development-paths)**
140+
141+
## FAQ (Quick)
142+
**Do I need Azure to try it?** No—local mode works offline.
143+
144+
**Why Web PubSub?** Managed scale, groups, CloudEvents, secure client negotiation.
145+
146+
**Where are advanced knobs?** All in `docs/ADVANCED.md` (RBAC, credential chain, persistence, CloudEvents, tunnels).
147+
148+
## Next Steps
149+
- Explore advanced capabilities: [docs/ADVANCED.md](./docs/ADVANCED.md)
150+
- Try hybrid tunnel mode for full lifecycle locally
151+
- Customize AI logic in `python_server/chat_model_client.py`
152+
- Review how scalable history works now (Table storage) in the persistence section of the advanced doc.
153+
154+
---
155+
Happy hacking! Open an issue or PR in [our GitHub repo](https://github.com/Azure/azure-webpubsub) with feedback.
156+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# AI Chat Demo – Release Notes
2+
3+
Plain-language updates focused on what demo users can try. Non-customer internal details intentionally omitted.
4+
5+
## [Unreleased]
6+
Nothing user-facing has changed yet.
7+
8+
## [0.1.0] - 2025-10-11 (Preview)
9+
Initial preview release.
10+
11+
### Snapshot
12+
| Area | What you get |
13+
|------|--------------|
14+
| Chat Core | Create / switch rooms instantly (default `public`), per-room cached history |
15+
| AI | Optional GitHub Models answers; app still works without a token |
16+
| Runtime Modes | `self` (local WebSocket) or `webpubsub` (managed service) – toggle with env var |
17+
| Storage Modes | `memory` (ephemeral) or `table` (Azure Table / Azurite) |
18+
| Streaming UX | Token-by-token AI output + typing indicator |
19+
| Messaging UX | Markdown (sanitized), simple formatting, removable non-default rooms |
20+
| Diagnostics | Connection / error banner |
21+
| One-Command Start | Local: `python start_dev.py`; Azure: `azd up` |
22+
23+
### Limitations
24+
| Limitation | Impact |
25+
|------------|--------|
26+
| No history pagination | Very long rooms may load slower over time |
27+
| No auth / identity | All users are anonymous sessions |
28+
| Single AI strategy | Must edit `chat_model_client.py` to change model logic |
29+
| Basic accessibility & theming | Visual polish / a11y incomplete |
30+
31+
### Explore More (Optional)
32+
| If you want to… | Do this |
33+
|------------------|---------|
34+
| Use managed service | Set `TRANSPORT_MODE=webpubsub` and deploy with `azd up` |
35+
| Keep history between runs | Set `STORAGE_MODE=table` (Azure or Azurite) |
36+
| Adjust AI tone | Edit prompt/model in `python_server/chat_model_client.py` |
37+
| Build a minimal custom feature | Fork and add a new room action or message type |
38+
39+
---

samples/ai/chat-demo/azure.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: chat-demo
2+
metadata:
3+
template: chat-demo
4+
infra:
5+
provider: bicep
6+
path: infra
7+
# To override the default web app name (<baseName>-web), set parameter:
8+
# parameters:
9+
# webAppNameOverride: your-custom-name
10+
# To override (or guarantee uniqueness for) the Web PubSub service name:
11+
# azd provision --set webPubSubNameOverride=myuniquewpsname123
12+
services:
13+
chatserver:
14+
# Use repo root as the project so `python_server` remains a package
15+
# and Oryx can load `wsgi:app` from the root wsgi.py
16+
project: .
17+
language: python
18+
host: appservice
19+
# Frontend build hook (build React and copy static files) - ensure this exists in project root or scripts
20+
hooks:
21+
prepackage:
22+
windows:
23+
shell: pwsh
24+
run: |
25+
Push-Location .\client
26+
if (Test-Path node_modules) {
27+
Write-Host "Reusing existing node_modules"
28+
} else {
29+
Write-Host "Installing dependencies in client/"
30+
npm install
31+
}
32+
npm run build
33+
Pop-Location
34+
if (Test-Path .\python_server\static) { Remove-Item -Recurse -Force .\python_server\static }
35+
Copy-Item -Recurse .\client\dist .\python_server\static
36+
posix:
37+
shell: sh
38+
run: |
39+
(cd ./client && ([ -d node_modules ] || npm install) && npm run build)
40+
rm -rf ./python_server/static
41+
mkdir -p ./python_server
42+
cp -R ./client/dist ./python_server/static
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

0 commit comments

Comments
 (0)