Skip to content

Commit

Permalink
.Net: Anthropic - streaming (#8560)
Browse files Browse the repository at this point in the history
### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->

#5690

### Description

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->

Added streaming functionality and related tests.

@RogerBarreto @RogerBarret0

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
  • Loading branch information
Krzysztof318 authored Oct 29, 2024
1 parent 86e169a commit 17cfd02
Show file tree
Hide file tree
Showing 13 changed files with 818 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.Anthropic;
using Microsoft.SemanticKernel.Connectors.Anthropic.Core;
using Microsoft.SemanticKernel.Connectors.Anthropic.Core.Models;
using Microsoft.SemanticKernel.Http;
using SemanticKernel.Connectors.Anthropic.UnitTests.Utils;
using Xunit;

namespace SemanticKernel.Connectors.Anthropic.UnitTests.Core;

/// <summary>
/// Test for <see cref="AnthropicClient"/>
/// </summary>
public sealed class AnthropicClientChatGenerationTests : IDisposable
public sealed class AnthropicChatGenerationTests : IDisposable
{
private readonly HttpClient _httpClient;
private readonly HttpMessageHandlerStub _messageHandlerStub;
private const string ChatTestDataFilePath = "./TestData/chat_one_response.json";

public AnthropicClientChatGenerationTests()
public AnthropicChatGenerationTests()
{
this._messageHandlerStub = new HttpMessageHandlerStub();
this._messageHandlerStub.ResponseToReturn.Content = new StringContent(
Expand Down Expand Up @@ -243,11 +244,13 @@ public async Task ShouldPassSystemMessageToRequestAsync()
}

[Fact]
public async Task ShouldPassVersionToRequestBodyIfCustomHandlerUsedAsync()
public async Task ShouldPassVersionToRequestBodyIfThirdVendorIsUsedAsync()
{
// Arrange
var options = new AnthropicClientOptions();
var client = new AnthropicClient("fake-model", "api-key", options: new(), httpClient: this._httpClient);
var options = new AmazonBedrockAnthropicClientOptions();
var client = new AnthropicClient("fake-model", new Uri("https://fake-uri.com"),
bearerTokenProvider: () => ValueTask.FromResult("fake-token"),
options: options, httpClient: this._httpClient);

var chatHistory = CreateSampleChatHistory();

Expand Down Expand Up @@ -390,7 +393,7 @@ public async Task ItCreatesRequestWithCustomUriAndCustomHeadersAsync(string head
{
// Arrange
Uri uri = new("https://fake-uri.com");
using var httpHandler = new CustomHeadersHandler(headerName, headerValue);
using var httpHandler = new CustomHeadersHandler(headerName, headerValue, ChatTestDataFilePath);
using var httpClient = new HttpClient(httpHandler);
httpClient.BaseAddress = uri;
var client = new AnthropicClient("fake-model", "api-key", options: new(), httpClient: httpClient);
Expand Down Expand Up @@ -439,40 +442,4 @@ public void Dispose()
this._httpClient.Dispose();
this._messageHandlerStub.Dispose();
}

private sealed class CustomHeadersHandler : DelegatingHandler
{
private readonly string _headerName;
private readonly string _headerValue;
public HttpRequestHeaders? RequestHeaders { get; private set; }

public HttpContentHeaders? ContentHeaders { get; private set; }

public byte[]? RequestContent { get; private set; }

public Uri? RequestUri { get; private set; }

public HttpMethod? Method { get; private set; }

public CustomHeadersHandler(string headerName, string headerValue)
{
this.InnerHandler = new HttpMessageHandlerStub
{
ResponseToReturn = { Content = new StringContent(File.ReadAllText(ChatTestDataFilePath)) }
};
this._headerName = headerName;
this._headerValue = headerValue;
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Headers.Add(this._headerName, this._headerValue);
this.Method = request.Method;
this.RequestUri = request.RequestUri;
this.RequestHeaders = request.Headers;
this.RequestContent = request.Content is null ? null : request.Content.ReadAsByteArrayAsync(cancellationToken).Result;

return base.SendAsync(request, cancellationToken);
}
}
}
Loading

0 comments on commit 17cfd02

Please sign in to comment.