Skip to content

Commit 023329a

Browse files
authored
[Firebase AI] Add new send realtime data functions (#1349)
* [Firebase AI] Add new send realtime data functions * Update LiveSession.cs
1 parent df771e6 commit 023329a

File tree

2 files changed

+79
-16
lines changed

2 files changed

+79
-16
lines changed

docs/readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ Release Notes
112112
### Upcoming
113113
- Changes
114114
- Firebase AI: Add support for Gemini's URL context tool.
115+
- Firebase AI: Add more specific methods for sending realtime data to
116+
the LiveSession. Deprecate the previous SendMediaChunksAsync method.
115117

116118
### 13.3.0
117119
- Changes

firebaseai/src/LiveSession.cs

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ public async Task SendAsync(
125125
if (functionParts.Count > 0)
126126
{
127127
Dictionary<string, object> toolResponse = new() {
128-
{ "toolResponse", new Dictionary<string, object>() {
129-
{ "functionResponses", functionParts.Select(frPart => (frPart as ModelContent.Part).ToJson()["functionResponse"]).ToList() }
130-
}}
131-
};
128+
{ "toolResponse", new Dictionary<string, object>() {
129+
{ "functionResponses", functionParts.Select(frPart => (frPart as ModelContent.Part).ToJson()["functionResponse"]).ToList() }
130+
}}
131+
};
132132
var toolResponseBytes = Encoding.UTF8.GetBytes(Json.Serialize(toolResponse));
133133

134134
await InternalSendBytesAsync(new ArraySegment<byte>(toolResponseBytes), cancellationToken);
@@ -147,15 +147,15 @@ public async Task SendAsync(
147147

148148
// Prepare the message payload
149149
Dictionary<string, object> contentDict = new() {
150-
{ "turnComplete", turnComplete }
151-
};
150+
{ "turnComplete", turnComplete }
151+
};
152152
if (content.HasValue)
153153
{
154154
contentDict["turns"] = new List<object>(new[] { content?.ToJson() });
155155
}
156156
Dictionary<string, object> jsonDict = new() {
157-
{ "clientContent", contentDict }
158-
};
157+
{ "clientContent", contentDict }
158+
};
159159
var byteArray = Encoding.UTF8.GetBytes(Json.Serialize(jsonDict));
160160

161161
await InternalSendBytesAsync(new ArraySegment<byte>(byteArray), cancellationToken);
@@ -166,23 +166,84 @@ public async Task SendAsync(
166166
/// </summary>
167167
/// <param name="mediaChunks">A list of media chunks to send.</param>
168168
/// <param name="cancellationToken">A token to cancel the send operation.</param>
169+
/// <remarks>
170+
/// Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead.
171+
/// </remarks>
172+
/// @deprecated Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead.
173+
[Obsolete("Use SendAudioRealtimeAsync, SendVideoRealtimeAsync, or SendTextRealtimeAsync instead.")]
169174
public async Task SendMediaChunksAsync(
170175
List<ModelContent.InlineDataPart> mediaChunks,
171176
CancellationToken cancellationToken = default)
172177
{
173178
if (mediaChunks == null) return;
174179

180+
await InternalSendRealtimeInputAsync("mediaChunks",
181+
mediaChunks.Select(mc => (mc as ModelContent.Part).ToJson()["inlineData"]).ToList(),
182+
cancellationToken);
183+
}
184+
185+
/// <summary>
186+
/// Sends text data to the server in realtime.
187+
///
188+
/// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
189+
/// details about the realtime input usage.
190+
/// </summary>
191+
/// <param name="text">The text data to send.</param>
192+
/// <param name="cancellationToken">A token to cancel the send operation.</param>
193+
public async Task SendTextRealtimeAsync(
194+
string text,
195+
CancellationToken cancellationToken = default)
196+
{
197+
if (string.IsNullOrEmpty(text)) return;
198+
199+
await InternalSendRealtimeInputAsync("text", text, cancellationToken);
200+
}
201+
202+
/// <summary>
203+
/// Sends audio data to the server in realtime.
204+
///
205+
/// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
206+
/// details about the realtime input usage.
207+
/// </summary>
208+
/// <param name="audio">The audio data to send.</param>
209+
/// <param name="cancellationToken">A token to cancel the send operation.</param>
210+
public async Task SendAudioRealtimeAsync(
211+
ModelContent.InlineDataPart audio,
212+
CancellationToken cancellationToken = default)
213+
{
214+
await InternalSendRealtimeInputAsync("audio",
215+
(audio as ModelContent.Part).ToJson()["inlineData"], cancellationToken);
216+
}
217+
218+
/// <summary>
219+
/// Sends video data to the server in realtime.
220+
///
221+
/// Check https://ai.google.dev/api/live#bidigeneratecontentrealtimeinput for
222+
/// details about the realtime input usage.
223+
/// </summary>
224+
/// <param name="video">The video data to send.</param>
225+
/// <param name="cancellationToken">A token to cancel the send operation.</param>
226+
public async Task SendVideoRealtimeAsync(
227+
ModelContent.InlineDataPart video,
228+
CancellationToken cancellationToken = default)
229+
{
230+
await InternalSendRealtimeInputAsync("video",
231+
(video as ModelContent.Part).ToJson()["inlineData"], cancellationToken);
232+
}
233+
234+
private async Task InternalSendRealtimeInputAsync(
235+
string key, object data, CancellationToken cancellationToken)
236+
{
175237
// Prepare the message payload.
176238
Dictionary<string, object> jsonDict = new() {
177-
{
178-
"realtimeInput", new Dictionary<string, object>() {
179-
{
180-
// InlineDataPart inherits from Part, so this conversion should be safe.
181-
"mediaChunks", mediaChunks.Select(mc => (mc as ModelContent.Part).ToJson()["inlineData"]).ToList()
239+
{
240+
"realtimeInput", new Dictionary<string, object>() {
241+
{
242+
key, data
243+
}
182244
}
183245
}
184-
}
185-
};
246+
};
186247
var byteArray = Encoding.UTF8.GetBytes(Json.Serialize(jsonDict));
187248

188249
await InternalSendBytesAsync(new ArraySegment<byte>(byteArray), cancellationToken);
@@ -214,7 +275,7 @@ private static byte[] ConvertTo16BitPCM(float[] samples)
214275
public Task SendAudioAsync(float[] audioData, CancellationToken cancellationToken = default)
215276
{
216277
ModelContent.InlineDataPart inlineDataPart = new("audio/pcm", ConvertTo16BitPCM(audioData));
217-
return SendMediaChunksAsync(new List<ModelContent.InlineDataPart>(new[] { inlineDataPart }), cancellationToken);
278+
return SendAudioRealtimeAsync(inlineDataPart, cancellationToken);
218279
}
219280

220281
/// <summary>

0 commit comments

Comments
 (0)