Skip to content

Commit 61dcce6

Browse files
jeffhandleystephentoubMackinnonBuckSteveSandersonMSgewarren
authored
Prepare 9.4.x update for Microsoft.Extensions.AI (#6409)
* Update CHANGELOGS for M.E.AI libs (#6359) * Add project template build tests + CG reporting (#6355) Co-authored-by: Steve Sanderson <[email protected]> * Use ConversationId instead of ChatThreadId (#6367) * Update OpenTelemetryChatClient/EmbeddingGenerator to 1.33 (#6366) Also adds the Enable SensitiveData property to OpenTelemetryEmbeddingGenerators. This was missed when adding it to OpenTelemetryChatClient. * Add AsIEmbeddingGenerator for Azure.AI.Inference ImageEmbeddingsClient (#6363) * Add DataContent.Base64Data (#6365) * Fix AIFunctionFactory handling of default struct arguments (#6381) * Fix AIFunctionFactory handling of default struct arguments * Extend testing to custom structs * Use GetUninitializedObject instead of Activator * Add JS dependency update instructions to chat template README (#6376) * Add see also links to conceptual docs (#6368) * Translate OpenAI refusals to ErrorContent (#6393) Refusals in OpenAI are errors reported when the service can't generate an output that matches the requested schema. Translate refusals to ErrorContent now that we have it. * Rename useJsonSchema parameter (#6394) * Rename useJsonSchema parameter The `GetResponseAsync<T>` methods accept a `bool?` parameter currently called `useJsonSchema`. This is confusing, because the whole point of the method is to create and use a JSON schema from the `T`. The parameter actually controls _how_ that schema is used, whether it's included as part of the messages (false), as part of a ChatResponseFormat in the ChatOptions (true), or up to the system to decide. I've clarified it by renaming it from `useJsonSchema` to `useJsonSchemaResponseFormat`. It's wordier, but it disambiguates the intent. * Update src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientStructuredOutputExtensions.cs Co-authored-by: Eirik Tsarpalis <[email protected]> --------- Co-authored-by: Eirik Tsarpalis <[email protected]> * Add JSON schema transformation functionality to `AIJsonUtilities` (#6383) * Add initial schema transformation functionality and incorporate into the OpenAI leaf client. * Update all leaf client implementions, improve naming, add testing. * Remove redundant suppressions * Address feedback. * Add ChatOptions.RawRepresentationFactory (#6319) * Look for OpenAI.ChatCompletionOptions in top-level additional properties and stop looking for individually specific additional properties * Add RawRepresentation to ChatOptions and use it in OpenAI and AzureAIInference * Remove now unused locals * Add [JsonIgnore] and update roundtrip tests * Overwirte properties only if the underlying model don't specify it already * Clone RawRepresentation * Reflection workaround for ToolChoice not being cloned * Style changes * AI.Inference: Bring back propagation of additional properties * Don't use 0.1f, it doesn't roundtrip properly in .NET Framework * Add RawRepresentationFactory instead of object? property * Augment remarks to discourage returning shared instances * Documentation feedback * AI.Inference: keep passing TopK as AdditionalProperty if not already there * Avoid caching in CachingChatClient when ConversationId is set (#6400) * Add comment LoggingChatClient et al trace-level logging (#6391) Also fixed the name of the LoggingSpeechToTextClientBuilderExtensions type to conform to patterns used elsewhere in the library. * Fix test validation of aggregate usage counts (#6401) * Add BinaryEmbedding (#6398) * Add BinaryEmbedding Also: - Renames the polymorphic discriminators to conform with typical lingo for these types. - Adds an Embedding.Dimensions virtual property. * Fix keys for EvaluationResult.Metrics dictionary to reflect the correct metric names for Safety evaluators (#6361) This was an unfortunate regression that was introduced during a recent refactoring. The metrics returned from the Azure AI Foundry Evaluation service have different names than the ones we use in the Safety library. We translate the EvaluationMetric.Name of the metrics returned by the service to the more display friendly names used in the library before returning the metrics to the caller. While the returned metrics were correctly patched up, the EvaluationResult.Metrics dictionary still stored these metrics by the original names returned from the service. Unfortunately, this meant EvaluationResult.Get would throw an exception when trying to fetch metric with name ViolenceEvaluator.ViolenceMetricName. The fix in this commit fixes the keys in the dictionary as well. This commit also updates tests to cover the case being fixed. Fixes #6360 * Update branding for Azure service used by Safety evaluators (#6362) `Azure AI Content Safety service` -> `Azure AI Foundry Evaluation service` * Remove CacheOptions from DiskBasedResponseCache (#6395) Details for this change are available in #6387. Fixes #6387 * Add back net9.0 version of the aieval dotnet tool (#6396) In #6148, we disabled net9.0 TFM for the aieval tool to work around the race described in dotnet/sdk#47696. The underlying issue was subsequently fixed in the SDK (via dotnet/sdk#47788). However, this fix has not been backported to the dotnet 9 SDK yet. The SDK team is working on backporting the fix (see discussion in dotnet/sdk#47788 (comment)). But in the meanwhile, we can add back the net9.0 TFM and continue to work around the race by disabling parallel build. This would help users of the aieval tool sidestep errors such as the ones described in #6388 when they dont have dotnet8 installed on the machine. We can remove this workaround, once the backported fix is available in the dotnet 9 SDK. Fixes #6388 * Add some additional documentation around usage of cache, and CSP properties on report (#6377) * Add documentation around proper usage of IDistributedCache * Add Content-Security-Policy to prevent page from calling into other sites. * Remove remark about IDistributedCache usage * Fix package-lock.json * Remove <remarks> start tag. * Some API related fixes for the evaluation libraries (#6402) * Rename IResultStore and IResponseCacheProvider IResultStore -> IEvaluationResultStore and IResponseCacheProvider -> IEvaluationResponseCacheProvider * Include missing EvaluationContextConverter in AzureStorageJsonUtilities Also use linked files to avoid the need to duplicate code. * Reorder enum members The new order goes from least desirable rating to most desirable. * Refactor extension method overloads Implement overloads that take ChatMessage by calling corresponding overloads that take ChatResponse. * Refactor AddTurnDetails to support adding details for multiple turns Adding single turns continues to be supported via a params array overload. * Add missing parameter for timeToLiveForCacheEntries to DiskBasedReportingConfiguration This was missed in an earlier PR that introduced the timeToLiveForCacheEntries on the constructor of DiskBasedResponseCacheProvider. Also reorder constructor parameters for AzureStorageReportingConfiguration so that the parameters for caching apear next to each other and so that the parameter ordering is aligned with DiskBasedReportingConfiguration. * Minor formatting changes * Bump vite from 6.2.6 to 6.3.4 in /src/Libraries/Microsoft.Extensions.AI.Evaluation.Reporting/TypeScript (#6354) * Bump vite Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.6 to 6.3.4. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.3.4/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-version: 6.3.4 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <[email protected]> --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Shyam Namboodiripad <[email protected]> * Allow image rendering in evaluation report (#6407) --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Stephen Toub <[email protected]> Co-authored-by: Mackinnon Buck <[email protected]> Co-authored-by: Steve Sanderson <[email protected]> Co-authored-by: Genevieve Warren <[email protected]> Co-authored-by: Eirik Tsarpalis <[email protected]> Co-authored-by: David Cantú <[email protected]> Co-authored-by: Shyam N <[email protected]> Co-authored-by: Peter Waldschmidt <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Shyam Namboodiripad <[email protected]>
1 parent c3514c1 commit 61dcce6

File tree

182 files changed

+4674
-1193
lines changed

Some content is hidden

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

182 files changed

+4674
-1193
lines changed

eng/MSBuild/LegacySupport.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
<Compile Include="$(MSBuildThisFileDirectory)\..\..\src\LegacySupport\RequiredMemberAttribute\*.cs" LinkBase="LegacySupport\RequiredMemberAttribute" />
88
</ItemGroup>
99

10+
<ItemGroup Condition="'$(InjectSystemIndexOnLegacy)' == 'true' AND ('$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netcoreapp3.1')">
11+
<Compile Include="$(MSBuildThisFileDirectory)\..\..\src\LegacySupport\SystemIndex\*.cs" LinkBase="LegacySupport\SystemIndex" />
12+
</ItemGroup>
13+
1014
<ItemGroup Condition="'$(InjectDiagnosticAttributesOnLegacy)' == 'true' AND ('$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netcoreapp3.1')">
1115
<Compile Include="$(MSBuildThisFileDirectory)\..\..\src\LegacySupport\DiagnosticAttributes\*.cs" LinkBase="LegacySupport\DiagnosticAttributes" />
1216
</ItemGroup>

eng/build.proj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.Build.Traversal">
22
<ItemGroup>
33
<_SnapshotsToExclude Include="$(MSBuildThisFileDirectory)..\test\**\Snapshots\**\*.*proj" />
4+
<_GeneratedContentToExclude Include="$(MSBuildThisFileDirectory)..\test\**\TemplateSandbox\**\*.*proj" />
45

56
<!-- We recursively add all of the projects inside the src directory, except for the exclusions above -->
67
<_ProjectsToBuild Include="$(MSBuildThisFileDirectory)..\src\**\*.csproj" />
@@ -11,6 +12,6 @@
1112
<_ProjectsToBuild Include="$(MSBuildThisFileDirectory)..\src\Packages\Microsoft.Internal.Extensions.DotNetApiDocs.Transport\Microsoft.Internal.Extensions.DotNetApiDocs.Transport.proj" />
1213

1314
<!-- Add all the projects we want to build as project references, so the traversal SDK can build them -->
14-
<ProjectReference Include="@(_ProjectsToBuild)" Exclude="@(_ProjectsToExclude);@(_SnapshotsToExclude)" />
15+
<ProjectReference Include="@(_ProjectsToBuild)" Exclude="@(_ProjectsToExclude);@(_SnapshotsToExclude);@(_GeneratedContentToExclude)" />
1516
</ItemGroup>
16-
</Project>
17+
</Project>

eng/pipelines/templates/BuildAndTest.yml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,25 @@ steps:
5656
--settings $(Build.SourcesDirectory)/eng/CodeCoverage.config
5757
--output ${{ parameters.repoTestResultsPath }}/$(Agent.JobName)_CodeCoverageResults/$(Agent.JobName)_cobertura.xml
5858
"${{ parameters.buildScript }} -test -configuration ${{ parameters.buildConfig }} /bl:${{ parameters.repoLogPath }}/tests.binlog $(_OfficialBuildIdArgs)"
59-
displayName: Run tests
59+
displayName: Run unit tests
60+
61+
- script: ${{ parameters.buildScript }}
62+
-pack
63+
-configuration ${{ parameters.buildConfig }}
64+
-warnAsError 1
65+
/bl:${{ parameters.repoLogPath }}/pack.binlog
66+
/p:Restore=false /p:Build=false
67+
$(_OfficialBuildIdArgs)
68+
displayName: Pack
69+
70+
- ${{ if ne(parameters.skipTests, 'true') }}:
71+
- script: ${{ parameters.buildScript }}
72+
-integrationTest
73+
-configuration ${{ parameters.buildConfig }}
74+
-warnAsError 1
75+
/bl:${{ parameters.repoLogPath }}/integration_tests.binlog
76+
$(_OfficialBuildIdArgs)
77+
displayName: Run integration tests
6078

6179
- pwsh: |
6280
$SourcesDirectory = '$(Build.SourcesDirectory)';
@@ -151,12 +169,11 @@ steps:
151169
displayName: Build Azure DevOps plugin
152170
153171
- script: ${{ parameters.buildScript }}
154-
-pack
155172
-sign $(_SignArgs)
156173
-publish $(_PublishArgs)
157174
-configuration ${{ parameters.buildConfig }}
158175
-warnAsError 1
159-
/bl:${{ parameters.repoLogPath }}/pack.binlog
176+
/bl:${{ parameters.repoLogPath }}/publish.binlog
160177
/p:Restore=false /p:Build=false
161178
$(_OfficialBuildIdArgs)
162-
displayName: Pack, sign, and publish
179+
displayName: Sign and publish
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
using System.Runtime.CompilerServices;
6+
7+
#pragma warning disable CS0436 // Type conflicts with imported type
8+
#pragma warning disable S3427 // Method overloads with default parameter values should not overlap
9+
#pragma warning disable SA1642 // Constructor summary documentation should begin with standard text
10+
#pragma warning disable IDE0011 // Add braces
11+
#pragma warning disable SA1623 // Property summary documentation should match accessors
12+
#pragma warning disable IDE0023 // Use block body for conversion operator
13+
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
14+
#pragma warning disable LA0001 // Use the 'Microsoft.Shared.Diagnostics.Throws' class instead of explicitly throwing exception for improved performance
15+
#pragma warning disable CA1305 // Specify IFormatProvider
16+
17+
namespace System
18+
{
19+
internal readonly struct Index : IEquatable<Index>
20+
{
21+
private readonly int _value;
22+
23+
/// <summary>Construct an Index using a value and indicating if the index is from the start or from the end.</summary>
24+
/// <param name="value">The index value. it has to be zero or positive number.</param>
25+
/// <param name="fromEnd">Indicating if the index is from the start or from the end.</param>
26+
/// <remarks>
27+
/// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
28+
/// </remarks>
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public Index(int value, bool fromEnd = false)
31+
{
32+
if (value < 0)
33+
{
34+
ThrowValueArgumentOutOfRange_NeedNonNegNumException();
35+
}
36+
37+
if (fromEnd)
38+
_value = ~value;
39+
else
40+
_value = value;
41+
}
42+
43+
// The following private constructors mainly created for perf reason to avoid the checks
44+
private Index(int value)
45+
{
46+
_value = value;
47+
}
48+
49+
/// <summary>Create an Index pointing at first element.</summary>
50+
public static Index Start => new Index(0);
51+
52+
/// <summary>Create an Index pointing at beyond last element.</summary>
53+
public static Index End => new Index(~0);
54+
55+
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
56+
/// <param name="value">The index value from the start.</param>
57+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58+
public static Index FromStart(int value)
59+
{
60+
if (value < 0)
61+
{
62+
ThrowValueArgumentOutOfRange_NeedNonNegNumException();
63+
}
64+
65+
return new Index(value);
66+
}
67+
68+
/// <summary>Create an Index from the end at the position indicated by the value.</summary>
69+
/// <param name="value">The index value from the end.</param>
70+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
71+
public static Index FromEnd(int value)
72+
{
73+
if (value < 0)
74+
{
75+
ThrowValueArgumentOutOfRange_NeedNonNegNumException();
76+
}
77+
78+
return new Index(~value);
79+
}
80+
81+
/// <summary>Returns the index value.</summary>
82+
public int Value
83+
{
84+
get
85+
{
86+
if (_value < 0)
87+
return ~_value;
88+
else
89+
return _value;
90+
}
91+
}
92+
93+
/// <summary>Indicates whether the index is from the start or the end.</summary>
94+
public bool IsFromEnd => _value < 0;
95+
96+
/// <summary>Calculate the offset from the start using the giving collection length.</summary>
97+
/// <param name="length">The length of the collection that the Index will be used with. length has to be a positive value.</param>
98+
/// <remarks>
99+
/// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
100+
/// we don't validate either the returned offset is greater than the input length.
101+
/// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
102+
/// then used to index a collection will get out of range exception which will be same affect as the validation.
103+
/// </remarks>
104+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
105+
public int GetOffset(int length)
106+
{
107+
int offset = _value;
108+
if (IsFromEnd)
109+
{
110+
// offset = length - (~value)
111+
// offset = length + (~(~value) + 1)
112+
// offset = length + value + 1
113+
114+
offset += length + 1;
115+
}
116+
117+
return offset;
118+
}
119+
120+
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
121+
/// <param name="value">An object to compare with this object.</param>
122+
public override bool Equals([NotNullWhen(true)] object? value) => value is Index && _value == ((Index)value)._value;
123+
124+
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
125+
/// <param name="other">An object to compare with this object.</param>
126+
public bool Equals(Index other) => _value == other._value;
127+
128+
/// <summary>Returns the hash code for this instance.</summary>
129+
public override int GetHashCode() => _value;
130+
131+
/// <summary>Converts integer number to an Index.</summary>
132+
public static implicit operator Index(int value) => FromStart(value);
133+
134+
/// <summary>Converts the value of the current Index object to its equivalent string representation.</summary>
135+
public override string ToString()
136+
{
137+
if (IsFromEnd)
138+
return ToStringFromEnd();
139+
140+
return ((uint)Value).ToString();
141+
}
142+
143+
private static void ThrowValueArgumentOutOfRange_NeedNonNegNumException()
144+
{
145+
throw new ArgumentOutOfRangeException("value", "value must be non-negative");
146+
}
147+
148+
private string ToStringFromEnd()
149+
{
150+
#if (!NETSTANDARD2_0 && !NETFRAMEWORK)
151+
Span<char> span = stackalloc char[11]; // 1 for ^ and 10 for longest possible uint value
152+
bool formatted = ((uint)Value).TryFormat(span.Slice(1), out int charsWritten);
153+
span[0] = '^';
154+
return new string(span.Slice(0, charsWritten + 1));
155+
#else
156+
return '^' + Value.ToString();
157+
#endif
158+
}
159+
}
160+
}

src/Libraries/Microsoft.Extensions.AI.Abstractions/CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Release History
22

3+
## 9.4.3-preview.1.25230.7
4+
5+
- Renamed `ChatThreadId` to `ConversationId` on `ChatResponse`, `ChatResponseUpdate`, and `ChatOptions`.
6+
- Renamed `EmbeddingGeneratorExtensions` method `GenerateEmbeddingAsync` to `GenerateAsync` and `GenerateEmbeddingVectorAsync` to `GenerateVectorAsync`.
7+
- Made `AIContent`'s constructor `public` instead of `protected`.
8+
- Fixed `AIJsonUtilities.CreateJsonSchema` to tolerate `JsonSerializerOptions` instances that don't have a `TypeInfoResolver` already configured.
9+
310
## 9.4.0-preview.1.25207.5
411

512
- Added `ErrorContent` and `TextReasoningContent`.
@@ -83,4 +90,4 @@
8390

8491
## 9.0.0-preview.9.24507.7
8592

86-
Initial Preview
93+
- Initial Preview

src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatOptions.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Text.Json.Serialization;
67

78
namespace Microsoft.Extensions.AI;
89

910
/// <summary>Represents the options for a chat request.</summary>
11+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#provide-options">Provide options.</related>
1012
public class ChatOptions
1113
{
1214
/// <summary>Gets or sets an optional identifier used to associate a request with an existing conversation.</summary>
@@ -20,6 +22,7 @@ public string? ChatThreadId
2022
}
2123

2224
/// <summary>Gets or sets an optional identifier used to associate a request with an existing conversation.</summary>
25+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#stateless-vs-stateful-clients">Stateless vs. stateful clients.</related>
2326
public string? ConversationId { get; set; }
2427

2528
/// <summary>Gets or sets the temperature for generating chat responses.</summary>
@@ -115,9 +118,30 @@ public string? ChatThreadId
115118
public ChatToolMode? ToolMode { get; set; }
116119

117120
/// <summary>Gets or sets the list of tools to include with a chat request.</summary>
121+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#tool-calling">Tool calling.</related>
118122
[JsonIgnore]
119123
public IList<AITool>? Tools { get; set; }
120124

125+
/// <summary>
126+
/// Gets or sets a callback responsible of creating the raw representation of the chat options from an underlying implementation.
127+
/// </summary>
128+
/// <remarks>
129+
/// The underlying <see cref="IChatClient" /> implementation may have its own representation of options.
130+
/// When <see cref="IChatClient.GetResponseAsync" /> or <see cref="IChatClient.GetStreamingResponseAsync" />
131+
/// is invoked with a <see cref="ChatOptions" />, that implementation may convert the provided options into
132+
/// its own representation in order to use it while performing the operation. For situations where a consumer knows
133+
/// which concrete <see cref="IChatClient" /> is being used and how it represents options, a new instance of that
134+
/// implementation-specific options type may be returned by this callback, for the <see cref="IChatClient" />
135+
/// implementation to use instead of creating a new instance. Such implementations may mutate the supplied options
136+
/// instance further based on other settings supplied on this <see cref="ChatOptions" /> instance or from other inputs,
137+
/// like the enumerable of <see cref="ChatMessage"/>s, therefore, its **strongly recommended** to not return shared instances
138+
/// and instead make the callback return a new instance per each call.
139+
/// This is typically used to set an implementation-specific setting that isn't otherwise exposed from the strongly-typed
140+
/// properties on <see cref="ChatOptions" />.
141+
/// </remarks>
142+
[JsonIgnore]
143+
public Func<IChatClient, object?>? RawRepresentationFactory { get; set; }
144+
121145
/// <summary>Gets or sets any additional properties associated with the options.</summary>
122146
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }
123147

@@ -144,6 +168,7 @@ public virtual ChatOptions Clone()
144168
ModelId = ModelId,
145169
AllowMultipleToolCalls = AllowMultipleToolCalls,
146170
ToolMode = ToolMode,
171+
RawRepresentationFactory = RawRepresentationFactory,
147172
AdditionalProperties = AdditionalProperties?.Clone(),
148173
};
149174

