Skip to content

Commit

Permalink
Added the session properties model
Browse files Browse the repository at this point in the history
  • Loading branch information
alistar-andrei committed Aug 8, 2024
1 parent 6fa032b commit 13798f4
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 69 deletions.
16 changes: 16 additions & 0 deletions src/dotnet/Common/Models/Chat/SessionProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;

namespace FoundationaLLM.Common.Models.Chat
{
/// <summary>
/// The session properties object.
/// </summary>
public class SessionProperties
{
/// <summary>
/// The session name.
/// </summary>
[JsonPropertyName("session_name")]
public required string SessionName { get; set; }
}
}
8 changes: 4 additions & 4 deletions src/dotnet/Core/Interfaces/ICoreService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ public interface ICoreService
/// Creates a new chat session.
/// </summary>
/// <param name="instanceId">The instance Id.</param>
/// <param name="sessionName">The name for the chat session.</param>
Task<Session> CreateNewChatSessionAsync(string instanceId, string sessionName);
/// <param name="sessionProperties">The session properties.</param>
Task<Session> CreateNewChatSessionAsync(string instanceId, SessionProperties sessionProperties);

/// <summary>
/// Rename the chat session from its default (eg., "New Chat") to the summary provided by OpenAI.
/// </summary>
/// <param name="instanceId">The instance id.</param>
/// <param name="sessionId">The session id to rename.</param>
/// <param name="sessionName">The new name for the chat session.</param>
Task<Session> RenameChatSessionAsync(string instanceId, string sessionId, string sessionName);
/// <param name="sessionProperties">The session properties.</param>
Task<Session> RenameChatSessionAsync(string instanceId, string sessionId, SessionProperties sessionProperties);

/// <summary>
/// Delete a chat session and related messages.
Expand Down
12 changes: 6 additions & 6 deletions src/dotnet/Core/Services/CoreService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,26 @@ public async Task<List<Message>> GetChatSessionMessagesAsync(string instanceId,
}

/// <inheritdoc/>
public async Task<Session> CreateNewChatSessionAsync(string instanceId, string sessionName)
public async Task<Session> CreateNewChatSessionAsync(string instanceId, SessionProperties sessionProperties)
{
ArgumentException.ThrowIfNullOrEmpty(sessionName);
ArgumentException.ThrowIfNullOrEmpty(sessionProperties.SessionName);

Session session = new()
{
Name = sessionName,
Name = sessionProperties.SessionName,
Type = _sessionType,
UPN = _callContext.CurrentUserIdentity?.UPN ?? throw new InvalidOperationException("Failed to retrieve the identity of the signed in user when creating a new chat session.")
};
return await _cosmosDbService.InsertSessionAsync(session);
}

/// <inheritdoc/>
public async Task<Session> RenameChatSessionAsync(string instanceId, string sessionId, string sessionName)
public async Task<Session> RenameChatSessionAsync(string instanceId, string sessionId, SessionProperties sessionProperties)
{
ArgumentNullException.ThrowIfNull(sessionId);
ArgumentException.ThrowIfNullOrEmpty(sessionName);
ArgumentException.ThrowIfNullOrEmpty(sessionProperties.SessionName);

return await _cosmosDbService.UpdateSessionNameAsync(sessionId, sessionName);
return await _cosmosDbService.UpdateSessionNameAsync(sessionId, sessionProperties.SessionName);
}

