mbd-studio-sdk 3.3.0 → 3.4.1

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/README.md CHANGED
@@ -19,13 +19,13 @@ const mbd = new StudioV1({ config });
19
19
 
20
20
  ## Usage
21
21
 
22
- ### 1. Set the target user for personalization
22
+ ### Set the target user for personalization
23
23
  ```javascript
24
24
  const polymarketWallet = '0x123...';
25
25
  mbd.forUser("polymarket-wallets", polymarketWallet);
26
26
  ```
27
27
 
28
- ### 2. Generate candidates
28
+ ### Generate candidates
29
29
 
30
30
  Search your mbd indices using inclide/exclude filters and boosting options.
31
31
 
@@ -44,7 +44,7 @@ const candidates = await mbd.search()
44
44
  .execute();
45
45
  ```
46
46
 
47
- ### 2. Add candidates to current context
47
+ ### Add candidates to current context
48
48
 
49
49
  Attach the search results to the SDK so later steps can use them.
50
50
 
@@ -52,7 +52,7 @@ Attach the search results to the SDK so later steps can use them.
52
52
  mbd.addCandidates(candidates);
53
53
  ```
54
54
 
55
- ### 3. Enrich your data
55
+ ### Enrich your data
56
56
 
57
57
  Fetch features (signals, metadata) for each candidate.
58
58
 
@@ -62,7 +62,7 @@ const features = await mbd.features("v1")
62
62
  mbd.addFeatures(features);
63
63
  ```
64
64
 
65
- ### 4. Run predictive and reranking AI models
65
+ ### Run predictive and reranking AI models
66
66
 
67
67
  Score candidates with ML models for relevance or reranking.
68
68
 
@@ -73,7 +73,7 @@ const scores = await mbd.scoring()
73
73
  mbd.addScores(scores, "rerank_polymkt1");
74
74
  ```
75
75
 
76
- ### 5. Combine all the data into final recommendations
76
+ ### Combine all the data into final recommendations
77
77
 
78
78
  Merge signals and produce the final ranked list with diversity and limits.
79
79
 
@@ -99,6 +99,7 @@ mbd.addRanking(ranking);
99
99
  |--------|-------------|
100
100
  | `forUser(index, userId)` | Set user context for personalization |
101
101
  | `search()` | Build and run a search query |
102
+ | `frequentValues(index, field, size?)` | Fetch frequent values in an index/field (default size: 25) |
102
103
  | `addCandidates(array)` | Add search hits to the current context |
103
104
  | `features(version)` | Fetch features for candidates |
104
105
  | `addFeatures(result)` | Attach features to candidates |
@@ -109,5 +110,5 @@ mbd.addRanking(ranking);
109
110
 
110
111
  ## Useful links
111
112
 
112
- - **Demo repo:** [https://github.com/ZKAI-Network/mbd_studio_demo](https://github.com/ZKAI-Network/mbd_studio_demo)
113
- - **Studio webapp:** [https://api.mbd.xyz/v3/studio/frontend/](https://api.mbd.xyz/v3/studio/frontend/)
113
+ - **Examples:** [https://github.com/ZKAI-Network/mbd_studio_demo](https://github.com/ZKAI-Network/mbd_studio_demo)
114
+ - **Embed Studio webapp:** [https://api.mbd.xyz/v3/studio/frontend/](https://api.mbd.xyz/v3/studio/frontend/)
package/V1/Studio.js CHANGED
@@ -33,6 +33,9 @@ export class Studio {
33
33
  show: this._show,
34
34
  });
35
35
  }
36
+ async frequentValues(index, field, size = 25) {
37
+ return this.search().index(index).frequentValues(field, size);
38
+ }
36
39
  addCandidates(array) {
37
40
  this._candidates.push(...array);
38
41
  }
@@ -142,6 +145,7 @@ export class Studio {
142
145
  for (const hit of this._candidates) {
143
146
  hit._ranking_score = scoreByItemId[hit._id];
144
147
  }
148
+ this._candidates.sort((a, b) => (b._ranking_score ?? -Infinity) - (a._ranking_score ?? -Infinity));
145
149
  }
146
150
  log(string) {
147
151
  this._log(string);
@@ -123,6 +123,39 @@ export class Search {
123
123
  this._log(` max_score: ${infos.max_score}`);
124
124
  return res.hits;
125
125
  }
126
+ async frequentValues(field, size = 25) {
127
+ if (!this._index || typeof this._index !== 'string' || !this._index.trim()) {
128
+ throw new Error('Search.frequentValues: index must be set (call index(name) first)');
129
+ }
130
+ if (typeof field !== 'string' || !field.trim()) {
131
+ throw new Error('Search.frequentValues: field must be a non-empty string');
132
+ }
133
+ const n = Number(size);
134
+ if (!Number.isInteger(n) || n <= 0) {
135
+ throw new Error('Search.frequentValues: size must be a positive integer');
136
+ }
137
+ const endpoint = `/search/frequent_values/${encodeURIComponent(this._index)}/${encodeURIComponent(field.trim())}?size=${n}`;
138
+ const url = `${this._url}${endpoint}`;
139
+ this.log(`GET ${url}`);
140
+ const response = await fetch(url, {
141
+ method: 'GET',
142
+ headers: { Authorization: `Bearer ${this._apiKey}` },
143
+ });
144
+ if (!response.ok) {
145
+ const text = await response.text();
146
+ let message = `Search frequentValues error: ${response.status} ${response.statusText}`;
147
+ if (text) message += ` — ${text}`;
148
+ this.log(message);
149
+ throw new Error(message);
150
+ }
151
+ const result = await response.json();
152
+ if (result && typeof result.error !== 'undefined' && result.error !== null) {
153
+ const msg = typeof result.error === 'string' ? result.error : String(result.error);
154
+ this.log(msg);
155
+ throw new Error(msg);
156
+ }
157
+ return result;
158
+ }
126
159
  async lookup(docId) {
127
160
  if (!this._index || typeof this._index !== 'string' || !this._index.trim()) {
128
161
  throw new Error('Search.lookup: index must be set (call index(name) first)');
package/package.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
2
  "name": "mbd-studio-sdk",
3
- "version": "3.3.0",
4
- "description": "SDK for MBD Studio backend services",
3
+ "version": "3.4.1",
4
+ "description": "SDK for Embed Recommendation Engine APIs",
5
+ "keywords": [
6
+ "web3",
7
+ "AI",
8
+ "recommendations",
9
+ "polymarket",
10
+ "farcaster",
11
+ "zora"
12
+ ],
5
13
  "type": "module",
6
14
  "main": "index.js",
7
15
  "exports": {