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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.ComponentModel;

namespace Devlooped.Extensions.AI;
namespace Devlooped.Extensions.AI.OpenAI;

/// <summary>
/// Effort a reasoning model should apply when generating a response.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Devlooped.Extensions.AI;
namespace Devlooped.Extensions.AI.OpenAI;

/// <summary>
/// Verbosity determines how many output tokens are generated for models that support it, such as GPT-5.
Expand Down
104 changes: 104 additions & 0 deletions src/Extensions/OpenAI/WebSearchTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using Microsoft.Extensions.AI;
using OpenAI.Responses;
using WebSearch = OpenAI.Responses.WebSearchTool;

namespace Devlooped.Extensions.AI.OpenAI;

/// <summary>
/// Basic web search tool that can limit the search to a specific country.
/// </summary>
public class WebSearchTool : HostedWebSearchTool
{
readonly Dictionary<string, object?> additionalProperties = new();
string? country;
string? region;
string? city;
string? timeZone;
string[]? allowedDomains;

/// <summary>
/// Initializes a new instance of the <see cref="WebSearchTool"/> class with the specified country.
/// </summary>
/// <param name="country">ISO alpha-2 country code.</param>
public WebSearchTool(string? country = null) => Country = country;

/// <summary>
/// Sets the user's country for web search results, using the ISO alpha-2 code.
/// </summary>
public string? Country
{
get => country;
set
{
country = value;
UpdateUserLocation();
}
}

/// <summary>
/// Optional free text additional information about the region to be used in the search.
/// </summary>
public string? Region
{
get => region;
set
{
region = value;
UpdateUserLocation();
}
}

/// <summary>
/// Optional free text additional information about the city to be used in the search.
/// </summary>
public string? City
{
get => city;
set
{
city = value;
UpdateUserLocation();
}
}

/// <summary>
/// Optional IANA timezone name to be used in the search.
/// </summary>
public string? TimeZone
{
get => timeZone;
set
{
timeZone = value;
UpdateUserLocation();
}
}

/// <summary>
/// Optional list of allowed domains to restrict the web search.
/// </summary>
public string[]? AllowedDomains
{
get => allowedDomains;
set
{
allowedDomains = value;
if (value is { Length: > 0 })
additionalProperties[nameof(WebSearch.Filters)] = new WebSearchToolFilters { AllowedDomains = value };
else
additionalProperties.Remove(nameof(WebSearch.Filters));
}
}

/// <inheritdoc/>
public override IReadOnlyDictionary<string, object?> AdditionalProperties => additionalProperties;

void UpdateUserLocation()
{
if (country != null || region != null || city != null || timeZone != null)
additionalProperties[nameof(WebSearch.UserLocation)] =
WebSearchToolLocation.CreateApproximateLocation(country, region, city, timeZone);
else
additionalProperties.Remove(nameof(WebSearch.UserLocation));
}
}
67 changes: 0 additions & 67 deletions src/Extensions/OpenAI/WebSearchToolExtensions.cs

This file was deleted.

45 changes: 0 additions & 45 deletions src/Extensions/WebSearchTool.cs

This file was deleted.

3 changes: 1 addition & 2 deletions src/Tests/OpenAITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,10 @@ public async Task WebSearchCountryHighContext()

var options = new ChatOptions
{
Tools = [new WebSearchTool("AR")
Tools = [new Devlooped.Extensions.AI.OpenAI.WebSearchTool("AR")
{
Region = "Bariloche",
TimeZone = "America/Argentina/Buenos_Aires",
ContextSize = WebSearchToolContextSize.High
}]
};

Expand Down