Skip to content

Commit

Permalink
Merge pull request #1648 from solliancenet/jdh-transform-content-item…
Browse files Browse the repository at this point in the history
…s-check-081

(0.8.1) API stability and status reporting improvements
  • Loading branch information
ciprianjichici authored Aug 30, 2024
2 parents 87930f6 + b677607 commit 0892d4f
Show file tree
Hide file tree
Showing 33 changed files with 383 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
"Type": "api-endpoint",
"Deleted": false
},
{
"Name": "CoreAPI",
"Filename": "/FoundationaLLM.Configuration/CoreAPI.json",
"Type": "api-endpoint",
"Deleted": false
},
{
"Name": "GatekeeperAPI",
"Filename": "/FoundationaLLM.Configuration/GatekeeperAPI.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"type": "api-endpoint",
"name": "CoreAPI",
"object_id": "/instances/${env:FOUNDATIONALLM_INSTANCE_ID}/providers/FoundationaLLM.Configuration/apiEndpointConfigurations/CoreAPI",
"display_name": null,
"description": null,
"cost_center": null,
"category": "General",
"authentication_type": "APIKey",
"authentication_parameters":{
"api_key_configuration_name": "",
"api_key_header_name": ""
},
"url": "",
"status_url": "",
"url_exceptions": [],
"timeout_seconds": 3500,
"retry_strategy_name": "ExponentialBackoff",
"created_on": "0001-01-01T00:00:00+00:00",
"updated_on": "0001-01-01T00:00:00+00:00",
"created_by": "SYSTEM",
"updated_by": null,
"deleted": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_GATEKEEPER_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_GATEKEEPER_API_ENDPOINT_URL}/instances/${env:FOUNDATIONALLM_INSTANCE_ID}/status",
"url_exceptions": [],
"timeout_seconds": 2700,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_GATEWAY_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_GATEWAY_API_ENDPOINT_URL}/status",
"url_exceptions": [],
"timeout_seconds": 1200,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_GATEWAY_ADAPTER_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_GATEWAY_ADAPTER_API_ENDPOINT_URL}/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_LANGCHAIN_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_LANGCHAIN_API_ENDPOINT_URL}/status",
"url_exceptions": [],
"timeout_seconds": 1800,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_ORCHESTRATION_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_ORCHESTRATION_API_ENDPOINT_URL}/instances/${env:FOUNDATIONALLM_INSTANCE_ID}/status",
"url_exceptions": [],
"timeout_seconds": 2400,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_SEMANTIC_KERNEL_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_SEMANTIC_KERNEL_API_ENDPOINT_URL}/instances/${env:FOUNDATIONALLM_INSTANCE_ID}/status",
"url_exceptions": [],
"timeout_seconds": 1800,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_STATE_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_STATE_API_ENDPOINT_URL}/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "${env:SERVICE_VECTORIZATION_API_ENDPOINT_URL}",
"status_url": "${env:SERVICE_VECTORIZATION_API_ENDPOINT_URL}/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
1 change: 1 addition & 0 deletions deploy/standard/azd-hooks/utility/Generate-Config.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,AzureContentSafety.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,AzureContentSafety.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,AzureEventGrid.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,AzureEventGrid.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,AzureOpenAI.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,AzureOpenAI.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,CoreAPI.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,CoreAPI.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,GatekeeperAPI.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,GatekeeperAPI.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,GatekeeperIntegrationAPI.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,GatekeeperIntegrationAPI.json"
PopulateTemplate $tokens "..,data,resource-provider,FoundationaLLM.Configuration,GatewayAdapterAPI.template.json" "..,..,common,data,resource-provider,FoundationaLLM.Configuration,GatewayAdapterAPI.json"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"type": "api-endpoint",
"name": "CoreAPI",
"object_id": "/instances/{{instanceId}}/providers/FoundationaLLM.Configuration/apiEndpointConfigurations/CoreAPI",
"display_name": null,
"description": null,
"cost_center": null,
"category": "General",
"authentication_type": "APIKey",
"authentication_parameters":{
"api_key_configuration_name": "",
"api_key_header_name": ""
},
"url": "",
"status_url": "",
"url_exceptions": [],
"timeout_seconds": 2700,
"retry_strategy_name": "ExponentialBackoff",
"created_on": "0001-01-01T00:00:00+00:00",
"updated_on": "0001-01-01T00:00:00+00:00",
"created_by": "SYSTEM",
"updated_by": null,
"deleted": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://gatekeeper-api/gatekeeper",
"status_url": "http://gatekeeper-api/gatekeeper/instances/{{instanceId}}/status",
"url_exceptions": [],
"timeout_seconds": 2700,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://gateway-api/gateway",
"status_url": "http://gateway-api/gateway/status",
"url_exceptions": [],
"timeout_seconds": 1200,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://gateway-adapter-api/gatewayadapter",
"status_url": "http://gateway-adapter-api/gatewayadapter/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://langchain-api/langchain",
"status_url": "http://langchain-api/langchain/status",
"url_exceptions": [],
"timeout_seconds": 1800,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://orchestration-api/orchestration",
"status_url": "http://orchestration-api/orchestration/instances/{{instanceId}}/status",
"url_exceptions": [],
"timeout_seconds": 2400,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://semantic-kernel-api/semantickernel",
"status_url": "http://semantic-kernel-api/semantickernel/instances/{{instanceId}}/status",
"url_exceptions": [],
"timeout_seconds": 1800,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://state-api/state",
"status_url": "http://state-api/state/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"api_key_header_name": "X-API-KEY"
},
"url": "http://vectorization-api/vectorization",
"status_url": "http://vectorization-api/vectorization/status",
"url_exceptions": [],
"timeout_seconds": 60,
"retry_strategy_name": "ExponentialBackoff",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public APIEndpointConfiguration() =>
[JsonPropertyName("url")]
public required string Url { get; set; }

