尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Explained match intelligence from synthetic football events, for the Microsoft Premier League Hackathon: on-screen graphics that explain each moment in a headline and a few lines of text. Agent Framework agents on Microsoft Foundry redraft some of them, code checks every figure, and a producer can approve, edit or kill each one.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Explained match intelligence from synthetic football events: on-screen graphics that explain each moment in a headline and a few lines of text. Entry to the Microsoft Premier League Hackathon ("Inside the Game").
Video, 1:55: https://youtu.be/rT6zPgLGF38. Its footage is filmed from the deployed demo.
The football here is synthetic. The league, clubs, players, officials and matches are fictional and generated by code in this repository. No real match events, footage, clubs, players or crests are used. Names were checked against real people and clubs; see docs/data.md.
Who it's for and why: docs/audience.md. What each viewer sees: docs/experience.md. Scope and done-list: SCOPE.md.
The demo runs on Azure until judging ends on 10 November 2026, free and with no sign-in: https://ca-web-kwy7jucrk2pdm.whitepebble-d77f6eb9.westus3.azurecontainerapps.io. It replays the showcase match, Saltmarsh Rovers v Kingsferry Athletic, as if it were live.
On the start page, pick who to watch as, where to start and the speed, then Start the replay. A replay begins 30 seconds before the minute picked. Starting as Nadia, the producer, leaves each graphic for her to approve; starting as a fan approves graphics as they're found, and the console's Approve automatically switch changes that either way. Watch as, above the match, switches between the producer and the fans at any point. At 2×, each of these takes a few minutes:
The fifth profile, Priya, owns Teo Varlan in a fantasy league and watches in analyst mode, focused on him, with pass difficulty pinned. A fan's Settings change the mode, club, player in focus, pinned metric, language, stream delay, calm mode, the pitch view and its graphics, and the described feed.
flowchart TB
replayer["Replayer"] -- "feed" --> eh[("Event Hubs")]
eh --> processor["Processor<br>models, insights, templates"]
processor -- "checkpoints" --> blob[("Blob Storage")]
processor -- "state, graphics, jobs" --> pg[("Azure Database<br>for PostgreSQL")]
pg -- "jobs" --> agents["Agents service<br>Agent Framework writers,<br>MCP match tools, checks,<br>translation, producer's desk"]
agents -- "drafts, translations" --> pg
agents -- "Responses API" --> foundry["Foundry<br>gpt-5-mini"]
agents -- "wording in English" --> translator["Azure AI Translator"]
agents -- "traces" --> appi["Application Insights"]
processor -- "events, graphics" --> wps["Web PubSub"]
agents -- "graphics" --> wps
wps --> browser["Browser"]
browser --> web["Web app<br>Next.js"]
web -- "client tokens" --> wps
web -- "start, stop" --> replayer
web -- "snapshots, evidence" --> pg
web -- "producer's actions" --> agents
The four services run as container apps in one Azure Container Apps environment and authenticate with managed identities, so no service uses a key or password. What each one does, how a replay flows through them, the latency measured on the deployed stack and the cost: docs/architecture.md.
Not built yet: a server-side store for viewer profiles. Settings are kept in the browser.
Next steps, after the hackathon:
Needs Python 3.11 and uv; Node.js 24 for the web app.
uv sync
uv run pytest -m "not slow" # tests, a minute or two
uv run python -m footnote.generator showcase # rebuild the committed showcase match in data/
tests/test_store.py runs the SQL against a real Postgres and is skipped
unless FOOTNOTE_TEST_DATABASE_URL names one whose role may create databases,
for example postgresql://[email protected]:5432/postgres. CI runs it against
a Postgres 17 service.
uv run python -m footnote.generator --help lists the other commands: the
league, any single match, the full season and the feed's JSON Schema.
uv run python -m footnote.interpret --workers 8 # refit the models; rewrites their parameters and docs/models.md
Refitting generates the whole season in memory, so it takes a while (the run
time is in docs/models.md). The services load the fitted
parameters committed in src/footnote/interpret/params/.
uv run python -m footnote.evals replay # the agents' recorded output through today's checks, as CI runs it
uv run --group evals python -m footnote.evals live --record --report # draft and judge again on Foundry
A live evaluation needs FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL from
azd env get-values and an Azure CLI sign-in as the account that ran azd up:
azd fills AZURE_PRINCIPAL_ID with that account, and the Bicep gives it the
roles local development needs, Foundry User among them
(docs/architecture.md). Run it
after changing the agents' instructions, tools or workflow: until the recording
matches them, CI fails.
Needs the Azure Developer CLI 1.36 or later (the version
this was deployed with) and the Azure CLI, both signed in to the subscription
(azd auth login and az login) with the right to create resources and assign
roles (Owner, or Contributor with User Access Administrator): the Bicep gives
each service its roles. Register the resource providers the Bicep uses, once
per subscription:
for p in Microsoft.App Microsoft.ContainerRegistry Microsoft.EventHub Microsoft.DBforPostgreSQL \
Microsoft.SignalRService Microsoft.Storage Microsoft.OperationalInsights Microsoft.Insights \
Microsoft.ManagedIdentity Microsoft.CognitiveServices; do
az provider register --namespace "$p"
done
Then:
azd env new footnote
azd env set AZURE_LOCATION westus3
azd up
azd up provisions infra/main.bicep, including a Foundry
project with a Global Standard deployment of gpt-5-mini (the subscription needs
100K tokens a minute of that model's quota), builds the four images in the
container registry (no local Docker needed, except on a subscription running on
free credits, where the registry's builds are paused) and deploys each container
app from infra/<service>.bicep, the processor first: it creates the other
services' database roles. It prints the web app's URL. The demo's stack was built
up from this Bicep over 19–21 October. A fresh azd up into an empty
environment on the same subscription, on 23 October, stopped at two refusals
from Azure: the model deployment in the new Foundry account (error 715-123420,
"unusual activity") and the Postgres server in westus3 ("SkuNotAvailable",
though az postgres flexible-server list-skus offers Standard_B1ms there). On
another subscription or in another region either may go through. To check the
deployed pipeline end to end, as a browser would follow it:
uv run python scripts/smoke_live.py <web app URL> --minute 81 --speed 4
live-check.yml runs the same check on the demo once a day, with
the web app's URL in the repository variable DEMO_URL.
Settings to make with azd env set before azd up, or before a later
azd provision:
TRANSLATOR_ENABLED true adds Azure AI Translator on its free tier for the
graphics in Spanish and French; without it the graphics stay in English.TRANSLATOR_SKU S1 picks the Standard tier, billed by the character, for a
subscription that already has its one free Translator.WEBPUBSUB_SKU is Free_F1 by default: 20 connections and 20,000 messages a
day. Standard_S1 raises both and bills the messages past a million a day.DEPLOY_WRITER_MODEL false leaves the model deployment out of later
provisions. On this project's subscription, Azure refused to submit the
existing deployment again, even unchanged (error 715-123420, "unusual
activity").AZURE_PRINCIPAL_NAME <your sign-in name> makes you a Postgres administrator,
for local development.CLIENT_IP_ADDRESS <your public IP> lets your machine through the Postgres
firewall, for local development.The four container apps each keep a replica running. azd down --purge deletes
the lot, purging the resources Azure keeps after deletion, such as the Foundry
and Translator accounts.
The services run locally against the resources azd up created, signed in as
you through the Azure CLI. The replayer is reachable only inside Azure, so run
it locally too. Settings come from azd env get-values.
# The replayer: EVENTHUB_NAMESPACE and EVENTHUB_NAME
uv run python -m footnote.replayer # http://localhost:8000
# The agents service, with the producer's desk on http://localhost:8080:
# FOUNDRY_PROJECT_ENDPOINT, FOUNDRY_MODEL, WEBPUBSUB_ENDPOINT, WEBPUBSUB_HUB,
# POSTGRES_HOST, POSTGRES_DATABASE, and POSTGRES_USER set to your sign-in name
# (needs AZURE_PRINCIPAL_NAME above); TRANSLATOR_ENDPOINT translates the graphics
# and APPLICATIONINSIGHTS_CONNECTION_STRING traces them, when set. Stop the
# deployed one first, or the two share the jobs.
uv run python -m footnote.agents
# The web app: frontend/.env.local with REPLAYER_URL=http://localhost:8000,
# DESK_URL=http://localhost:8080, WEBPUBSUB_ENDPOINT, WEBPUBSUB_HUB,
# POSTGRES_HOST, POSTGRES_DATABASE, and POSTGRES_USER set to your sign-in name
# (needs AZURE_PRINCIPAL_NAME above); POSTGRES_PORT if it isn't 5432
cd frontend && npm ci && npm run dev # http://localhost:3000
The deployed processor picks up runs started locally. Checks for the web app:
npm run lint, npm run typecheck, npm test, npm run build.
src/footnote/generator/ league, match simulation, officials, feed, tracking, showcase search
src/footnote/calibration/ published targets and the calibration report
src/footnote/interpret/ pass difficulty, the match-state model, distances and tags; their training and report
src/footnote/live/ shared by the services: the match files, replay time, stats, analysis, state, contracts, the overlay contract, the pitch view's tracking
src/footnote/replayer/ plays the showcase feed into Event Hubs, one run per replay
src/footnote/processor/ Event Hubs to match state, insights, Postgres and Web PubSub
src/footnote/insights/ moments found and ranked, facts, templates, the checks every graphic passes
src/footnote/tools/ the match tools: an MCP server answering as of one moment of one run
src/footnote/agents/ the agents service: the Agent Framework writers, their checks, the job loop, the translation worker, the producer's desk
src/footnote/evals/ the agents' evaluations: every agent job in the showcase, code evaluators, the groundedness judge, the report
src/footnote/db/ Entra-authenticated Postgres connections, migrations and roles
src/footnote/cloud.py the services' Azure credentials and settings
src/footnote/telemetry.py the agents service's traces to Application Insights
frontend/ the Next.js web app (fan view, producer console, 2D pitch), with its Vitest tests beside the code
infra/ Bicep: main.bicep, the shared resources in resources.bicep and modules/, and one file per container app
scripts/check_names.py checks every generated name against Wikidata
scripts/smoke_live.py follows a replay on the deployed stack: completeness, order, final state, stored pushes, tracking, latency
tests/ contract, consistency, physics, story, calibration, model, replay, processing, insight, agent, evaluation and SQL checks
data/ generated output; git keeps the league, the showcase match, both answer keys, the recipe, the name check and the agents' recorded evaluation run
docs/ audience, experience, data, calibration, models, insights, evaluations, the overlay contract and its schema, architecture
.github/workflows/ CI: lint, type checks, tests (with a Postgres and the agents' evaluations), the web build and the Bicep, on pushes to main and on pull requests; the live check, once a day
Copyright (c) 2026 Cesaire Tobias. All rights reserved. The code is public so the hackathon can judge it, and that gives no right to use it: see LICENSE. Entering the hackathon grants Microsoft and the Premier League the licence in section 7 of its official rules. Code from other projects keeps its own licence: THIRD_PARTY_NOTICES.md.