Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion java-library/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-ai-openai</artifactId>
<version>1.0.0-beta.10</version>
<version>1.0.0-beta.11</version>
<scope>compile</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class AssistantCreateRequest {
private String id;
private String instructions = "You are a helpful assistant.";
private String chatStorageConnectionSetting;
private String collectionName = "SampleChatState";
private String collectionName = "ChatState";

public AssistantCreateRequest(String id) {
this.id = id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
* <p>
* Assistant post input attribute which is used to update the assistant.
Expand All @@ -26,18 +25,34 @@
@CustomBinding(direction = "in", name = "", type = "assistantPost")
public @interface AssistantPost {

/**
* The default storage account setting for the table storage account.
* This constant is used to specify the connection string for the table storage
* account
* where chat data will be stored.
*/
String DEFAULT_CHATSTORAGE = "AzureWebJobsStorage";

/**
* The default collection name for the table storage account.
* This constant is used to specify the collection name for the table storage
* account
* where chat data will be stored.
*/
String DEFAULT_COLLECTION = "ChatState";

/**
* The variable name used in function.json.
*
* @return The variable name used in function.json.
*/
*/
String name();

/**
* The ID of the Assistant to query.
*
* @return The ID of the Assistant to query.
*/
*/
String id();

/**
Expand All @@ -48,12 +63,27 @@
*/
String model();


/**
* The user message that user has entered for assistant to respond to.
*
* @return The user message that user has entered for assistant to respond to.
*/
*/
String userMessage();

/**
* The configuration section name for the table settings for assistant chat
* storage.
*
* @return The configuration section name for the table settings for assistant
* chat storage. By default, it returns {@code DEFAULT_CHATSTORAGE}.
*/
String chatStorageConnectionSetting() default DEFAULT_CHATSTORAGE;

/**
* The table collection name for assistant chat storage.
*
* @return the table collection name for assistant chat storage.By default, it
* returns {@code DEFAULT_COLLECTION}.
*/
String collectionName() default DEFAULT_COLLECTION;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* <p>
* Assistant query input attribute which is used query the Assistant to get current state.
* Assistant query input attribute which is used query the Assistant to get
* current state.
* </p>
*
* @since 1.0.0
Expand All @@ -25,13 +26,29 @@
@CustomBinding(direction = "in", name = "", type = "assistantQuery")
public @interface AssistantQuery {

/**
* The default storage account setting for the table storage account.
* This constant is used to specify the connection string for the table storage
* account
* where chat data will be stored.
*/
String DEFAULT_CHATSTORAGE = "AzureWebJobsStorage";

/**
* The default collection name for the table storage account.
* This constant is used to specify the collection name for the table storage
* account
* where chat data will be stored.
*/
String DEFAULT_COLLECTION = "ChatState";

/**
* The variable name used in function.json.
*
* @return The variable name used in function.json.
*/
String name();

/**
* The ID of the Assistant to query.
*
Expand All @@ -41,10 +58,27 @@

/**
* The timestamp of the earliest message in the chat history to fetch.
* The timestamp should be in ISO 8601 format - for example, 2023-08-01T00:00:00Z.
* The timestamp should be in ISO 8601 format - for example,
* 2023-08-01T00:00:00Z.
*
* @return The timestamp of the earliest message in the chat history to fetch.
*/
String timestampUtc();

}

/**
* The configuration section name for the table settings for assistant chat
* storage.
*
* @return The configuration section name for the table settings for assistant
* chat storage. By default, it returns {@code DEFAULT_CHATSTORAGE}.
*/
String chatStorageConnectionSetting() default DEFAULT_CHATSTORAGE;

/**
* The table collection name for assistant chat storage.
*
* @return the table collection name for assistant chat storage.By default, it
* returns {@code DEFAULT_COLLECTION}.
*/
String collectionName() default DEFAULT_COLLECTION;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class EmbeddingsContext {

private EmbeddingsOptions request;
private Embeddings response;
private int count;
private int count = 0;

public EmbeddingsOptions getRequest() {
return request;
Expand Down
49 changes: 18 additions & 31 deletions samples/assistant/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,6 @@ This OpenAI extension internally uses the [function calling](https://platform.op
* 0301 is the default and oldest model version for gpt-3.5 but it doesn't support this feature.
* Model version 1106 has known issue with duplicate function calls in the OpenAI extension, check the repo issues for progress as the extension team works on it.

### Chat Storage Configuration

If you are using a different table storage than `AzureWebJobsStorage` for chat storage, follow these steps:

1. **Managed Identity - Assign Permissions**:
* Assign the user or function app's managed identity the role of `Storage Table Data Contributor`.

1. **Configure Table Service URI**:
* Set the `tableServiceUri` in the configuration as follows:

```json
"<CONNECTION_NAME_PREFIX>__tableServiceUri": "tableServiceUri"
```

* Replace `CONNECTION_NAME_PREFIX` with the appropriate prefix.

1. **Update Function Code**:
* Supply the `ConnectionNamePrefix` to `ChatStorageConnectionSetting` in the function code. This will replace the default value of `AzureWebJobsStorage`.

For additional details on using identity-based connections, refer to the [Azure Functions reference documentation](https://learn.microsoft.com/azure/azure-functions/functions-reference?#common-properties-for-identity-based-connections).

## Defining skills

You can define a skill by creating a function that uses the `AssistantSkillTrigger` binding. The following example shows a skill that adds a todo item to a database:
Expand Down Expand Up @@ -205,18 +184,26 @@ Additionally, if you want to run the sample with Cosmos DB, then you must also d
* Install the [Azure Cosmos DB Emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator), or get a connection string to a real Azure Cosmos DB resource.
* Update the `CosmosDbConnectionString` setting in the `local.settings.json` file and configure it with the connection string to your Cosmos DB resource (local or Azure).

Also note that the storage of chat history is done via table storage. You may configure the `host.json` file within the project to be as follows:
### Chat Storage Configuration

```json
"extensions": {
"openai": {
"storageConnectionName": "AzureWebJobsStorage",
"collectionName": "SampleChatState"
}
}
```
If you are using a different table storage than `AzureWebJobsStorage` for chat storage, follow these steps:

1. **Managed Identity - Assign Permissions**:
* Assign the user or function app's managed identity the role of `Storage Table Data Contributor`.

1. **Configure Table Service URI**:
* Set the `tableServiceUri` in the configuration as follows:

`StorageConnectionName` is the name of connection string of a storage account and `CollectionName` is the name of the table that would hold the chat state and messages.
```json
"<CONNECTION_NAME_PREFIX>__tableServiceUri": "tableServiceUri"
```

* Replace `CONNECTION_NAME_PREFIX` with the appropriate prefix.

1. **Update Function Code**:
* Supply the `ConnectionNamePrefix` to `ChatStorageConnectionSetting` in the function code. This will replace the default value of `AzureWebJobsStorage`.

For additional details on using identity-based connections, refer to the [Azure Functions reference documentation](https://learn.microsoft.com/azure/azure-functions/functions-reference?#common-properties-for-identity-based-connections).

## Running the sample

Expand Down
11 changes: 7 additions & 4 deletions samples/assistant/csharp-ooproc/AssistantApis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace AssistantSample;
/// </summary>
static class AssistantApis
{
const string DefaultChatStorageConnectionSetting = "AzureWebJobsStorage";
const string DefaultCollectionName = "ChatState";

/// <summary>
/// HTTP PUT function that creates a new assistant chat bot with the specified ID.
/// </summary>
Expand All @@ -37,8 +40,8 @@ public static async Task<CreateChatBotOutput> CreateAssistant(
HttpResponse = new ObjectResult(new { assistantId }) { StatusCode = 202 },
ChatBotCreateRequest = new AssistantCreateRequest(assistantId, instructions)
{
ChatStorageConnectionSetting = "AzureWebJobsStorage",
CollectionName = "SampleChatState",
ChatStorageConnectionSetting = DefaultChatStorageConnectionSetting,
CollectionName = DefaultCollectionName,
},
};
}
Expand All @@ -59,7 +62,7 @@ public class CreateChatBotOutput
public static async Task<IActionResult> PostUserQuery(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "assistants/{assistantId}")] HttpRequestData req,
string assistantId,
[AssistantPostInput("{assistantId}", "{Query.message}", Model = "%CHAT_MODEL_DEPLOYMENT_NAME%")] AssistantState state)
[AssistantPostInput("{assistantId}", "{Query.message}", Model = "%CHAT_MODEL_DEPLOYMENT_NAME%", ChatStorageConnectionSetting = DefaultChatStorageConnectionSetting, CollectionName = DefaultCollectionName)] AssistantState state)
{
return new OkObjectResult(state.RecentMessages.LastOrDefault()?.Content ?? "No response returned.");
}
Expand All @@ -71,7 +74,7 @@ public static async Task<IActionResult> PostUserQuery(
public static async Task<IActionResult> GetChatState(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "assistants/{assistantId}")] HttpRequestData req,
string assistantId,
[AssistantQueryInput("{assistantId}", TimestampUtc = "{Query.timestampUTC}")] AssistantState state)
[AssistantQueryInput("{assistantId}", TimestampUtc = "{Query.timestampUTC}", ChatStorageConnectionSetting = DefaultChatStorageConnectionSetting, CollectionName = DefaultCollectionName)] AssistantState state)
{
return new OkObjectResult(state);
}
Expand Down
13 changes: 3 additions & 10 deletions samples/assistant/csharp-ooproc/TodoManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,15 @@ class CosmosDbTodoManager : ITodoManager

public CosmosDbTodoManager(ILoggerFactory loggerFactory, CosmosClient cosmosClient)
{
if (loggerFactory is null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}

if (cosmosClient is null)
{
throw new ArgumentNullException(nameof(cosmosClient));
}
ArgumentNullException.ThrowIfNull(loggerFactory, nameof(loggerFactory));
ArgumentNullException.ThrowIfNull(cosmosClient, nameof(cosmosClient));

string? CosmosDatabaseName = Environment.GetEnvironmentVariable("CosmosDatabaseName");
string? CosmosContainerName = Environment.GetEnvironmentVariable("CosmosContainerName");

if (string.IsNullOrEmpty(CosmosDatabaseName) || string.IsNullOrEmpty(CosmosContainerName))
{
throw new ArgumentNullException("CosmosDatabaseName and CosmosContainerName must be set as environment variables or in local.settings.json");
throw new InvalidOperationException("CosmosDatabaseName and CosmosContainerName must be set as environment variables or in local.settings.json");
}

this.logger = loggerFactory.CreateLogger<CosmosDbTodoManager>();
Expand Down
15 changes: 11 additions & 4 deletions samples/assistant/javascript/src/functions/assistantApis.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

const { app, input, output } = require("@azure/functions");

const CHAT_STORAGE_CONNECTION_SETTING = "AzureWebJobsStorage";
const COLLECTION_NAME = "ChatState";

const chatBotCreateOutput = output.generic({
type: 'assistantCreate'
})
Expand All @@ -21,8 +24,8 @@ app.http('CreateAssistant', {
const createRequest = {
id: assistantId,
instructions: instructions,
chatStorageConnectionSetting: "AzureWebJobsStorage",
collectionName: "SampleChatState"
chatStorageConnectionSetting: CHAT_STORAGE_CONNECTION_SETTING,
collectionName: COLLECTION_NAME
}
context.extraOutputs.set(chatBotCreateOutput, createRequest)
return { status: 202, jsonBody: { assistantId: assistantId } }
Expand All @@ -34,7 +37,9 @@ const assistantPostInput = input.generic({
type: 'assistantPost',
id: '{assistantId}',
model: '%CHAT_MODEL_DEPLOYMENT_NAME%',
userMessage: '{Query.message}'
userMessage: '{Query.message}',
chatStorageConnectionSetting: CHAT_STORAGE_CONNECTION_SETTING,
collectionName: COLLECTION_NAME
})
app.http('PostUserResponse', {
methods: ['POST'],
Expand All @@ -58,7 +63,9 @@ app.http('PostUserResponse', {
const chatBotQueryInput = input.generic({
type: 'assistantQuery',
id: '{assistantId}',
timestampUtc: '{Query.timestampUTC}'
timestampUtc: '{Query.timestampUTC}',
chatStorageConnectionSetting: CHAT_STORAGE_CONNECTION_SETTING,
collectionName: COLLECTION_NAME
})
app.http('GetChatState', {
methods: ['GET'],
Expand Down
6 changes: 3 additions & 3 deletions samples/assistant/powershell/CreateAssistant/run.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ $instructions += "\nAsk for clarification if a user request is ambiguous."

$create_request = @{
"id" = $assistantId
"instructions" = $instructions,
"chatStorageConnectionSetting" = "AzureWebJobsStorage",
"collectionName" = "SampleChatState"
"instructions" = $instructions
"chatStorageConnectionSetting" = "AzureWebJobsStorage"
"collectionName" = "ChatState"
}

Push-OutputBinding -Name Requests -Value (ConvertTo-Json $create_request)
Expand Down
4 changes: 3 additions & 1 deletion samples/assistant/powershell/GetChatState/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"direction": "in",
"dataType": "string",
"id": "{assistantId}",
"timestampUtc": "{Query.timestampUTC}"
"timestampUtc": "{Query.timestampUTC}",
"chatStorageConnectionSetting": "AzureWebJobsStorage",
"collectionName": "ChatState"
}
]
}
4 changes: 3 additions & 1 deletion samples/assistant/powershell/PostUserQuery/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"dataType": "string",
"id": "{assistantId}",
"userMessage": "{Query.message}",
"model": "%CHAT_MODEL_DEPLOYMENT_NAME%"
"model": "%CHAT_MODEL_DEPLOYMENT_NAME%",
"chatStorageConnectionSetting": "AzureWebJobsStorage",
"collectionName": "ChatState"
}
]
}
2 changes: 1 addition & 1 deletion samples/assistant/python/assistant_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def create_assistant(req: func.HttpRequest, requests: func.Out[str]) -> func.Htt
"id": assistantId,
"instructions": instructions,
"chatStorageConnectionSection": "AzureWebJobsStorage",
"collectionName": "SampleChatState"
"collectionName": "ChatState"
}
requests.set(json.dumps(create_request))
response_json = {"assistantId": assistantId}
Expand Down
Loading