src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/ChatResponse.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public string? ChatThreadId
9292
/// or may not differ on every response, depending on whether the underlying provider uses a fixed ID for each conversation
9393
/// or updates it for each message.
9494
/// </remarks>
95+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#stateless-vs-stateful-clients">Stateless vs. stateful clients.</related>
9596
public string? ConversationId { get; set; }
9697

9798
/// <summary>Gets or sets the model ID used in the creation of the chat response.</summary>

src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/DelegatingChatClient.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace Microsoft.Extensions.AI;
1616
/// This is recommended as a base type when building clients that can be chained around an underlying <see cref="IChatClient"/>.
1717
/// The default implementation simply passes each call to the inner client instance.
1818
/// </remarks>
19+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#custom-ichatclient-middleware">Custom IChatClient middleware.</related>
1920
public class DelegatingChatClient : IChatClient
2021
{
2122
/// <summary>

src/Libraries/Microsoft.Extensions.AI.Abstractions/ChatCompletion/IChatClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace Microsoft.Extensions.AI;
2424
/// </para>
2525
/// </remarks>
2626
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/quickstarts/build-chat-app">Build an AI chat app with .NET.</related>
27+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#the-ichatclient-interface">The IChatClient interface.</related>
2728
public interface IChatClient : IDisposable
2829
{
2930
/// <summary>Sends chat messages and returns the response.</summary>
@@ -32,6 +33,7 @@ public interface IChatClient : IDisposable
3233
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
3334
/// <returns>The response messages generated by the client.</returns>
3435
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
36+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#request-a-chat-response">Request a chat response.</related>
3537
Task<ChatResponse> GetResponseAsync(
3638
IEnumerable<ChatMessage> messages,
3739
ChatOptions? options = null,
@@ -43,6 +45,7 @@ Task<ChatResponse> GetResponseAsync(
4345
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
4446
/// <returns>The response messages generated by the client.</returns>
4547
/// <exception cref="ArgumentNullException"><paramref name="messages"/> is <see langword="null"/>.</exception>
48+
/// <related type="Article" href="https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai#request-a-streaming-chat-response">Request a streaming chat response.</related>
4649
IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
4750
IEnumerable<ChatMessage> messages,
4851
ChatOptions? options = null,

0 commit comments

Comments
 (0)