/// <summary>
/// The status URL of the API endpoint, if available.
/// </summary>
[JsonPropertyName("status_url")]
public string? StatusUrl { get; set; }

/// <summary>
/// A list of URL exceptions.
/// </summary>
Expand Down Expand Up @@ -104,5 +110,11 @@ public class UrlException
/// </summary>
[JsonPropertyName("url")]
public required string Url { get; set; }

/// <summary>
/// Indicates whether the exception is enabled.
/// </summary>
[JsonPropertyName("enabled")]
public required bool Enabled { get; set; }
}
}
4 changes: 2 additions & 2 deletions src/dotnet/Common/Services/API/HttpClientFactoryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public async Task<T> CreateClient<T>(string clientName, UnifiedUserIdentity user
Dictionary<string, object> clientBuilderParameters = [];

clientBuilderParameters[HttpClientFactoryServiceKeyNames.Endpoint] =
endpointConfiguration.UrlExceptions.Where(x => x.UserPrincipalName == userIdentity.UPN).SingleOrDefault()?.Url
endpointConfiguration.UrlExceptions.SingleOrDefault(x => x.UserPrincipalName == userIdentity.UPN && x.Enabled)?.Url
?? endpointConfiguration.Url;
clientBuilderParameters[HttpClientFactoryServiceKeyNames.TimeoutSeconds] = endpointConfiguration.TimeoutSeconds;
clientBuilderParameters[HttpClientFactoryServiceKeyNames.AuthenticationType] = endpointConfiguration.AuthenticationType;
Expand Down Expand Up @@ -91,7 +91,7 @@ public async Task<HttpClient> CreateClient(APIEndpointConfiguration endpointConf
// Override the default URL if an exception is provided.
if (userIdentity != null)
{
var urlException = endpointConfiguration.UrlExceptions.Where(x => x.UserPrincipalName == userIdentity.UPN).SingleOrDefault();
var urlException = endpointConfiguration.UrlExceptions.SingleOrDefault(x => x.UserPrincipalName == userIdentity.UPN && x.Enabled);
if (urlException != null)
httpClient.BaseAddress = new Uri(urlException.Url);

Expand Down
35 changes: 33 additions & 2 deletions src/dotnet/Core/Services/CoreService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public partial class CoreService(
IOptions<CoreServiceSettings> settings,
ICallContext callContext,
IEnumerable<IResourceProviderService> resourceProviderServices,
IConfiguration configuration) : ICoreService
IConfiguration configuration,
IHttpClientFactoryService httpClientFactory) : ICoreService
{
private readonly ICosmosDbService _cosmosDbService = cosmosDbService;
private readonly IDownstreamAPIService _gatekeeperAPIService = downstreamAPIServices.Single(das => das.APIName == HttpClientNames.GatekeeperAPI);
Expand All @@ -65,7 +66,8 @@ public partial class CoreService(
private readonly ICallContext _callContext = callContext;
private readonly string _sessionType = brandingSettings.Value.KioskMode ? SessionTypes.KioskSession : SessionTypes.Session;
private readonly CoreServiceSettings _settings = settings.Value;
private readonly string _baseUrl = configuration[AppConfigurationKeys.FoundationaLLM_APIEndpoints_CoreAPI_Essentials_APIUrl]!;
private readonly IHttpClientFactoryService _httpClientFactory = httpClientFactory;
private readonly string _baseUrl = GetBaseUrl(configuration, httpClientFactory, callContext).GetAwaiter().GetResult();

private readonly IResourceProviderService _attachmentResourceProvider =
resourceProviderServices.Single(rps => rps.Name == ResourceProviderNames.FoundationaLLM_Attachment);
Expand Down Expand Up @@ -573,6 +575,35 @@ private CompletionRequest PrepareCompletionRequest(CompletionRequest request)
return request;
}

private static async Task<string> GetBaseUrl(
IConfiguration configuration,
IHttpClientFactoryService httpClientFactory,
ICallContext callContext)
{
var baseUrl = configuration[AppConfigurationKeys.FoundationaLLM_APIEndpoints_CoreAPI_Essentials_APIUrl]!;
try
{
var baseUrlOverride = await httpClientFactory.CreateClient<string?>(
HttpClientNames.CoreAPI,
callContext.CurrentUserIdentity!,
BuildClient);
if (!string.IsNullOrWhiteSpace(baseUrlOverride))
{
baseUrl = baseUrlOverride;
}
}
catch (Exception e)
{
Console.WriteLine(e);
// Ignore the exception since we should always fall back to the configured value.
}

return baseUrl;
}

private static string? BuildClient(Dictionary<string, object> parameters) =>
parameters[HttpClientFactoryServiceKeyNames.Endpoint].ToString();

[GeneratedRegex(@"[^\w\s]")]
private static partial Regex ChatSessionNameReplacementRegex();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private async Task<List<AttachmentProperties>> GetAttachmentPaths(List<string> a
private async Task<List<MessageContentItemBase>> TransformContentItems(List<MessageContentItemBase> contentItems)
{
List<FileMapping> newFileMappings = [];
if (contentItems.Count == 0)
if (contentItems == null || contentItems.Count == 0)
return [];

if (contentItems.All(ci => ci.AgentCapabilityCategory == AgentCapabilityCategoryNames.FoundationaLLMKnowledgeManagement))
Expand Down
24 changes: 16 additions & 8 deletions src/ui/ManagementPortal/components/ApiStatusCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
<h2>{{ apiName }}</h2>
<div v-if="loading" class="loading">Loading...</div>
<div v-else-if="error" class="error">{{ error }}</div>
<div v-else>
<div v-else-if="apiStatus">
<div class="api-detail">
<p><strong>Name:</strong> {{ apiStatus.name }}</p>
<p><strong>Description:</strong> {{ description }}</p>
<p><strong>Instance:</strong> {{ apiStatus.instance }}</p>
<p><strong>Version:</strong> {{ apiStatus.version }}</p>
<p><strong>Status:</strong> {{ apiStatus.status }}</p>
<p v-if="apiStatus.message"><strong>Message:</strong> {{ apiStatus.message }}</p>
<p><strong>URL:</strong> {{ apiUrl }}</p>
</div>
<div v-if="apiStatus.subordinate_services" class="subordinate-services">
<h3>Subordinate Services</h3>
Expand All @@ -26,6 +25,8 @@
</ul>
</div>
</div>
<div v-else>This service does not contain a status endpoint.</div>
<p><strong>URL:</strong> {{ apiUrl }}</p>
</div>
</template>

Expand All @@ -40,6 +41,11 @@ export default {
type: String,
required: true,
},
statusUrl: {
type: [String, null],
required: false,
default: '',
},
description: {
type: String,
required: false,
Expand All @@ -60,15 +66,17 @@ export default {
async fetchApiStatus() {
this.loading = true;
try {
const response = await $fetch(`/api/api-status?url=${encodeURIComponent(this.apiUrl)}`);
if (response.error) {
this.error = response.error;
} else {
this.apiStatus = response;
if (this.statusUrl) {
const response = await $fetch(`/api/api-status?url=${encodeURIComponent(this.statusUrl)}`);
if (response.error) {
this.error = response.error;
} else {
this.apiStatus = response;
}
}
} catch (error) {
console.error('Error fetching API status:', error);
this.error = `Error fetching API status from ${this.apiUrl}`;
this.error = `Error fetching API status from ${this.statusUrl}`;
} finally {
this.loading = false;
}
Expand Down
1 change: 1 addition & 0 deletions src/ui/ManagementPortal/js/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export type ExternalOrchestrationService = ResourceBase & {
api_url_configuration_name: string;
api_key_configuration_name: string;
url: string;
status_url?: string | null;
// The resolved value of the API key configuration reference for displaying in the UI and updating the configuration.
resolved_api_key: string;
};
Expand Down
Loading

0 comments on commit 0892d4f

Please sign in to comment.