Skip to content

Commit bdb9cb4

Browse files
committed
initial grounding prototype
1 parent f25c99d commit bdb9cb4

File tree

4 files changed

+156
-22
lines changed

4 files changed

+156
-22
lines changed

ai/ai-react-app/src/components/Layout/RightSidebar.tsx

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
AVAILABLE_IMAGEN_MODELS,
77
defaultFunctionCallingTool,
88
defaultGoogleSearchTool,
9+
defaultGoogleMapsTool,
910
} from "../../services/firebaseAIService";
1011
import {
1112
ModelParams,
@@ -160,17 +161,49 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
160161
nextState.toolConfig = undefined; // Clear config when turning off
161162
}
162163
} else if (name === "google-search-toggle") {
164+
let currentTools = nextState.tools ? [...nextState.tools] : [];
163165
if (checked) {
164-
// Turn ON Google Search Grounding
165-
nextState.tools = [defaultGoogleSearchTool];
166-
166+
// Add Google Search if not present
167+
if (!currentTools.some((t) => "googleSearch" in t)) {
168+
currentTools.push(defaultGoogleSearchTool);
169+
}
167170
// Turn OFF JSON mode and Function Calling
168171
nextState.generationConfig.responseMimeType = undefined;
169172
nextState.generationConfig.responseSchema = undefined;
170173
nextState.toolConfig = undefined;
171174
} else {
172-
// Turn OFF Google Search Grounding
173-
nextState.tools = undefined;
175+
// Remove Google Search
176+
currentTools = currentTools.filter((t) => !("googleSearch" in t));
177+
}
178+
nextState.tools = currentTools.length > 0 ? currentTools : undefined;
179+
} else if (name === "google-maps-toggle") {
180+
let currentTools = nextState.tools ? [...nextState.tools] : [];
181+
if (checked) {
182+
// Add Google Maps if not present
183+
if (!currentTools.some((t) => "googleMaps" in t)) {
184+
currentTools.push(defaultGoogleMapsTool);
185+
}
186+
// Turn OFF JSON mode and Function Calling
187+
nextState.generationConfig.responseMimeType = undefined;
188+
nextState.generationConfig.responseSchema = undefined;
189+
nextState.toolConfig = undefined;
190+
} else {
191+
// Remove Google Maps
192+
currentTools = currentTools.filter((t) => !("googleMaps" in t));
193+
}
194+
nextState.tools = currentTools.length > 0 ? currentTools : undefined;
195+
} else if (name === "google-maps-widget-toggle") {
196+
let currentTools = nextState.tools ? [...nextState.tools] : [];
197+
const mapToolIndex = currentTools.findIndex((t) => "googleMaps" in t);
198+
if (mapToolIndex !== -1) {
199+
// Update existing tool
200+
currentTools[mapToolIndex] = {
201+
googleMaps: {
202+
enableWidget: checked,
203+
},
204+
};
205+
console.error("DEDB tool: ", currentTools[mapToolIndex]);
206+
nextState.tools = currentTools;
174207
}
175208
}
176209
console.log("[RightSidebar] Updated generative params state:", nextState);
@@ -236,6 +269,13 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
236269
const isGroundingWithGoogleSearchActive = !!generativeParams.tools?.some(
237270
(tool) => "googleSearch" in tool,
238271
);
272+
const isGroundingWithGoogleMapsActive = !!generativeParams.tools?.some(
273+
(tool) => "googleMaps" in tool,
274+
);
275+
// Check if widget is enabled in the first Google Maps tool found
276+
const isGoogleMapsWidgetEnabled = !!generativeParams.tools?.find(
277+
(tool) => "googleMaps" in tool,
278+
)?.googleMaps?.enableWidget;
239279

