You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refine README for production readiness; align docs on v1.0-first-print tag
Adds CI badge, teaching-samples disclaimer, configuration/secrets section,
cost-expectations callout, CI section, and contributing guide. Fixes layout
tree to match disk, drops review-jargon labels, switches main->master in
the versioning table, and renames every `v1.0-print-ready` reference in
docs to the actual `v1.0-first-print` tag.
Every sample in this repo corresponds to a section of the printed book. The full map between book and code lives in [`docs/citation-index.md`](docs/citation-index.md). When the book has been condensed in favor of pointing here, the manuscript cites a **tag** (e.g. `v1.0-print-ready`) so the code stays aligned with the print run.
5
+
Runnable code samples for **Generative AI in .NET** by Najaf Shaikh.
6
+
7
+
Every sample in this repo corresponds to a section of the printed book. The full book-to-code map lives in [`docs/citation-index.md`](docs/citation-index.md). When the book condenses a section in favor of pointing here, the manuscript cites a **tag** (e.g. `v1.0-first-print`) so the cited code matches the print run -- `master` will drift as the surrounding APIs evolve.
8
+
9
+
> **About this code.** These are **teaching samples**, not production-grade libraries. They are written for clarity over coverage: each sample demonstrates a single technique, with error handling, retry, observability, and configuration shown to a useful depth rather than exhaustively. Patterns covered -- prompt caching, resilience, evaluation, model routing, output guards, MCP transports -- are real and copy-pasteable, but hardening, threat-modeling, and cost-bounding them for your environment is your responsibility.
6
10
7
11
## Layout
8
12
9
13
```
10
-
samples/
11
-
ch01-foundations/
12
-
01.3-hello-chat/ -- IChatClient with provider selection
└── appendix-a-packages/ -- Quick-start bundles from Appendix A
60
70
```
61
71
62
72
## Prerequisites
63
73
64
74
-**.NET 9 SDK** (`dotnet --version` should be 9.0.x).
65
-
-**Provider credentials** for samples that hit a live model -- each sample's README names what it needs:
75
+
-**Provider credentials** for samples that hit a live model -- each sample's README names exactly which it needs:
66
76
-`OPENAI_API_KEY` for OpenAI / GitHub Models samples.
67
77
-`AZURE_OPENAI_ENDPOINT` + `AZURE_OPENAI_KEY` for Azure OpenAI samples.
68
78
-`ANTHROPIC_API_KEY` for Claude samples.
69
-
-**Local services** for offline samples: [Ollama](https://ollama.com/) for local inference; an MCP-compatible runtime (`dnx`) for some MCP samples.
79
+
-**[Ollama](https://ollama.com/)** for the offline samples and any sample that lists Ollama as its default profile.
80
+
81
+
The repo uses **central package management** -- versions live in [`Directory.Packages.props`](Directory.Packages.props), shared MSBuild properties in [`samples/Directory.Build.props`](samples/Directory.Build.props). Project files only carry `<PackageReference Include="..." />` -- no version attributes.
82
+
83
+
## Configuration and secrets
70
84
71
-
The repo uses **central package management** -- versions live in [`Directory.Packages.props`](Directory.Packages.props), shared properties in [`samples/Directory.Build.props`](samples/Directory.Build.props). Project files only carry `<PackageReference Include="..." />` -- no version attributes.
85
+
All samples read configuration in the standard .NET cascade: `appsettings.json` -> `appsettings.Development.json` -> environment variables -> User Secrets. **No sample contains a hardcoded API key.** Where User Secrets are required, the sample's README spells out the exact `dotnet user-secrets set` commands.
For anything beyond a developer workstation -- CI, shared environments, deployed services -- use your platform's secret manager (Azure Key Vault, AWS Secrets Manager, Doppler, etc.). Do not commit `appsettings.Development.json` or `.env` files containing keys; the repo's `.gitignore` already excludes the common patterns, but the responsibility is on you.
72
95
73
96
## Running a sample
74
97
@@ -84,6 +107,8 @@ Each sample folder has its own `README.md` with run instructions, expected outpu
84
107
dotnet build
85
108
```
86
109
110
+
builds the full `AI in .Net.sln` solution from the repo root.
111
+
87
112
## What's offline-runnable
88
113
89
114
These samples need **only** Ollama (no API keys, no cloud calls):
@@ -97,33 +122,56 @@ These samples need **only** Ollama (no API keys, no cloud calls):
97
122
98
123
The rest assume an OpenAI / Anthropic / Azure OpenAI key.
99
124
100
-
## 1.x API surface (Agent Framework 1.3 / MCP 1.2)
125
+
## Cost expectations
126
+
127
+
Cloud-provider samples spend real money against your account. Most are single-shot prompts that come in well under a cent at current OpenAI / Azure OpenAI / Anthropic pricing. The two exceptions worth flagging:
128
+
129
+
-`03.2-ingestion-pipeline` embeds a multi-document corpus -- expect a few cents per full ingestion run, depending on the embedding model.
130
+
-`06.5.3-llm-as-judge` and `03.2.7-evaluation` issue judge calls per evaluated response -- a 50-row golden set against a frontier model is typically tens of cents.
131
+
132
+
If you intend to run any sample unattended (CI, scheduled jobs, scripts), set per-key spend caps in your provider console first.
101
133
102
-
All samples target `Microsoft.Agents.AI` 1.3 and `ModelContextProtocol` 1.2. The manuscript was originally drafted against the 0.3.x previews, so the printed code occasionally differs from what's in this repo. The original 0.3-preview snippets are preserved alongside the live code as `*.cs.book.txt` for traceability. The shape changes that recur most often:
134
+
## Continuous integration
135
+
136
+
CI runs on every push and pull request, plus a weekly Monday build to catch transitive package drift. The matrix builds every sample in the `samples/` tree against the pinned versions in `Directory.Packages.props`. A green badge above means the print-tagged code still compiles end-to-end. If the badge is red, check the latest [Actions run](https://github.com/CodeShayk/generative-ai-dotnet-samples/actions/workflows/ci.yml) for the breaking package or API change before assuming the samples are wrong.
137
+
138
+
## Versioning and tags
139
+
140
+
| Tag | Meaning |
141
+
|---|---|
142
+
|`v1.0-first-print`| Code as it appears in the first print run of the book. |
143
+
|`v1.x-second-print`| Updated for any subsequent print revisions (placeholder; not yet cut). |
144
+
|`master`| Always-current; tracks latest stable .NET 9 + Microsoft.Extensions.AI. May drift from any specific print run. |
145
+
146
+
Use a **tag** in any URL you cite from the book -- never `master`.
147
+
148
+
## Notes on the 1.x API surface (Agent Framework 1.3 / MCP 1.2)
149
+
150
+
All samples target `Microsoft.Agents.AI` 1.3 and `ModelContextProtocol` 1.2. The manuscript was originally drafted against the 0.3.x previews, so a few printed snippets differ from what's checked in here. The original 0.3-preview snippets are preserved alongside the live code as `*.cs.book.txt` for traceability. The shape changes that recur most often:
103
151
104
152
-`ChatClientAgentOptions` no longer carries `Instructions` / `Tools` -- they move to `ChatClientAgentOptions.ChatOptions` (`Instructions`, `Tools`) or to the string-arg `ChatClientAgent` constructor.
-`WorkflowBuilder()` parameterless ctor is gone -- the start executor is passed to the constructor (`new WorkflowBuilder(start)`). `Executor.From` / `FromAsync` lambdas became `new FunctionExecutor<TIn, TOut>(id, handler)`. `SetOutputExecutor` -> `WithOutputFrom(...)`. `workflow.RunAsync(...)` was replaced by `InProcessExecution.RunAsync(workflow, input)`.
107
155
- The `AsBuilder().Use(...)` middleware delegate now receives `(messages, session, options, innerAgent, ct)` -- you call `innerAgent.RunAsync(...)` instead of a `next` delegate.
108
-
-`ModelContextProtocol.Client` / `ModelContextProtocol.Server` are no longer separate packages -- everything is in `ModelContextProtocol` / `ModelContextProtocol.Core` / `ModelContextProtocol.AspNetCore`. `McpClientTool`now extends `AIFunction` directly (no `.AsAIFunction()` needed); rename via `tool.WithName(...)`.
156
+
-`ModelContextProtocol.Client` / `ModelContextProtocol.Server` are no longer separate packages -- everything is in `ModelContextProtocol` / `ModelContextProtocol.Core` / `ModelContextProtocol.AspNetCore`. `McpClientTool` extends `AIFunction` directly (no `.AsAIFunction()` needed); rename via `tool.WithName(...)`.
109
157
- Server bootstrap is `.AddMcpServer().WithHttpTransport().WithToolsFromAssembly()` then `app.MapMcp(...)`. `WithHttpServerTransport(...)` and `HttpTransportType.Sse` have been retired -- streamable HTTP is the only HTTP transport.
- A2A server hosting requires implementing `A2A.IAgentHandler`, registering it via `services.AddA2AAgent<THandler>(agentCard)`, then `app.MapA2A("/path")` from `A2A.AspNetCore`. The 0.3-preview's one-liner `app.MapA2A(agent, "/path")` no longer exists.
112
160
-`McpClient.OnToolsListChanged(...)` was replaced by `client.RegisterNotificationHandler(NotificationMethods.ToolListChangedNotification, handler)`, which returns an `IAsyncDisposable`.
113
161
114
-
## Versioning and tags
162
+
## Contributing
115
163
116
-
| Tag | Meaning |
117
-
|---|---|
118
-
|`v1.0-print-ready`| Code as it appears in the first print run. |
119
-
|`v1.x-second-print`| Updated for subsequent print revisions. |
120
-
|`main`| Always-current; may drift from any specific print run. |
164
+
Issues are welcome -- bugs, builds broken by transitive package drift, samples whose APIs have moved on, README mistakes. Pull requests are welcome too, especially:
165
+
166
+
- Build fixes for newer NuGet releases.
167
+
- README clarifications (per sample or repo-wide).
168
+
- New offline-runnable variants of samples that currently require cloud keys.
121
169
122
-
Use a **tag** in any URL you cite from the book -- never `main`.
170
+
Before opening a PR: run `dotnet build` from the repo root and confirm the affected sample(s) still run. If you change observable behavior, update the sample's README.
123
171
124
172
## Errata
125
173
126
-
Open an issue at [github.com/CodeShayk/generative-ai-dotnet-samples](https://github.com/CodeShayk/generative-ai-dotnet-samples). Confirmed errata roll into the next print tag and are noted in the parent book's errata page.
174
+
Open an issue at [github.com/CodeShayk/generative-ai-dotnet-samples](https://github.com/CodeShayk/generative-ai-dotnet-samples/issues). Confirmed errata roll into the next print tag and are noted in the parent book's errata page.
Copy file name to clipboardExpand all lines: docs/citation-index.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
The map between book sections and their runnable companion code in this repository.
4
4
5
-
When the manuscript condenses a section and points at this repo, the citation should always reference a **tag** (e.g. `v1.0-print-ready`) rather than `main`. `main` will drift.
5
+
When the manuscript condenses a section and points at this repo, the citation should always reference a **tag** (e.g. `v1.0-first-print`) rather than `master`. `master` will drift.
6
6
7
7
## Chapter 1 -- Foundations
8
8
@@ -75,7 +75,7 @@ When the manuscript condenses a section and points at this repo, the citation sh
75
75
76
76
When a manuscript section is condensed in favor of pointing here, use this exact wording (substitute the tag and path):
0 commit comments