Skip to content

Commit

Permalink
Beta4 release of azure-ai-projects SDK (#38873)
Browse files Browse the repository at this point in the history
  • Loading branch information
dargilco authored Dec 20, 2024
1 parent ab0ed5e commit 980fe42
Show file tree
Hide file tree
Showing 79 changed files with 1,590 additions and 597 deletions.
2 changes: 2 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,8 @@
{
"filename": "sdk/ai/azure-ai-projects/**",
"words": [
"ENTRAID",
"entraid",
"aiservices",
"OTEL",
"GENAI",
Expand Down
13 changes: 13 additions & 0 deletions sdk/ai/azure-ai-projects/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Release History

## 1.0.0b4 (2024-12-20)

### Bugs Fixed

* Fix for Agent streaming issue (see [GitHub issue 38918](https://github.com/Azure/azure-sdk-for-python/issues/38918))
* Fix for Agent async function `send_email_async` is not called (see [GitHub issue 38898](https://github.com/Azure/azure-sdk-for-python/issues/38898))
* Fix for Agent streaming with event handler fails with "AttributeError: 'MyEventHandler' object has no attribute 'buffer'" (see [GitHub issue 38897](https://github.com/Azure/azure-sdk-for-python/issues/38897))

### Features Added

* Add optional input argument `connection_name` to methods `.inference.get_chat_completions_client`,
`.inference.get_embeddings_client` and `.inference.get_azure_openai_client`.

## 1.0.0b3 (2024-12-13)

### Features Added
Expand Down
101 changes: 101 additions & 0 deletions sdk/ai/azure-ai-projects/FunctionTool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# FunctionTool Specifications

FunctionTool is the utility allowing developers to provide functions within their code and invoke during streaming or running.

## Example of Function

Here is an example of a function:
```python
def fetch_weather(location: str) -> str:
"""
Fetches the weather information for the specified location.
:param location (str): The location to fetch weather for.
:return: Weather information as a JSON string.
:rtype: str
"""
# In a real-world scenario, you'd integrate with a weather API.
mock_weather_data = {"New York": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"}
weather = mock_weather_data.get(location, "Weather data not available for this location.")
weather_json = json.dumps({"weather": weather})
return weather_json
```

Here is an example to attach this function definition to create_agent

```python
functions = FunctionTool({fetch_weather})

agent = project_client.agents.create_agent(
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
tools=functions.definitions,
)
```

To verify that the SDK parsed the docstring properly, you can print the definition:

```python
[print(json.dumps(tool.as_dict(), indent=4)) for tool in functions.definitions]
```

Alternatively user can check the tools property in newly created agent:

```python
[print(json.dumps(tool.as_dict(), indent=4)) for tool in agent.tools if tool.type == "function"]
```

The terminal will display the definition as below:

```json
[
{
"type": "function",
"function": {
"name": "fetch_weather",
"description": "Fetches the weather information for the specified location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to fetch weather for."
}
},
"required": [
"location"
]
}
}
}
]
```

## Requirements for FunctionTool

To ensure `FunctionTool` operates correctly and generates accurate function definitions that agents can reliably call, adhere to the following standards:

1. **Type Annotations**
- All function parameters and return types should be explicitly type-annotated using Python's type hinting.

2. **Structured Docstrings**
- Utilize a consistent docstring format similar to the example above (see also related agent samples in this repository).
- Include clear descriptions for each function and parameter.

3. **Supported Types**

`FunctionTool` maps common Python types to their JSON Schema equivalents, ensuring accurate representation without complex type details:

- **Strings and Numbers**
- `str``string`
- `int``integer`
- `float``number`
- `bool``boolean`

- **Collections**
- `list``array`
- `dict``object`

- **Nullable Types**
- `Optional[type]` includes `null`
58 changes: 43 additions & 15 deletions sdk/ai/azure-ai-projects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ Here is an example of how to create an Agent:

```python
agent = project_client.agents.create_agent(
model="gpt-4o",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are helpful assistant",
)
Expand All @@ -275,7 +275,10 @@ toolset.add(functions)
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
toolset=toolset,
)
```

Expand All @@ -291,7 +294,7 @@ file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id])

# Notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file
agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are helpful assistant",
tools=file_search_tool.definitions,
Expand Down Expand Up @@ -320,7 +323,7 @@ print(f"Created vector store, vector store ID: {vector_store.id}")
file_search = FileSearchTool(vector_store_ids=[vector_store.id])

agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="Hello, you are helpful assistant and can search information from uploaded files",
tools=file_search.definitions,
Expand Down Expand Up @@ -350,7 +353,7 @@ file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id])

# Notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file
agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are helpful assistant",
tools=file_search_tool.definitions,
Expand All @@ -360,7 +363,7 @@ agent = project_client.agents.create_agent(

<!-- END SNIPPET -->

We also can attach files to the existing vector vector store. In the code snippet below, we first create an empty vector store and add file to it.
We also can attach files to the existing vector store. In the code snippet below, we first create an empty vector store and add file to it.

<!-- SNIPPET:sample_agents_vector_store_batch_enterprise_file_search.attach_files_to_store -->

Expand Down Expand Up @@ -398,7 +401,7 @@ code_interpreter = CodeInterpreterTool(file_ids=[file.id])

# Create agent with code interpreter tool and tools_resources
agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are helpful assistant",
tools=code_interpreter.definitions,
Expand Down Expand Up @@ -428,7 +431,7 @@ bing = BingGroundingTool(connection_id=conn_id)
# Create agent with the bing tool and process assistant run
with project_client:
agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
tools=bing.definitions,
Expand Down Expand Up @@ -462,7 +465,7 @@ ai_search = AzureAISearchTool(index_connection_id=conn_id, index_name="myindexna
# Create agent with AI search tool and process assistant run
with project_client:
agent = project_client.agents.create_agent(
model="gpt-4o-mini",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
tools=ai_search.definitions,
Expand All @@ -482,6 +485,8 @@ You can enhance your Agents by defining callback functions as function tools. Th

For more details about calling functions by code, refer to [`sample_agents_stream_eventhandler_with_functions.py`](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/agents/sample_agents_stream_eventhandler_with_functions.py) and [`sample_agents_functions.py`](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/agents/sample_agents_functions.py).

For more details about requirements and specification of functions, refer to [Function Tool Specifications](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/FunctionTool.md)

Here is an example to use [user functions](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/agents/user_functions.py) in `toolset`:
<!-- SNIPPET:sample_agents_stream_eventhandler_with_toolset.create_agent_with_function_tool -->

Expand All @@ -491,7 +496,10 @@ toolset = ToolSet()
toolset.add(functions)

agent = project_client.agents.create_agent(
model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
toolset=toolset,
)
```

Expand All @@ -512,7 +520,7 @@ toolset = AsyncToolSet()
toolset.add(functions)

agent = await project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
toolset=toolset,
Expand Down Expand Up @@ -583,7 +591,10 @@ openapi = OpenApiTool(
# Create agent with OpenApi tool and process assistant run
with project_client:
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-assistant", instructions="You are a helpful assistant", tools=openapi.definitions
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are a helpful assistant",
tools=openapi.definitions,
)
```

Expand Down Expand Up @@ -618,7 +629,7 @@ print(f"Created vector store, vector store ID: {vector_store.id}")
file_search = FileSearchTool(vector_store_ids=[vector_store.id])

agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="Hello, you are helpful assistant and can search information from uploaded files",
tools=file_search.definitions,
Expand Down Expand Up @@ -661,7 +672,7 @@ message = project_client.agents.create_message(

#### Create Message with Code Interpreter Attachment

To attach a file to a message for data analysis, you use `MessageAttachment` and `CodeInterpreterTool`. You must pass `CodeInterpreterTool` as `tools` or `toolset` in `create_agent` call or the file attachment cannot be opened for code interpreter.
To attach a file to a message for data analysis, use `MessageAttachment` and `CodeInterpreterTool` classes. You must pass `CodeInterpreterTool` as `tools` or `toolset` in `create_agent` call or the file attachment cannot be opened for code interpreter.

Here is an example to pass `CodeInterpreterTool` as tool:

Expand All @@ -671,7 +682,7 @@ Here is an example to pass `CodeInterpreterTool` as tool:
# Notice that CodeInterpreter must be enabled in the agent creation,
# otherwise the agent will not be able to see the file attachment for code interpretation
agent = project_client.agents.create_agent(
model="gpt-4-1106-preview",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-assistant",
instructions="You are helpful assistant",
tools=CodeInterpreterTool().definitions,
Expand All @@ -695,6 +706,23 @@ message = project_client.agents.create_message(

<!-- END SNIPPET -->

Azure blob storage can be used as a message attachment. In this case, use `VectorStoreDataSource` as a data source:

<!-- SNIPPET:sample_agents_code_interpreter_attachment_enterprise_search.upload_file_and_create_message_with_code_interpreter -->

```python
# We will upload the local file to Azure and will use it for vector store creation.
_, asset_uri = project_client.upload_file("./product_info_1.md")
ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET)

# Create a message with the attachment
attachment = MessageAttachment(data_source=ds, tools=code_interpreter.definitions)
message = project_client.agents.create_message(
thread_id=thread.id, role="user", content="What does the attachment say?", attachments=[attachment]
)
```

<!-- END SNIPPET -->

#### Create Run, Run_and_Process, or Stream

Expand Down
2 changes: 1 addition & 1 deletion sdk/ai/azure-ai-projects/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/ai/azure-ai-projects",
"Tag": "python/ai/azure-ai-projects_12144a7ce2"
"Tag": "python/ai/azure-ai-projects_e85eaccb70"
}
2 changes: 1 addition & 1 deletion sdk/ai/azure-ai-projects/azure/ai/projects/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

VERSION = "1.0.0b3"
VERSION = "1.0.0b4"
Loading

0 comments on commit 980fe42

Please sign in to comment.