@cravery/core 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/ai/embedding.d.ts +2 -1
- package/dist/lib/ai/embedding.d.ts.map +1 -1
- package/dist/lib/ai/embedding.js +4 -17
- package/dist/lib/ai/embedding.js.map +1 -1
- package/dist/lib/ai/flow.d.ts +3 -23
- package/dist/lib/ai/flow.d.ts.map +1 -1
- package/dist/lib/ai/flow.js +74 -37
- package/dist/lib/ai/flow.js.map +1 -1
- package/dist/lib/ai/genkit.d.ts +1 -0
- package/dist/lib/ai/genkit.d.ts.map +1 -1
- package/dist/lib/ai/genkit.js +14 -1
- package/dist/lib/ai/genkit.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/ai/embedding.ts +4 -19
- package/src/lib/ai/flow.ts +94 -49
- package/src/lib/ai/genkit.ts +15 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { recipesRetriever } from "./genkit";
|
|
2
|
+
export { recipesRetriever };
|
|
1
3
|
export declare const generateEmbedding: (text: string, flowName: string) => Promise<number[]>;
|
|
2
4
|
export declare const storeEmbedding: (collection: string, docId: string, text: string, flowName?: string, vectorField?: string) => Promise<void>;
|
|
3
|
-
export declare let recipesRetriever: any;
|
|
4
5
|
//# sourceMappingURL=embedding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/embedding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/embedding.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAMpE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,EAAE,UAAU,MAAM,sBAmBrE,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,YAAY,MAAM,EAClB,OAAO,MAAM,EACb,MAAM,MAAM,EACZ,WAAW,MAAM,EACjB,cAAa,MAAoB,kBAYlC,CAAC"}
|
package/dist/lib/ai/embedding.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.storeEmbedding = exports.generateEmbedding = exports.recipesRetriever = void 0;
|
|
4
4
|
const firestore_1 = require("firebase-admin/firestore");
|
|
5
|
-
const firebase_1 = require("
|
|
6
|
-
const core_1 = require("firebase-functions/v2/core");
|
|
7
|
-
const firebase_2 = require("../firebase");
|
|
5
|
+
const firebase_1 = require("../firebase");
|
|
8
6
|
const genkit_1 = require("./genkit");
|
|
7
|
+
Object.defineProperty(exports, "recipesRetriever", { enumerable: true, get: function () { return genkit_1.recipesRetriever; } });
|
|
9
8
|
const cost_1 = require("./cost");
|
|
10
9
|
const ai_1 = require("../../config/ai");
|
|
11
10
|
const types_1 = require("../../types");
|
|
@@ -33,7 +32,7 @@ const generateEmbedding = async (text, flowName) => {
|
|
|
33
32
|
exports.generateEmbedding = generateEmbedding;
|
|
34
33
|
const storeEmbedding = async (collection, docId, text, flowName, vectorField = "embedding") => {
|
|
35
34
|
const embedding = await (0, exports.generateEmbedding)(text, flowName || `${collection}:embedding`);
|
|
36
|
-
await
|
|
35
|
+
await firebase_1.firestore
|
|
37
36
|
.collection(collection)
|
|
38
37
|
.doc(docId)
|
|
39
38
|
.update({
|
|
@@ -41,16 +40,4 @@ const storeEmbedding = async (collection, docId, text, flowName, vectorField = "
|
|
|
41
40
|
});
|
|
42
41
|
};
|
|
43
42
|
exports.storeEmbedding = storeEmbedding;
|
|
44
|
-
(0, core_1.onInit)(() => {
|
|
45
|
-
exports.recipesRetriever = (0, firebase_1.defineFirestoreRetriever)(genkit_1.ai, {
|
|
46
|
-
name: "recipesRetriever",
|
|
47
|
-
firestore: firebase_2.firestore,
|
|
48
|
-
collection: "recipes",
|
|
49
|
-
contentField: "searchTerms",
|
|
50
|
-
vectorField: "titleEmbedding",
|
|
51
|
-
embedder: genkit_1.geminiEmbedding001,
|
|
52
|
-
distanceMeasure: "COSINE",
|
|
53
|
-
distanceResultField: "distance",
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
43
|
//# sourceMappingURL=embedding.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../../src/lib/ai/embedding.ts"],"names":[],"mappings":";;;AAAA,wDAAsD;AACtD,
|
|
1
|
+
{"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../../src/lib/ai/embedding.ts"],"names":[],"mappings":";;;AAAA,wDAAsD;AACtD,0CAAwC;AACxC,qCAAoE;AAM3D,iGANwB,yBAAgB,OAMxB;AALzB,iCAAoC;AACpC,wCAA4C;AAC5C,uCAA8C;AAKvC,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAE,QAAgB,EAAE,EAAE;;IACxE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QAC1C,MAAM,IAAI,uBAAe,CAAC,4CAA4C,EAAE;YACtE,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,WAAE,CAAC,KAAK,CAAC;QAC9B,QAAQ,EAAE,2BAAkB;QAC5B,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IACH,IAAA,iBAAU,EAAC;QACT,IAAI,EAAE,WAAW;QACjB,QAAQ;QACR,KAAK,EAAE,cAAS,CAAC,kBAAkB;QACnC,UAAU,EAAE,IAAI,CAAC,MAAM;KACxB,CAAC,CAAC;IACH,OAAO,MAAA,QAAQ,CAAC,CAAC,CAAC,0CAAE,SAAS,CAAC;AAChC,CAAC,CAAC;AAnBW,QAAA,iBAAiB,qBAmB5B;AAEK,MAAM,cAAc,GAAG,KAAK,EACjC,UAAkB,EAClB,KAAa,EACb,IAAY,EACZ,QAAiB,EACjB,cAAsB,WAAW,EACjC,EAAE;IACF,MAAM,SAAS,GAAG,MAAM,IAAA,yBAAiB,EACvC,IAAI,EACJ,QAAQ,IAAI,GAAG,UAAU,YAAY,CACtC,CAAC;IACF,MAAM,oBAAS;SACZ,UAAU,CAAC,UAAU,CAAC;SACtB,GAAG,CAAC,KAAK,CAAC;SACV,MAAM,CAAC;QACN,CAAC,WAAW,CAAC,EAAE,sBAAU,CAAC,MAAM,CAAC,SAAS,CAAC;KAC5C,CAAC,CAAC;AACP,CAAC,CAAC;AAjBW,QAAA,cAAc,kBAiBzB"}
|
package/dist/lib/ai/flow.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "genkit";
|
|
2
|
+
import { ai } from "./genkit";
|
|
2
3
|
import { AIModelConfig } from "../../types";
|
|
3
4
|
export declare const ImagenOutputSchema: z.ZodObject<{
|
|
4
5
|
images: z.ZodArray<z.ZodObject<{
|
|
@@ -27,27 +28,6 @@ export type ImageFlowHandler<T> = (input: T, prompt: string) => Promise<{
|
|
|
27
28
|
base64Data: string;
|
|
28
29
|
storagePath: string;
|
|
29
30
|
}[]>;
|
|
30
|
-
export declare const createGeminiFlow: <T, R>(name: string, inputSchema: z.ZodSchema<T>, outputSchema: z.ZodSchema<R>, handler: FlowHandler<T, R>, model?: AIModelConfig) =>
|
|
31
|
-
export declare const createImagenFlow: <T>(name: string, inputSchema: z.ZodSchema<T>, handler: ImageFlowHandler<T>, model?: AIModelConfig) =>
|
|
32
|
-
images: z.ZodArray<z.ZodObject<{
|
|
33
|
-
url: z.ZodString;
|
|
34
|
-
path: z.ZodString;
|
|
35
|
-
}, "strip", z.ZodTypeAny, {
|
|
36
|
-
url: string;
|
|
37
|
-
path: string;
|
|
38
|
-
}, {
|
|
39
|
-
url: string;
|
|
40
|
-
path: string;
|
|
41
|
-
}>, "many">;
|
|
42
|
-
}, "strip", z.ZodTypeAny, {
|
|
43
|
-
images: {
|
|
44
|
-
url: string;
|
|
45
|
-
path: string;
|
|
46
|
-
}[];
|
|
47
|
-
}, {
|
|
48
|
-
images: {
|
|
49
|
-
url: string;
|
|
50
|
-
path: string;
|
|
51
|
-
}[];
|
|
52
|
-
}>, z.ZodTypeAny>;
|
|
31
|
+
export declare const createGeminiFlow: <T, R>(name: string, inputSchema: z.ZodSchema<T>, outputSchema: z.ZodSchema<R>, handler: FlowHandler<T, R>, model?: AIModelConfig) => ReturnType<typeof ai.defineFlow>;
|
|
32
|
+
export declare const createImagenFlow: <T>(name: string, inputSchema: z.ZodSchema<T>, handler: ImageFlowHandler<T>, model?: AIModelConfig) => ReturnType<typeof ai.defineFlow>;
|
|
53
33
|
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAO7B,CAAC;AAEH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3E,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAChC,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAAC;AAE5D,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,EACnC,MAAM,MAAM,EACZ,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAC3B,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAC5B,SAAS,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,QAAO,aAAuC,KAmDxC,UAAU,CAAC,OAAO,EAAE,CAAC,UAAU,CACtC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAChC,MAAM,MAAM,EACZ,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAC3B,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAC5B,QAAO,aAAqC,KA+CtC,UAAU,CAAC,OAAO,EAAE,CAAC,UAAU,CACtC,CAAC"}
|
package/dist/lib/ai/flow.js
CHANGED
|
@@ -13,47 +13,84 @@ exports.ImagenOutputSchema = genkit_1.z.object({
|
|
|
13
13
|
})),
|
|
14
14
|
});
|
|
15
15
|
const createGeminiFlow = (name, inputSchema, outputSchema, handler, model = ai_1.AI_MODELS.Gemini25Flash) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
// Lazy initialization - don't access ai until the flow is actually called
|
|
17
|
+
let initialized = false;
|
|
18
|
+
let FlowInputSchema;
|
|
19
|
+
let FlowOutputSchema;
|
|
20
|
+
let prompt;
|
|
21
|
+
let flow;
|
|
22
|
+
const initializeFlow = () => {
|
|
23
|
+
if (!initialized) {
|
|
24
|
+
if (!genkit_2.ai) {
|
|
25
|
+
throw new Error("Genkit AI not initialized. Make sure Firebase Functions onInit has been called.");
|
|
26
|
+
}
|
|
27
|
+
FlowInputSchema = genkit_2.ai.defineSchema(`${name}InputSchema`, inputSchema);
|
|
28
|
+
FlowOutputSchema = genkit_2.ai.defineSchema(`${name}OutputSchema`, outputSchema);
|
|
29
|
+
prompt = genkit_2.ai.prompt(name);
|
|
30
|
+
flow = genkit_2.ai.defineFlow({
|
|
31
|
+
name: name,
|
|
32
|
+
inputSchema: inputSchema,
|
|
33
|
+
outputSchema: outputSchema,
|
|
34
|
+
}, async (input) => {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const response = await prompt(input);
|
|
37
|
+
(0, cost_1.logAIUsage)({
|
|
38
|
+
type: "multimodal",
|
|
39
|
+
flowName: name,
|
|
40
|
+
model,
|
|
41
|
+
inputTokens: ((_a = response.usage) === null || _a === void 0 ? void 0 : _a.inputTokens) || 0,
|
|
42
|
+
outputTokens: ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.outputTokens) || 0,
|
|
43
|
+
});
|
|
44
|
+
return handler(input, response.output);
|
|
45
|
+
});
|
|
46
|
+
initialized = true;
|
|
47
|
+
}
|
|
48
|
+
return flow;
|
|
49
|
+
};
|
|
50
|
+
// Return a proxy function that initializes on first call
|
|
51
|
+
return (async (input) => {
|
|
52
|
+
const actualFlow = initializeFlow();
|
|
53
|
+
return actualFlow(input);
|
|
34
54
|
});
|
|
35
55
|
};
|
|
36
56
|
exports.createGeminiFlow = createGeminiFlow;
|
|
37
57
|
const createImagenFlow = (name, inputSchema, handler, model = ai_1.AI_MODELS.Imagen4Fast) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
// Lazy initialization - don't access ai until the flow is actually called
|
|
59
|
+
let initialized = false;
|
|
60
|
+
let flow;
|
|
61
|
+
const initializeFlow = () => {
|
|
62
|
+
if (!initialized) {
|
|
63
|
+
if (!genkit_2.ai) {
|
|
64
|
+
throw new Error("Genkit AI not initialized. Make sure Firebase Functions onInit has been called.");
|
|
65
|
+
}
|
|
66
|
+
flow = genkit_2.ai.defineFlow({
|
|
67
|
+
name: name,
|
|
68
|
+
inputSchema: inputSchema,
|
|
69
|
+
outputSchema: exports.ImagenOutputSchema,
|
|
70
|
+
}, async (input) => {
|
|
71
|
+
const imageData = await handler(input, name);
|
|
72
|
+
const uploadPromises = imageData.map(({ base64Data, storagePath }) => (0, storage_1.uploadImageToStorage)(base64Data, storagePath).catch((err) => {
|
|
73
|
+
throw err;
|
|
74
|
+
}));
|
|
75
|
+
const uploadedImages = await Promise.all(uploadPromises);
|
|
76
|
+
(0, cost_1.logAIUsage)({
|
|
77
|
+
type: "image",
|
|
78
|
+
flowName: name,
|
|
79
|
+
model,
|
|
80
|
+
imageCount: imageData.length,
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
images: uploadedImages,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
initialized = true;
|
|
87
|
+
}
|
|
88
|
+
return flow;
|
|
89
|
+
};
|
|
90
|
+
// Return a proxy function that initializes on first call
|
|
91
|
+
return (async (input) => {
|
|
92
|
+
const actualFlow = initializeFlow();
|
|
93
|
+
return actualFlow(input);
|
|
57
94
|
});
|
|
58
95
|
};
|
|
59
96
|
exports.createImagenFlow = createImagenFlow;
|
package/dist/lib/ai/flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../../src/lib/ai/flow.ts"],"names":[],"mappings":";;;AAAA,mCAA2B;AAC3B,wCAA4C;AAC5C,iCAAoC;AACpC,qCAA8B;AAC9B,wCAAkD;AAGrC,QAAA,kBAAkB,GAAG,UAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,UAAC,CAAC,KAAK,CACb,UAAC,CAAC,MAAM,CAAC;QACP,GAAG,EAAE,UAAC,CAAC,MAAM,EAAE;QACf,IAAI,EAAE,UAAC,CAAC,MAAM,EAAE;KACjB,CAAC,CACH;CACF,CAAC,CAAC;AAQI,MAAM,gBAAgB,GAAG,CAC9B,IAAY,EACZ,WAA2B,EAC3B,YAA4B,EAC5B,OAA0B,EAC1B,QAAuB,cAAS,CAAC,aAAa,EAC9C,EAAE;IACF,MAAM,eAAe,GAAG,WAAE,CAAC,YAAY,CAAC,GAAG,IAAI,aAAa,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../../src/lib/ai/flow.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/ai/genkit.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genkit.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/genkit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,iBAAiB,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"genkit.d.ts","sourceRoot":"","sources":["../../../src/lib/ai/genkit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,iBAAiB,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAU3D,eAAO,IAAI,EAAE,EAAE,MAAM,CAAC;AACtB,eAAO,IAAI,kBAAkB,EAAE,iBAAiB,CAAC;AACjD,eAAO,IAAI,gBAAgB,EAAE,GAAG,CAAC"}
|
package/dist/lib/ai/genkit.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.geminiEmbedding001 = exports.ai = void 0;
|
|
3
|
+
exports.recipesRetriever = exports.geminiEmbedding001 = exports.ai = void 0;
|
|
4
4
|
const genkit_1 = require("genkit");
|
|
5
5
|
const google_genai_1 = require("@genkit-ai/google-genai");
|
|
6
|
+
const firebase_1 = require("@genkit-ai/firebase");
|
|
6
7
|
const core_1 = require("firebase-functions/v2/core");
|
|
8
|
+
const firebase_2 = require("../firebase");
|
|
7
9
|
const projectId = process.env.GCLOUD_PROJECT || process.env.GCP_PROJECT || "canary-cravery";
|
|
8
10
|
// Initialize during Firebase Functions init phase, not at module load
|
|
9
11
|
(0, core_1.onInit)(() => {
|
|
@@ -16,5 +18,16 @@ const projectId = process.env.GCLOUD_PROJECT || process.env.GCP_PROJECT || "cana
|
|
|
16
18
|
],
|
|
17
19
|
});
|
|
18
20
|
exports.geminiEmbedding001 = google_genai_1.vertexAI.embedder("gemini-embedding-001");
|
|
21
|
+
// Initialize retriever after ai is set up
|
|
22
|
+
exports.recipesRetriever = (0, firebase_1.defineFirestoreRetriever)(exports.ai, {
|
|
23
|
+
name: "recipesRetriever",
|
|
24
|
+
firestore: firebase_2.firestore,
|
|
25
|
+
collection: "recipes",
|
|
26
|
+
contentField: "searchTerms",
|
|
27
|
+
vectorField: "titleEmbedding",
|
|
28
|
+
embedder: exports.geminiEmbedding001,
|
|
29
|
+
distanceMeasure: "COSINE",
|
|
30
|
+
distanceResultField: "distance",
|
|
31
|
+
});
|
|
19
32
|
});
|
|
20
33
|
//# sourceMappingURL=genkit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genkit.js","sourceRoot":"","sources":["../../../src/lib/ai/genkit.ts"],"names":[],"mappings":";;;AAAA,mCAA2D;AAC3D,0DAAmD;AACnD,qDAAoD;
|
|
1
|
+
{"version":3,"file":"genkit.js","sourceRoot":"","sources":["../../../src/lib/ai/genkit.ts"],"names":[],"mappings":";;;AAAA,mCAA2D;AAC3D,0DAAmD;AACnD,kDAA+D;AAC/D,qDAAoD;AACpD,0CAAwC;AAExC,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,gBAAgB,CAAC;AAO5E,sEAAsE;AACtE,IAAA,aAAM,EAAC,GAAG,EAAE;IACV,UAAE,GAAG,IAAA,eAAM,EAAC;QACV,OAAO,EAAE;YACP,IAAA,uBAAQ,EAAC;gBACP,QAAQ,EAAE,aAAa;gBACvB,SAAS;aACV,CAAC;SACH;KACF,CAAC,CAAC;IAEH,0BAAkB,GAAG,uBAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IAE/D,0CAA0C;IAC1C,wBAAgB,GAAG,IAAA,mCAAwB,EAAC,UAAE,EAAE;QAC9C,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAT,oBAAS;QACT,UAAU,EAAE,SAAS;QACrB,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,gBAAgB;QAC7B,QAAQ,EAAE,0BAAkB;QAC5B,eAAe,EAAE,QAAQ;QACzB,mBAAmB,EAAE,UAAU;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
package/src/lib/ai/embedding.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { FieldValue } from "firebase-admin/firestore";
|
|
2
|
-
import { defineFirestoreRetriever } from "@genkit-ai/firebase";
|
|
3
|
-
import { onInit } from "firebase-functions/v2/core";
|
|
4
2
|
import { firestore } from "../firebase";
|
|
5
|
-
import { ai, geminiEmbedding001 } from "./genkit";
|
|
3
|
+
import { ai, geminiEmbedding001, recipesRetriever } from "./genkit";
|
|
6
4
|
import { logAIUsage } from "./cost";
|
|
7
5
|
import { AI_MODELS } from "../../config/ai";
|
|
8
6
|
import { ValidationError } from "../../types";
|
|
9
7
|
|
|
8
|
+
// Re-export retriever from genkit for convenience
|
|
9
|
+
export { recipesRetriever };
|
|
10
|
+
|
|
10
11
|
export const generateEmbedding = async (text: string, flowName: string) => {
|
|
11
12
|
if (text.length < 1 || text.length > 7500) {
|
|
12
13
|
throw new ValidationError("Text must be between 1 and 7500 characters", {
|
|
@@ -46,19 +47,3 @@ export const storeEmbedding = async (
|
|
|
46
47
|
[vectorField]: FieldValue.vector(embedding),
|
|
47
48
|
});
|
|
48
49
|
};
|
|
49
|
-
|
|
50
|
-
// Defer retriever initialization to avoid deployment timeout
|
|
51
|
-
export let recipesRetriever: any;
|
|
52
|
-
|
|
53
|
-
onInit(() => {
|
|
54
|
-
recipesRetriever = defineFirestoreRetriever(ai, {
|
|
55
|
-
name: "recipesRetriever",
|
|
56
|
-
firestore,
|
|
57
|
-
collection: "recipes",
|
|
58
|
-
contentField: "searchTerms",
|
|
59
|
-
vectorField: "titleEmbedding",
|
|
60
|
-
embedder: geminiEmbedding001,
|
|
61
|
-
distanceMeasure: "COSINE",
|
|
62
|
-
distanceResultField: "distance",
|
|
63
|
-
});
|
|
64
|
-
});
|
package/src/lib/ai/flow.ts
CHANGED
|
@@ -27,32 +27,56 @@ export const createGeminiFlow = <T, R>(
|
|
|
27
27
|
handler: FlowHandler<T, R>,
|
|
28
28
|
model: AIModelConfig = AI_MODELS.Gemini25Flash,
|
|
29
29
|
) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
>(name);
|
|
30
|
+
// Lazy initialization - don't access ai until the flow is actually called
|
|
31
|
+
let initialized = false;
|
|
32
|
+
let FlowInputSchema: any;
|
|
33
|
+
let FlowOutputSchema: any;
|
|
34
|
+
let prompt: any;
|
|
35
|
+
let flow: any;
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
37
|
+
const initializeFlow = () => {
|
|
38
|
+
if (!initialized) {
|
|
39
|
+
if (!ai) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
"Genkit AI not initialized. Make sure Firebase Functions onInit has been called.",
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
FlowInputSchema = ai.defineSchema(`${name}InputSchema`, inputSchema);
|
|
45
|
+
FlowOutputSchema = ai.defineSchema(`${name}OutputSchema`, outputSchema);
|
|
46
|
+
prompt = ai.prompt<
|
|
47
|
+
typeof FlowInputSchema,
|
|
48
|
+
typeof FlowOutputSchema,
|
|
49
|
+
z.ZodTypeAny
|
|
50
|
+
>(name);
|
|
51
|
+
|
|
52
|
+
flow = ai.defineFlow(
|
|
53
|
+
{
|
|
54
|
+
name: name,
|
|
55
|
+
inputSchema: inputSchema,
|
|
56
|
+
outputSchema: outputSchema,
|
|
57
|
+
},
|
|
58
|
+
async (input: T) => {
|
|
59
|
+
const response = await prompt(input);
|
|
60
|
+
logAIUsage({
|
|
61
|
+
type: "multimodal",
|
|
62
|
+
flowName: name,
|
|
63
|
+
model,
|
|
64
|
+
inputTokens: response.usage?.inputTokens || 0,
|
|
65
|
+
outputTokens: response.usage?.outputTokens || 0,
|
|
66
|
+
});
|
|
67
|
+
return handler(input, response.output);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
initialized = true;
|
|
71
|
+
}
|
|
72
|
+
return flow;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Return a proxy function that initializes on first call
|
|
76
|
+
return (async (input: T) => {
|
|
77
|
+
const actualFlow = initializeFlow();
|
|
78
|
+
return actualFlow(input);
|
|
79
|
+
}) as ReturnType<typeof ai.defineFlow>;
|
|
56
80
|
};
|
|
57
81
|
|
|
58
82
|
export const createImagenFlow = <T>(
|
|
@@ -61,29 +85,50 @@ export const createImagenFlow = <T>(
|
|
|
61
85
|
handler: ImageFlowHandler<T>,
|
|
62
86
|
model: AIModelConfig = AI_MODELS.Imagen4Fast,
|
|
63
87
|
) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
// Lazy initialization - don't access ai until the flow is actually called
|
|
89
|
+
let initialized = false;
|
|
90
|
+
let flow: any;
|
|
91
|
+
|
|
92
|
+
const initializeFlow = () => {
|
|
93
|
+
if (!initialized) {
|
|
94
|
+
if (!ai) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
"Genkit AI not initialized. Make sure Firebase Functions onInit has been called.",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
flow = ai.defineFlow(
|
|
100
|
+
{
|
|
101
|
+
name: name,
|
|
102
|
+
inputSchema: inputSchema,
|
|
103
|
+
outputSchema: ImagenOutputSchema,
|
|
104
|
+
},
|
|
105
|
+
async (input: T) => {
|
|
106
|
+
const imageData = await handler(input, name);
|
|
107
|
+
const uploadPromises = imageData.map(({ base64Data, storagePath }) =>
|
|
108
|
+
uploadImageToStorage(base64Data, storagePath).catch((err) => {
|
|
109
|
+
throw err;
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
const uploadedImages = await Promise.all(uploadPromises);
|
|
113
|
+
logAIUsage({
|
|
114
|
+
type: "image",
|
|
115
|
+
flowName: name,
|
|
116
|
+
model,
|
|
117
|
+
imageCount: imageData.length,
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
images: uploadedImages,
|
|
121
|
+
};
|
|
122
|
+
},
|
|
76
123
|
);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
},
|
|
88
|
-
);
|
|
124
|
+
initialized = true;
|
|
125
|
+
}
|
|
126
|
+
return flow;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Return a proxy function that initializes on first call
|
|
130
|
+
return (async (input: T) => {
|
|
131
|
+
const actualFlow = initializeFlow();
|
|
132
|
+
return actualFlow(input);
|
|
133
|
+
}) as ReturnType<typeof ai.defineFlow>;
|
|
89
134
|
};
|
package/src/lib/ai/genkit.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { genkit, EmbedderReference, Genkit } from "genkit";
|
|
2
2
|
import { vertexAI } from "@genkit-ai/google-genai";
|
|
3
|
+
import { defineFirestoreRetriever } from "@genkit-ai/firebase";
|
|
3
4
|
import { onInit } from "firebase-functions/v2/core";
|
|
5
|
+
import { firestore } from "../firebase";
|
|
4
6
|
|
|
5
7
|
const projectId =
|
|
6
8
|
process.env.GCLOUD_PROJECT || process.env.GCP_PROJECT || "canary-cravery";
|
|
@@ -8,6 +10,7 @@ const projectId =
|
|
|
8
10
|
// Declare but don't initialize yet - will be initialized in onInit
|
|
9
11
|
export let ai: Genkit;
|
|
10
12
|
export let geminiEmbedding001: EmbedderReference;
|
|
13
|
+
export let recipesRetriever: any;
|
|
11
14
|
|
|
12
15
|
// Initialize during Firebase Functions init phase, not at module load
|
|
13
16
|
onInit(() => {
|
|
@@ -21,4 +24,16 @@ onInit(() => {
|
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
geminiEmbedding001 = vertexAI.embedder("gemini-embedding-001");
|
|
27
|
+
|
|
28
|
+
// Initialize retriever after ai is set up
|
|
29
|
+
recipesRetriever = defineFirestoreRetriever(ai, {
|
|
30
|
+
name: "recipesRetriever",
|
|
31
|
+
firestore,
|
|
32
|
+
collection: "recipes",
|
|
33
|
+
contentField: "searchTerms",
|
|
34
|
+
vectorField: "titleEmbedding",
|
|
35
|
+
embedder: geminiEmbedding001,
|
|
36
|
+
distanceMeasure: "COSINE",
|
|
37
|
+
distanceResultField: "distance",
|
|
38
|
+
});
|
|
24
39
|
});
|