/// <inheritdoc/>
Expand Down
12 changes: 6 additions & 6 deletions src/dotnet/CoreAPI/Controllers/SessionsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@ public async Task<CompletionPrompt> GetCompletionPrompt(string instanceId, strin
/// Creates a new chat session.
/// </summary>
/// <param name="instanceId">The id of the instance.</param>
/// <param name="sessionName">The name for the chat session.</param>
/// <param name="sessionProperties">The session properties.</param>
[HttpPost(Name = "CreateNewChatSession")]
public async Task<Session> CreateNewChatSession(string instanceId, [FromBody] string sessionName) =>
await _coreService.CreateNewChatSessionAsync(instanceId, sessionName);
public async Task<Session> CreateNewChatSession(string instanceId, [FromBody] SessionProperties sessionProperties) =>
await _coreService.CreateNewChatSessionAsync(instanceId, sessionProperties);

/// <summary>
/// Rename the chat session.
/// </summary>
/// <param name="instanceId">The id of the instance.</param>
/// <param name="sessionId">The id of the session to rename.</param>
/// <param name="sessionName">The new name for the session.</param>
/// <param name="sessionProperties">The session properties.</param>
[HttpPost("{sessionId}/rename", Name = "RenameChatSession")]
public async Task<Session> RenameChatSession(string instanceId, string sessionId, [FromBody] string sessionName) =>
await _coreService.RenameChatSessionAsync(instanceId, sessionId, sessionName);
public async Task<Session> RenameChatSession(string instanceId, string sessionId, [FromBody] SessionProperties sessionProperties) =>
await _coreService.RenameChatSessionAsync(instanceId, sessionId, sessionProperties);

/// <summary>
/// Delete a chat session and related messages.
Expand Down
10 changes: 5 additions & 5 deletions src/dotnet/CoreClient/Clients/RESTClients/SessionRESTClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ internal class SessionRESTClient(
private readonly string _instanceId = instanceId ?? throw new ArgumentNullException(nameof(instanceId));

/// <inheritdoc/>
public async Task<string> CreateSessionAsync(string sessionName)
public async Task<string> CreateSessionAsync(SessionProperties sessionProperties)
{
var coreClient = await GetCoreClientAsync();
var responseSession = await coreClient.PostAsync(
$"instances/{_instanceId}/sessions",
JsonContent.Create(sessionName));
JsonContent.Create(sessionProperties));

if (responseSession.IsSuccessStatusCode)
{
Expand All @@ -38,16 +38,16 @@ public async Task<string> CreateSessionAsync(string sessionName)
}

/// <inheritdoc/>
public async Task<string> RenameChatSession(string sessionId, string sessionName)
public async Task<string> RenameChatSession(string sessionId, SessionProperties sessionProperties)
{
var coreClient = await GetCoreClientAsync();
var response = await coreClient.PostAsync(
$"instances/{_instanceId}/sessions/{sessionId}/rename",
JsonContent.Create(sessionName));
JsonContent.Create(sessionProperties));

if (response.IsSuccessStatusCode)
{
return sessionName;
return sessionProperties.SessionName;
}

throw new Exception($"Failed to rename chat session. Status code: {response.StatusCode}. Reason: {response.ReasonPhrase}");
Expand Down
23 changes: 13 additions & 10 deletions src/dotnet/CoreClient/CoreClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,29 @@ public CoreClient(
_coreRestClient = new CoreRESTClient(coreUri, credential, instanceId, options);

/// <inheritdoc/>
public async Task<string> CreateChatSessionAsync(string sessionName)
public async Task<string> CreateChatSessionAsync(SessionProperties sessionProperties)
{
var sessionId = await _coreRestClient.Sessions.CreateSessionAsync(sessionName);
if (string.IsNullOrWhiteSpace(sessionProperties.SessionName))
throw new ArgumentException("A session name must be provided when creating a new session.");

var sessionId = await _coreRestClient.Sessions.CreateSessionAsync(sessionProperties);
return sessionId;
}

/// <inheritdoc/>
public async Task<Completion> GetCompletionWithSessionAsync(string? sessionId, string? sessionName,
public async Task<Completion> GetCompletionWithSessionAsync(string? sessionId, SessionProperties? sessionProperties,
string userPrompt, string agentName)
{
if (string.IsNullOrWhiteSpace(sessionId))
{
if (string.IsNullOrWhiteSpace(sessionName))
if (sessionProperties == null)
{
throw new ArgumentException(
"The completion request must contain a sessionName if no sessionId is provided. " +
"The completion request must contain a session name if no session Id is provided. " +
"A new session will be created with the provided session name.");
}

sessionId = await CreateChatSessionAsync(sessionName);
sessionId = await CreateChatSessionAsync(sessionProperties);
}

var orchestrationRequest = new CompletionRequest
Expand Down Expand Up @@ -129,7 +132,7 @@ public async Task<Completion> GetCompletionAsync(CompletionRequest completionReq

/// <inheritdoc/>
public async Task<Completion> AttachFileAndAskQuestionAsync(Stream fileStream, string fileName, string contentType,
string agentName, string question, bool useSession, string? sessionId, string? sessionName)
string agentName, string question, bool useSession, string? sessionId, SessionProperties? sessionProperties)
{
if (fileStream == null)
{
Expand All @@ -142,14 +145,14 @@ public async Task<Completion> AttachFileAndAskQuestionAsync(Stream fileStream, s
{
if (string.IsNullOrWhiteSpace(sessionId))
{
if (string.IsNullOrWhiteSpace(sessionName))
if (sessionProperties == null)
{
throw new ArgumentException(
"The completion request must contain a sessionName if no sessionId is provided. " +
"The completion request must contain a session name if no session Id is provided. " +
"A new session will be created with the provided session name.");
}

sessionId = await CreateChatSessionAsync(sessionName);
sessionId = await CreateChatSessionAsync(sessionProperties);
}

var orchestrationRequest = new CompletionRequest
Expand Down
12 changes: 6 additions & 6 deletions src/dotnet/CoreClient/Interfaces/ICoreClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public interface ICoreClient
/// <summary>
/// Creates a new chat session with the specified name.
/// </summary>
/// <param name="sessionName">The chat session name.</param>
/// <param name="sessionProperties">The session properties.</param>
/// <returns>The new chat session ID.</returns>
Task<string> CreateChatSessionAsync(string sessionName);
Task<string> CreateChatSessionAsync(SessionProperties sessionProperties);

/// <summary>
/// Runs a single completion request with an agent using the Core API and a chat session.
Expand All @@ -25,12 +25,12 @@ public interface ICoreClient
/// </summary>
/// <param name="sessionId">The ID of an existing session. If null or empty, a new session
/// is created first.</param>
/// <param name="sessionName">Renames the new chat session if not null or empty.</param>
/// <param name="sessionProperties">Optional session priperties.</param>
/// <param name="userPrompt">The user prompt to send to the agent.</param>
/// <param name="agentName">The name of the FoundationaLLM agent that will handle the
/// completion request.</param>
/// <returns>A completion from the designated FoundationaLLM agent.</returns>
Task<Completion> GetCompletionWithSessionAsync(string? sessionId, string? sessionName,
Task<Completion> GetCompletionWithSessionAsync(string? sessionId, SessionProperties? sessionProperties,
string userPrompt, string agentName);

/// <summary>
Expand Down Expand Up @@ -83,11 +83,11 @@ Task<Completion> GetCompletionWithSessionAsync(string? sessionId, string? sessio
/// false, no session is created and the sessionless orchestration flow is used.</param>
/// <param name="sessionId">The ID of an existing session. If null or empty, a new session
/// is created first.</param>
/// <param name="sessionName">Renames the new chat session if not null or empty.</param>
/// <param name="sessionProperties">Optional session properties.</param>
/// <returns>A completion from the designated FoundationaLLM agent.</returns>
/// <returns>A completion from the designated FoundationaLLM agent.</returns>
Task<Completion> AttachFileAndAskQuestionAsync(Stream fileStream, string fileName, string contentType,
string agentName, string question, bool useSession, string? sessionId, string? sessionName);
string agentName, string question, bool useSession, string? sessionId, SessionProperties? sessionProperties);

/// <summary>
/// Returns the chat messages related to an existing session.
Expand Down
8 changes: 4 additions & 4 deletions src/dotnet/CoreClient/Interfaces/ISessionRESTClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ public interface ISessionRESTClient
/// <summary>
/// Creates a new session with the specified name.
/// </summary>
/// <param name="sessionName">The name for the chat session.</param>
/// <param name="sessionProperties">The session properties.</param>
/// <returns>Returns the new Session ID.</returns>
Task<string> CreateSessionAsync(string sessionName);
Task<string> CreateSessionAsync(SessionProperties sessionProperties);

/// <summary>
/// Renames a chat session.
/// </summary>
/// <param name="sessionId">The chat session ID.</param>
/// <param name="sessionName">The new session name.</param>
/// <param name="sessionProperties">The session properties.</param>
/// <returns></returns>
Task<string> RenameChatSession(string sessionId, string sessionName);
Task<string> RenameChatSession(string sessionId, SessionProperties sessionProperties);

/// <summary>
/// Gets a completion prompt by session ID and completion prompt ID.
Expand Down
28 changes: 15 additions & 13 deletions tests/dotnet/Core.Client.Tests/CoreClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ public CoreClientTests()
public async Task CreateChatSessionAsync_WithName_CreatesAndRenamesSession()
{
// Arrange
var sessionName = "TestSession";
var sessionProperties = new SessionProperties() { SessionName = "TestSession" };
var sessionId = "session-id";
_coreRestClient.Sessions.CreateSessionAsync(sessionName).Returns(Task.FromResult(sessionId));
_coreRestClient.Sessions.CreateSessionAsync(sessionProperties).Returns(Task.FromResult(sessionId));

// Act
var result = await _coreClient.CreateChatSessionAsync(sessionName);
var result = await _coreClient.CreateChatSessionAsync(sessionProperties);

// Assert
Assert.Equal(sessionId, result);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionName);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionProperties);
}

[Fact]
Expand All @@ -42,18 +42,18 @@ public async Task GetCompletionWithSessionAsync_WithNewSession_CreatesSessionAnd
// Arrange
var userPrompt = "Hello, World!";
var agentName = "TestAgent";
var sessionName = "TestSession";
var sessionProperties = new SessionProperties() { SessionName = "TestSession" };
var sessionId = "new-session-id";
var completion = new Completion();
_coreRestClient.Sessions.CreateSessionAsync(sessionName).Returns(Task.FromResult(sessionId));
_coreRestClient.Sessions.CreateSessionAsync(sessionProperties).Returns(Task.FromResult(sessionId));
_coreRestClient.Completions.GetChatCompletionAsync(Arg.Any<CompletionRequest>()).Returns(Task.FromResult(completion));

// Act
var result = await _coreClient.GetCompletionWithSessionAsync(null, sessionName, userPrompt, agentName);
var result = await _coreClient.GetCompletionWithSessionAsync(null, sessionProperties, userPrompt, agentName);

// Assert
Assert.Equal(completion, result);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionName);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionProperties);
await _coreRestClient.Completions.GetChatCompletionAsync(Arg.Is<CompletionRequest>(
r => r.SessionId == sessionId && r.AgentName == agentName && r.UserPrompt == userPrompt));
}
Expand Down Expand Up @@ -100,21 +100,21 @@ public async Task AttachFileAndAskQuestionAsync_UsesSession_UploadsFileAndSendsS
var contentType = "text/plain";
var agentName = "TestAgent";
var question = "What is this file about?";
var sessionName = "TestSession";
var sessionProperties = new SessionProperties() { SessionName = "TestSession" };
var sessionId = "session-id";
var objectId = "object-id";
var completion = new Completion();
_coreRestClient.Attachments.UploadAttachmentAsync(fileStream, fileName, contentType).Returns(Task.FromResult(objectId));
_coreRestClient.Sessions.CreateSessionAsync(sessionName).Returns(Task.FromResult(sessionId));
_coreRestClient.Sessions.CreateSessionAsync(sessionProperties).Returns(Task.FromResult(sessionId));
_coreRestClient.Completions.GetChatCompletionAsync(Arg.Any<CompletionRequest>()).Returns(Task.FromResult(completion));

// Act
var result = await _coreClient.AttachFileAndAskQuestionAsync(fileStream, fileName, contentType, agentName, question, true, null, sessionName);
var result = await _coreClient.AttachFileAndAskQuestionAsync(fileStream, fileName, contentType, agentName, question, true, null, sessionProperties);

// Assert
Assert.Equal(completion, result);
await _coreRestClient.Attachments.Received(1).UploadAttachmentAsync(fileStream, fileName, contentType);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionName);
await _coreRestClient.Sessions.Received(1).CreateSessionAsync(sessionProperties);
await _coreRestClient.Completions.GetChatCompletionAsync(Arg.Is<CompletionRequest>(
r => r.AgentName == agentName && r.SessionId == sessionId && r.UserPrompt == question && r.Attachments.Contains(objectId)));
}
Expand All @@ -124,7 +124,9 @@ public async Task AttachFileAndAskQuestionAsync_ThrowsException_WhenFileStreamIs
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ArgumentNullException>(() =>
_coreClient.AttachFileAndAskQuestionAsync(null!, "file.txt", "text/plain", "agent", "question", true, "session-id", "session-name"));
_coreClient.AttachFileAndAskQuestionAsync(
null!, "file.txt", "text/plain", "agent", "question", true, "session-id",
new SessionProperties() { SessionName = "session-name" }));
}

[Fact]
Expand Down
Loading

0 comments on commit 13798f4

Please sign in to comment.