240280
return (
241281
<div className={styles.rightSidebarContainer}>
@@ -378,11 +418,13 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
378418
checked={isStructuredOutputActive}
379419
onChange={handleToggleChange}
380420
disabled={
381-
isFunctionCallingActive || isGroundingWithGoogleSearchActive
421+
isFunctionCallingActive ||
422+
isGroundingWithGoogleSearchActive ||
423+
isGroundingWithGoogleMapsActive
382424
}
383425
/>
384426
<span
385-
className={`${styles.slider} ${isFunctionCallingActive || isGroundingWithGoogleSearchActive ? styles.disabled : ""}`}
427+
className={`${styles.slider} ${isFunctionCallingActive || isGroundingWithGoogleSearchActive || isGroundingWithGoogleMapsActive ? styles.disabled : ""}`}
386428
></span>
387429
</label>
388430
</div>
@@ -399,7 +441,8 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
399441
onChange={handleToggleChange}
400442
disabled={
401443
isStructuredOutputActive ||
402-
isGroundingWithGoogleSearchActive
444+
isGroundingWithGoogleSearchActive ||
445+
isGroundingWithGoogleMapsActive
403446
}
404447
/>
405448
<span
@@ -424,17 +467,73 @@ const RightSidebar: React.FC<RightSidebarProps> = ({
424467
name="google-search-toggle"
425468
checked={isGroundingWithGoogleSearchActive}
426469
onChange={handleToggleChange}
427-
disabled={isStructuredOutputActive || isFunctionCallingActive}
470+
disabled={
471+
isStructuredOutputActive || isFunctionCallingActive
472+
}
428473
/>
429474
<span
430-
className={`${styles.slider} ${
475+
className={`${styles.slider} ${isStructuredOutputActive ||
476+
isFunctionCallingActive ||
477+
isGroundingWithGoogleMapsActive
478+
? styles.disabled
479+
: ""
480+
}`}
481+
></span>
482+
</label>
483+
</div>
484+
<div
485+
className={`${styles.toggleGroup} ${isStructuredOutputActive ||
486+
isFunctionCallingActive ||
487+
isGroundingWithGoogleSearchActive
488+
? styles.disabledText
489+
: ""
490+
}`}
491+
>
492+
<label htmlFor="google-maps-toggle">
493+
Grounding with Google Maps
494+
</label>
495+
<label className={styles.switch}>
496+
<input
497+
type="checkbox"
498+
id="google-maps-toggle"
499+
name="google-maps-toggle"
500+
checked={isGroundingWithGoogleMapsActive}
501+
onChange={handleToggleChange}
502+
disabled={
431503
isStructuredOutputActive || isFunctionCallingActive
504+
}
505+
/>
506+
<span
507+
className={`${styles.slider} ${
508+
isStructuredOutputActive ||
509+
isFunctionCallingActive ||
510+
isGroundingWithGoogleSearchActive
432511
? styles.disabled
433512
: ""
434513
}`}
435514
></span>
436515
</label>
437516
</div>
517+
{/* Indented Widget Toggle */}
518+
<div
519+
className={`${styles.toggleGroup} ${!isGroundingWithGoogleMapsActive ? styles.disabledText : ""}`}
520+
style={{ paddingLeft: "20px" }}
521+
>
522+
<label htmlFor="google-maps-widget-toggle">Enable Widget</label>
523+
<label className={styles.switch}>
524+
<input
525+
type="checkbox"
526+
id="google-maps-widget-toggle"
527+
name="google-maps-widget-toggle"
528+
checked={isGoogleMapsWidgetEnabled}
529+
onChange={handleToggleChange}
530+
disabled={!isGroundingWithGoogleMapsActive}
531+
/>
532+
<span
533+
className={`${styles.slider} ${!isGroundingWithGoogleMapsActive ? styles.disabled : ""}`}
534+
></span>
535+
</label>
536+
</div>
438537
</div>
439538
</>
440539
)}

ai/ai-react-app/src/components/Specific/ChatMessage.tsx

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ const getMessageText = (message: Content): string => {
3737
.join("");
3838
};
3939

40+
const getChunkDisplayData = (
41+
chunk: GroundingChunk,
42+
): { title: string; uri?: string } => {
43+
if (chunk.web) {
44+
return {
45+
title: chunk.web.title || chunk.web.uri || "Unknown Web Source",
46+
uri: chunk.web.uri,
47+
};
48+
} else if (chunk.maps) {
49+
return {
50+
title: chunk.maps.title || chunk.maps.text || "Unknown Maps Source",
51+
uri: chunk.maps.uri,
52+
};
53+
}
54+
return { title: "Unknown Source" };
55+
};
56+
4057
const renderTextWithInlineHighlighting = (
4158
text: string,
4259
supports: GroundingSupport[],
@@ -89,7 +106,7 @@ const renderTextWithInlineHighlighting = (
89106
const tooltipText = seg.chunkIndices
90107
.map((ci) => {
91108
const chunk = chunks[ci - 1]; // ci is 1-based
92-
return chunk.web?.title || chunk.web?.uri || `Source ${ci}`;
109+
return getChunkDisplayData(chunk).title;
93110
})
94111
.join("; ");
95112

@@ -190,23 +207,30 @@ const ChatMessage: React.FC<ChatMessageProps> = ({
190207
groundingMetadata.groundingChunks.length > 0 && (
191208
<>
192209
<h5 className={styles.sourcesTitle}>Sources:</h5>
193-
<ul className={styles.sourcesList}>
194-
{groundingMetadata.groundingChunks.map((chunk, index) => (
210+
<ul className={styles.sourcesList}>
211+
{groundingMetadata.groundingChunks.map((chunk, index) => {
212+
const displayData = getChunkDisplayData(chunk);
213+
return (
195214
<li
196215
key={index}
197216
className={styles.sourceItem}
198217
id={`source-ref-${index + 1}`}
199218
>
200-
<a
201-
href={chunk.web?.uri}
202-
target="_blank"
203-
rel="noopener noreferrer"
204-
>
205-
{`[${index + 1}] ${chunk.web?.title || chunk.web?.uri}`}
206-
</a>
219+
{displayData.uri ? (
220+
<a
221+
href={displayData.uri}
222+
target="_blank"
223+
rel="noopener noreferrer"
224+
>
225+
{`[${index + 1}] ${displayData.title}`}
226+
</a>
227+
) : (
228+
<span>{`[${index + 1}] ${displayData.title}`}</span>
229+
)}
207230
</li>
208-
))}
209-
</ul>
231+
);
232+
})}
233+
</ul>
210234
</>
211235
)}
212236
</div>

ai/ai-react-app/src/services/firebaseAIService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export const defaultGoogleSearchTool: GoogleSearchTool = {
7272
googleSearch: {}
7373
}
7474

75+
export const defaultGoogleMapsTool = {
76+
googleMaps: {}
77+
}
78+
7579
export const defaultGenerativeParams: Omit<ModelParams, "model"> = {
7680
// Model name itself is selected in the UI
7781
generationConfig: {

ai/ai-react-app/src/views/ChatView.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ const ChatView: React.FC<ChatViewProps> = ({
188188
console.log(
189189
`[ChatView] Grounding Metadata: ${finalModelCandidate?.groundingMetadata}`,
190190
);
191+
192+
if (finalModelCandidate?.groundingMetadata) {
193+
console.log("DEDB lastGroundingMetadata: ", JSON.stringify(finalModelCandidate?.groundingMetadata));
194+
} else {
195+
console.log("DEDB no grounding metadata");
196+
}
197+
191198
setLastGroundingMetadata(
192199
finalModelCandidate?.groundingMetadata || null,
193200
);

0 commit comments

Comments
 (0)