Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit f843a8c

Browse files
committed
add cart recommendation
1 parent a73c5f4 commit f843a8c

File tree

3 files changed

+107
-9
lines changed

3 files changed

+107
-9
lines changed

backend/functions/assembly/search.ts

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,83 @@
11
import { models } from "@hypermode/functions-as";
22
import { EmbeddingsModel } from "@hypermode/models-as/models/experimental/embeddings";
33
import { collections } from "@hypermode/functions-as";
4-
import { getProduct } from "./crud";
4+
import { getProduct, getCart } from "./crud";
55
import { ProductSearchResult, ProductSearchObject, consts } from "./types";
66

7+
export function recommendProductByCart(
8+
cartId: string,
9+
maxItems: i32,
10+
): ProductSearchResult {
11+
const productSearchRes = new ProductSearchResult(
12+
consts.productNameCollection,
13+
consts.searchMethod,
14+
"success",
15+
"",
16+
);
17+
18+
const cart = getCart(cartId);
19+
if (cart === null) {
20+
productSearchRes.status = "error";
21+
productSearchRes.error = "Cart not found";
22+
return productSearchRes;
23+
}
24+
25+
const cartVecs: f32[][] = [];
26+
27+
for (let i = 0; i < cart.items.length; i++) {
28+
const vec = collections.getVector(
29+
consts.productNameCollection,
30+
consts.searchMethod,
31+
cart.items[i].Product.id,
32+
);
33+
34+
cartVecs.push(vec);
35+
}
36+
37+
const sumVec: f32[] = [];
38+
39+
for (let i = 0; i < cartVecs[0].length; i++) {
40+
sumVec[i] = 0;
41+
for (let j = 0; j < cartVecs.length; j++) {
42+
sumVec[i] += cartVecs[j][i];
43+
}
44+
}
45+
46+
const normalizedVec = normalize(sumVec);
47+
48+
const cartProductIds = cart.items.map((item) => item.Product.id);
49+
50+
const semanticSearchRes = collections.searchByVector(
51+
consts.productNameCollection,
52+
consts.searchMethod,
53+
normalizedVec,
54+
maxItems + cart.items.length,
55+
);
56+
57+
if (!semanticSearchRes.isSuccessful) {
58+
productSearchRes.status = semanticSearchRes.status;
59+
productSearchRes.error = semanticSearchRes.error;
60+
61+
return productSearchRes;
62+
}
63+
64+
for (let i = 0; i < semanticSearchRes.objects.length; i++) {
65+
if (cartProductIds.includes(semanticSearchRes.objects[i].key)) {
66+
continue;
67+
}
68+
const searchObj = getSearchObject(
69+
semanticSearchRes.objects[i].key,
70+
semanticSearchRes.objects[i].score,
71+
semanticSearchRes.objects[i].distance,
72+
);
73+
productSearchRes.searchObjs.push(searchObj);
74+
}
75+
76+
productSearchRes.searchObjs = productSearchRes.searchObjs.slice(0, maxItems);
77+
78+
return productSearchRes;
79+
}
80+
781
export function searchProducts(
882
query: string,
983
maxItems: i32,
@@ -125,3 +199,27 @@ export function miniLMEmbed(texts: string[]): f32[][] {
125199

126200
return output.predictions;
127201
}
202+
203+
// Function to calculate the magnitude of a vector
204+
function magnitude(vec: f32[]): f32 {
205+
let sum: f32 = 0.0;
206+
for (let i = 0; i < vec.length; i++) {
207+
sum += vec[i] * vec[i];
208+
}
209+
return f32(Math.sqrt(sum));
210+
}
211+
212+
// Function to normalize a vector
213+
function normalize(vec: f32[]): f32[] {
214+
const mag = magnitude(vec);
215+
if (mag == 0) {
216+
throw new Error("Cannot normalize a zero vector");
217+
}
218+
219+
const normalizedVec: f32[] = [];
220+
for (let i = 0; i < vec.length; i++) {
221+
normalizedVec.push(vec[i] / mag);
222+
}
223+
224+
return normalizedVec;
225+
}

backend/functions/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/functions/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"lint:fix": "eslint --ext .ts --fix ."
1515
},
1616
"dependencies": {
17-
"@hypermode/functions-as": "^0.11.0",
17+
"@hypermode/functions-as": "^0.11.2",
1818
"@hypermode/models-as": "^0.2.2",
1919
"json-as": "^0.9.20"
2020
},

0 commit comments

Comments
 (0)