Skip to content

[VertexAI] Add version info to the rest calls #1238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 1, 2025
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
8 changes: 6 additions & 2 deletions vertexai/src/GenerativeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,12 @@ private string GetURL() {

private async Task SetRequestHeaders(HttpRequestMessage request) {
request.Headers.Add("x-goog-api-key", _firebaseApp.Options.ApiKey);
// TODO: Get the Version from the Firebase.VersionInfo.SdkVersion (requires exposing it via App)
request.Headers.Add("x-goog-api-client", "genai-csharp/0.1.0");
string version = FirebaseInterops.GetVersionInfoSdkVersion();
request.Headers.Add("x-goog-api-client", $"genai-csharp/{version}");
if (FirebaseInterops.GetIsDataCollectionDefaultEnabled(_firebaseApp)) {
request.Headers.Add("X-Firebase-AppId", _firebaseApp.Options.AppId);
request.Headers.Add("X-Firebase-AppVersion", UnityEngine.Application.version);
}
// Add additional Firebase tokens to the header.
await FirebaseInterops.AddFirebaseTokensAsync(request, _firebaseApp);
}
Expand Down
70 changes: 69 additions & 1 deletion vertexai/src/Internal/FirebaseInterops.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace Firebase.VertexAI.Internal {

// Contains internal helper methods for interacting with other Firebase libraries.
internal static class FirebaseInterops {
// The cached fields for FirebaseApp reflection.
private static PropertyInfo _dataCollectionProperty = null;

// The various App Check types needed to retrieve the token, cached via reflection on startup.
private static Type _appCheckType;
Expand All @@ -48,6 +50,7 @@ internal static class FirebaseInterops {
private const string authHeader = "Authorization";

static FirebaseInterops() {
InitializeAppReflection();
InitializeAppCheckReflection();
InitializeAuthReflection();
}
Expand All @@ -58,6 +61,72 @@ private static void LogError(string message) {
#endif
}

// Cache the methods needed for FirebaseApp reflection.
private static void InitializeAppReflection() {
try {
_dataCollectionProperty = typeof(FirebaseApp).GetProperty(
"IsDataCollectionDefaultEnabled",
BindingFlags.Instance | BindingFlags.NonPublic);
if (_dataCollectionProperty == null) {
LogError("Could not find FirebaseApp.IsDataCollectionDefaultEnabled property via reflection.");
return;
}
if (_dataCollectionProperty.PropertyType != typeof(bool)) {
LogError("FirebaseApp.IsDataCollectionDefaultEnabled is not a bool, " +
$"but is {_dataCollectionProperty.PropertyType}");
return;
}
} catch (Exception e) {
LogError($"Failed to initialize FirebaseApp reflection: {e}");
}
}

// Gets the property FirebaseApp.IsDataCollectionDefaultEnabled.
public static bool GetIsDataCollectionDefaultEnabled(FirebaseApp firebaseApp) {
if (firebaseApp == null || _dataCollectionProperty == null) {
return false;
}

try {
return (bool)_dataCollectionProperty.GetValue(firebaseApp);
} catch (Exception e) {
LogError($"Error accessing 'IsDataCollectionDefaultEnabled': {e}");
return false;
}
}

// SDK version to use if unable to find it.
private const string _unknownSdkVersion = "unknown";
private static readonly Lazy<string> _sdkVersionFetcher = new(() => {
try {
// Get the type Firebase.VersionInfo from the assembly that defines FirebaseApp.
Type versionInfoType = typeof(FirebaseApp).Assembly.GetType("Firebase.VersionInfo");
if (versionInfoType == null) {
LogError("Firebase.VersionInfo type not found via reflection");
return _unknownSdkVersion;
}

// Firebase.VersionInfo.SdkVersion
PropertyInfo sdkVersionProperty = versionInfoType.GetProperty(
"SdkVersion",
BindingFlags.Static | BindingFlags.NonPublic);
if (sdkVersionProperty == null) {
LogError("Firebase.VersionInfo.SdkVersion property not found via reflection.");
return _unknownSdkVersion;
}

return sdkVersionProperty.GetValue(null) as string ?? _unknownSdkVersion;
} catch (Exception e) {
LogError($"Error accessing SdkVersion via reflection: {e}");
return _unknownSdkVersion;
}
});

// Gets the internal property Firebase.VersionInfo.SdkVersion
internal static string GetVersionInfoSdkVersion() {
return _sdkVersionFetcher.Value;
}

// Cache the various types and methods needed for AppCheck token retrieval.
private static void InitializeAppCheckReflection() {
const string firebaseAppCheckTypeName = "Firebase.AppCheck.FirebaseAppCheck, Firebase.AppCheck";
Expand Down Expand Up @@ -301,7 +370,6 @@ internal static async Task AddFirebaseTokensAsync(ClientWebSocket socket, Fireba
socket.Options.SetRequestHeader(authHeader, $"Firebase {authToken}");
}
}

}

}
8 changes: 6 additions & 2 deletions vertexai/src/LiveGenerativeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ public async Task<LiveSession> ConnectAsync(CancellationToken cancellationToken
string endpoint = GetURL();

// Set initial headers
// TODO: Get the Version from the Firebase.VersionInfo.SdkVersion (requires exposing it via App)
clientWebSocket.Options.SetRequestHeader("x-goog-api-client", "genai-csharp/0.1.0");
string version = FirebaseInterops.GetVersionInfoSdkVersion();
clientWebSocket.Options.SetRequestHeader("x-goog-api-client", $"genai-csharp/{version}");
if (FirebaseInterops.GetIsDataCollectionDefaultEnabled(_firebaseApp)) {
clientWebSocket.Options.SetRequestHeader("X-Firebase-AppId", _firebaseApp.Options.AppId);
clientWebSocket.Options.SetRequestHeader("X-Firebase-AppVersion", UnityEngine.Application.version);
}
// Add additional Firebase tokens to the header.
await FirebaseInterops.AddFirebaseTokensAsync(clientWebSocket, _firebaseApp);

Expand Down