@ai.ntellect/core 0.1.8 → 0.1.83

Sign up to get free protection for your applications and to get access to all the features.
package/memory/cache.ts CHANGED
@@ -56,22 +56,23 @@ export class CacheMemory {
56
56
  private async storeMemory(memory: CacheMemoryType) {
57
57
  const prefix = this.getMemoryKey(memory.scope, memory.userId);
58
58
  const key = `${prefix}${memory.id}`;
59
- await this.redis.set(key, JSON.stringify(memory), {
59
+ const result = await this.redis.set(key, JSON.stringify(memory), {
60
60
  EX: this.CACHE_TTL,
61
61
  });
62
+ console.log("Cache memory created: ", result);
62
63
  }
63
64
 
64
- async findBestMatches(
65
+ async findSimilarQueries(
65
66
  query: string,
66
67
  options: MatchOptions & { userId?: string; scope?: MemoryScope } = {}
67
68
  ): Promise<
68
69
  {
69
70
  data: any;
70
71
  similarityPercentage: number;
71
- purpose: string;
72
+ query: string;
72
73
  }[]
73
74
  > {
74
- console.log("\n🔍 Searching in cache for query:", query);
75
+ console.log("\nSearching in cache for query:", query);
75
76
 
76
77
  const { embedding } = await embed({
77
78
  model: openai.embedding("text-embedding-3-small"),
@@ -79,21 +80,20 @@ export class CacheMemory {
79
80
  });
80
81
 
81
82
  const memories = await this.getAllMemories(options.scope, options.userId);
82
- console.log("\n📚 Found", memories.length, "memories to compare with");
83
+ console.log("\n📚 Found", memories.length, "queries to compare with");
83
84
 
84
85
  const matches = memories
85
86
  .map((memory) => {
86
87
  const similarity = cosineSimilarity(embedding, memory.embedding);
87
88
  const similarityPercentage = (similarity + 1) * 50; // Conversion en pourcentage
88
89
 
89
- console.log(`\n📊 Memory "${memory.purpose}":
90
- - Similarity: ${similarityPercentage.toFixed(2)}%
91
- - Query: ${memory.query}`);
90
+ console.log(`\n📊 Query "${memory.query}":
91
+ - Similarity: ${similarityPercentage.toFixed(2)}%`);
92
92
 
93
93
  return {
94
94
  data: memory.data,
95
+ query: memory.query,
95
96
  similarityPercentage,
96
- purpose: memory.purpose,
97
97
  // Optionnel : ajouter des métadonnées utiles
98
98
  memoryId: memory.id,
99
99
  };
@@ -109,10 +109,10 @@ export class CacheMemory {
109
109
  : matches;
110
110
 
111
111
  if (results.length > 0) {
112
- console.log("\n✨ Best matches found:");
112
+ console.log("\n✨ Similar queries found:");
113
113
  results.forEach((match) => {
114
114
  console.log(
115
- `- ${match.purpose} (${match.similarityPercentage.toFixed(2)}%)`
115
+ `- ${match.query} (${match.similarityPercentage.toFixed(2)}%)`
116
116
  );
117
117
  });
118
118
  } else {
@@ -123,7 +123,7 @@ export class CacheMemory {
123
123
  return results;
124
124
  }
125
125
 
126
- private async getAllMemories(
126
+ async getAllMemories(
127
127
  scope?: MemoryScope,
128
128
  userId?: string
129
129
  ): Promise<CacheMemoryType[]> {
@@ -162,23 +162,28 @@ export class CacheMemory {
162
162
  public async createMemory(
163
163
  input: CreateMemoryInput
164
164
  ): Promise<string | undefined> {
165
- const existingPattern = await this.findBestMatches(input.content, {
165
+ console.log("Searching for similar memory", input);
166
+ const existingPattern = await this.findSimilarQueries(input.content, {
166
167
  similarityThreshold: 95,
167
168
  userId: input.userId,
168
169
  scope: input.scope,
169
170
  });
170
171
 
171
172
  if (existingPattern.length > 0) {
172
- console.log("\n🔍 Similar memory found:");
173
+ console.log("\nSimilar cache memory found:");
173
174
  existingPattern.forEach((match) => {
174
175
  console.log(
175
- `- ${match.purpose} (${match.similarityPercentage.toFixed(2)}%)`
176
+ `- ${match.query} (${match.similarityPercentage.toFixed(2)}%)`
176
177
  );
177
178
  });
179
+ console.log("Cache memory already exists. No need to create new one..");
178
180
  return;
179
181
  }
180
182
 
183
+ console.log("No similar memory found");
184
+
181
185
  // Générer les variations via GPT-4
186
+ console.log("Generating variations...");
182
187
  const variations = await generateObject({
183
188
  model: openai("gpt-4"),
184
189
  schema: z.object({
@@ -186,20 +191,17 @@ export class CacheMemory {
186
191
  queries: z.array(z.object({ text: z.string() })),
187
192
  }),
188
193
  prompt: `For this input: "${input.content}"
189
- Generate similar variations that should match the same context.
190
- Context type: ${input.type}
191
- Data: ${JSON.stringify(input.data)}
194
+ Generate similar way to ask the same question.
195
+ Action results: ${JSON.stringify(input.data)}
192
196
  - Keep variations natural and human-like
193
- - Include the original input
194
197
  - Add 3-5 variations`,
195
198
  });
196
-
199
+ console.log("Variations generated:", variations.object.queries);
197
200
  await this.createSingleMemory({
198
201
  id: crypto.randomUUID(),
199
202
  content: input.content,
200
203
  type: input.type,
201
204
  data: input.data,
202
- purpose: variations.object.request,
203
205
  userId: input.userId,
204
206
  scope: input.scope,
205
207
  });
@@ -212,7 +214,6 @@ export class CacheMemory {
212
214
  content: variation.text,
213
215
  type: input.type,
214
216
  data: input.data,
215
- purpose: variations.object.request,
216
217
  userId: input.userId,
217
218
  scope: input.scope,
218
219
  });
@@ -229,20 +230,20 @@ export class CacheMemory {
229
230
  content: string;
230
231
  type: MemoryType;
231
232
  data: any;
232
- purpose: string;
233
233
  userId?: string;
234
234
  scope?: MemoryScope;
235
235
  }): Promise<CacheMemoryType> {
236
+ console.log("Creating new cache memory...", params.content);
237
+ console.log("Creating embedding...");
236
238
  const { embedding } = await embed({
237
239
  model: openai.embedding("text-embedding-3-small"),
238
240
  value: params.content,
239
241
  });
240
-
242
+ console.log("Embedding created");
241
243
  const memory: CacheMemoryType = {
242
244
  id: params.id,
243
245
  type: params.type,
244
246
  data: params.data,
245
- purpose: params.purpose,
246
247
  query: params.content,
247
248
  embedding,
248
249
  userId: params.userId,
@@ -250,7 +251,6 @@ export class CacheMemory {
250
251
  params.scope || (params.userId ? MemoryScope.USER : MemoryScope.GLOBAL),
251
252
  createdAt: new Date(),
252
253
  };
253
-
254
254
  await this.storeMemory(memory);
255
255
  return memory;
256
256
  }
@@ -77,7 +77,6 @@ export class PersistentMemory {
77
77
  options: RequestInit = {}
78
78
  ): Promise<T> {
79
79
  const url = `${this.host}${path}`;
80
- console.log("Making request to:", url);
81
80
  const response = await fetch(url, {
82
81
  ...options,
83
82
  headers: {
@@ -187,7 +186,7 @@ export class PersistentMemory {
187
186
  * Find best matching memories
188
187
  */
189
188
  async searchSimilarQueries(query: string, options: SearchOptions = {}) {
190
- console.log("\n🔍 Searching in persistent memory:", query);
189
+ console.log("\nSearching in persistent memory:", query);
191
190
 
192
191
  // Generate embedding for the query
193
192
  const { embedding: queryEmbedding } = await embed({
@@ -240,7 +239,9 @@ export class PersistentMemory {
240
239
  }
241
240
  }
242
241
 
243
- console.log("Found in persistent memory:", searchResults);
242
+ console.log(
243
+ `📚 Found ${searchResults.length} queries in persistent memory`
244
+ );
244
245
 
245
246
  // Process and filter results using cosine similarity
246
247
  const results = searchResults
@@ -272,7 +273,7 @@ export class PersistentMemory {
272
273
 
273
274
  // Log results
274
275
  if (results.length > 0) {
275
- console.log("\n✨ Best matches found:");
276
+ console.log("\n✨ Similar queries found:");
276
277
  results.forEach((match) => {
277
278
  console.log(
278
279
  `- ${match.query} : ${match.similarityPercentage.toFixed(2)}% (${
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai.ntellect/core",
3
- "version": "0.1.8",
3
+ "version": "0.1.83",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -14,7 +14,10 @@
14
14
  "dependencies": {
15
15
  "@ai-sdk/openai": "1.0.6",
16
16
  "ai": "^3.0.0",
17
+ "ethers": "^6.13.5",
18
+ "langchain": "^0.3.11",
17
19
  "redis": "^4.7.0",
20
+ "rss-parser": "^3.13.0",
18
21
  "zod": "^3.24.1"
19
22
  },
20
23
  "devDependencies": {
package/services/queue.ts CHANGED
@@ -42,7 +42,6 @@ export class ActionQueueManager {
42
42
 
43
43
  for (const action of this.queue) {
44
44
  const actionConfig = this.actions.find((a) => a.name === action.name);
45
-
46
45
  if (actionConfig?.confirmation?.requireConfirmation) {
47
46
  // Wait for user confirmation before executing this action
48
47
  const shouldProceed = await this.callbacks.onConfirmationRequired?.(
@@ -62,6 +61,7 @@ export class ActionQueueManager {
62
61
  continue;
63
62
  }
64
63
  }
64
+ const parameters = this.formatArguments(action.parameters);
65
65
 
66
66
  actionPromises.push(
67
67
  this.executeAction(action)
@@ -72,7 +72,7 @@ export class ActionQueueManager {
72
72
  .catch((error) => {
73
73
  const result = {
74
74
  name: action.name,
75
- parameters: this.formatArguments(action.parameters),
75
+ parameters,
76
76
  result: null,
77
77
  error: error.message || "Unknown error occurred",
78
78
  };
@@ -98,7 +98,23 @@ export class ActionQueueManager {
98
98
 
99
99
  private formatArguments(args: QueueItemParameter[]): Record<string, string> {
100
100
  return args.reduce<Record<string, string>>((acc, arg) => {
101
- acc[arg.name] = arg.value;
101
+ try {
102
+ // Parse the JSON string if the value is a stringified JSON object
103
+ const parsedValue = JSON.parse(arg.value);
104
+ if (
105
+ parsedValue &&
106
+ typeof parsedValue === "object" &&
107
+ "value" in parsedValue
108
+ ) {
109
+ acc[parsedValue.name] = parsedValue.value;
110
+ } else {
111
+ // Fallback to original value if not in expected format
112
+ acc[arg.name] = arg.value;
113
+ }
114
+ } catch {
115
+ // If JSON parsing fails, use the original value
116
+ acc[arg.name] = arg.value;
117
+ }
102
118
  return acc;
103
119
  }, {});
104
120
  }
@@ -115,13 +131,7 @@ export class ActionQueueManager {
115
131
  error: `Action '${action.name}' not found in actions list`,
116
132
  };
117
133
  }
118
- const actionArgs = action.parameters.reduce<Record<string, string>>(
119
- (acc: Record<string, string>, arg: QueueItemParameter) => {
120
- acc[arg.name] = arg.value;
121
- return acc;
122
- },
123
- {}
124
- );
134
+ const actionArgs = this.formatArguments(action.parameters);
125
135
  try {
126
136
  const result = await actionConfig.execute(actionArgs);
127
137
  const actionResult = {
@@ -130,8 +140,7 @@ export class ActionQueueManager {
130
140
  result,
131
141
  error: null,
132
142
  };
133
- console.log("Action executed successfully: ", action.name);
134
- console.dir(actionResult, { depth: null });
143
+ console.log("Action executed successfully: ", action.name, "🎉");
135
144
  return actionResult;
136
145
  } catch (error) {
137
146
  const actionResult = {
package/t.ts ADDED
@@ -0,0 +1,133 @@
1
+ export interface NetworkConfig {
2
+ name: string;
3
+ id?: number;
4
+ rpc: string;
5
+ explorerUrl: string;
6
+ nativeToken: string; // WETH
7
+ }
8
+ export const networkConfigs: Record<string, NetworkConfig> = {
9
+ ethereum: {
10
+ name: "Ethereum Mainnet",
11
+ id: 1,
12
+ rpc: "https://eth.llamarpc.com",
13
+ explorerUrl: "https://etherscan.io",
14
+ nativeToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
15
+ },
16
+ polygon: {
17
+ name: "Polygon Mainnet",
18
+ id: 137,
19
+ rpc: "https://polygon.llamarpc.com",
20
+ explorerUrl: "https://polygonscan.com",
21
+ nativeToken: "0x0000000000000000000000000000000000001010",
22
+ },
23
+ arbitrum: {
24
+ name: "Arbitrum Mainnet",
25
+ id: 42161,
26
+ rpc: "https://arbitrum.llamarpc.com",
27
+ explorerUrl: "https://arbiscan.io",
28
+ nativeToken: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
29
+ },
30
+ base: {
31
+ name: "Base Mainnet",
32
+ id: 8453,
33
+ rpc: "https://base.llamarpc.com",
34
+ explorerUrl: "https://basescan.org",
35
+ nativeToken: "0x4200000000000000000000000000000000000006",
36
+ },
37
+ solana: {
38
+ name: "Solana Mainnet",
39
+ rpc: "https://api.mainnet-beta.solana.com",
40
+ explorerUrl: "https://solscan.io",
41
+ nativeToken: "So11111111111111111111111111111111111111112",
42
+ },
43
+ sepolia: {
44
+ name: "Sepolia Testnet",
45
+ id: 11155111,
46
+ rpc: "https://sepolia.llamarpc.com",
47
+ explorerUrl: "https://sepolia.etherscan.io",
48
+ nativeToken: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
49
+ },
50
+ baseSepolia: {
51
+ name: "Base Sepolia Testnet",
52
+ id: 84532,
53
+ rpc: "https://base-sepolia-rpc.publicnode.com",
54
+ explorerUrl: "https://sepolia.basescan.org",
55
+ nativeToken: "0x4200000000000000000000000000000000000006",
56
+ },
57
+ };
58
+
59
+ export const getNetworkProvider = (networkName: string) => {
60
+ const config = networkConfigs[networkName.toLowerCase()];
61
+ if (!config) {
62
+ throw new Error(`Network ${networkName} not supported`);
63
+ }
64
+ return { config };
65
+ };
66
+
67
+ import { parseEther } from "ethers";
68
+ import { z } from "zod";
69
+
70
+ export type TransactionPrepared = {
71
+ to: string;
72
+ value: string;
73
+ data?: string;
74
+ chain: {
75
+ id: number;
76
+ rpc: string;
77
+ };
78
+ type: "transfer" | "approve" | "swap";
79
+ method?: string;
80
+ params?: any[];
81
+ };
82
+
83
+ export const prepareEvmTransaction = {
84
+ name: "prepare-evm-transaction",
85
+ description: "Prepare a transaction for the user to sign.",
86
+ parameters: z.object({
87
+ walletAddress: z.string(),
88
+ amount: z
89
+ .string()
90
+ .describe("Ask the user for the amount to send, if not specified"),
91
+ network: z
92
+ .string()
93
+ .describe(
94
+ "Examples networks: ethereum, arbitrum, base. IMPORTANT: You must respect the network name."
95
+ ),
96
+ }),
97
+ execute: async ({
98
+ walletAddress,
99
+ amount,
100
+ network,
101
+ }: {
102
+ walletAddress: string;
103
+ amount: string;
104
+ network: string;
105
+ }): Promise<TransactionPrepared> => {
106
+ try {
107
+ console.log("💰 Preparing transaction", {
108
+ to: walletAddress,
109
+ amount,
110
+ network,
111
+ });
112
+
113
+ const networkConfig = networkConfigs[network.toLowerCase()];
114
+
115
+ if (!networkConfig) {
116
+ throw new Error(`Network ${network} not found`);
117
+ }
118
+
119
+ return {
120
+ to: walletAddress,
121
+ value: parseEther(amount).toString(),
122
+ chain: {
123
+ id: networkConfig.id || 0,
124
+ rpc: networkConfig.rpc,
125
+ },
126
+ type: "transfer",
127
+ };
128
+ } catch (error) {
129
+ console.error("💰 Error sending transaction:", error);
130
+ throw new Error("An error occurred while sending the transaction");
131
+ }
132
+ },
133
+ };
package/types.ts CHANGED
@@ -126,9 +126,9 @@ export interface CacheMemoryOptions {
126
126
  }
127
127
 
128
128
  export interface CreateMemoryInput {
129
- content: string;
129
+ content: any;
130
130
  type: MemoryType;
131
- data: any;
131
+ data: ActionSchema[];
132
132
  userId?: string;
133
133
  scope?: MemoryScope;
134
134
  }
@@ -137,7 +137,6 @@ export interface CacheMemoryType {
137
137
  id: string;
138
138
  type: MemoryType;
139
139
  data: any;
140
- purpose: string;
141
140
  query: string;
142
141
  embedding: Embedding;
143
142
  userId?: string;
@@ -5,7 +5,7 @@ export const injectActions = (actions: ActionSchema[]) => {
5
5
  return actions.map((action) => {
6
6
  const parameters = action.parameters as z.ZodObject<any>;
7
7
  const schemaShape = Object.keys(parameters._def.shape()).join(", ");
8
- const actionString = `Name: ${action.name}, Description: ${action.description}, Arguments: { ${schemaShape} }`;
8
+ const actionString = `Name: ${action.name}, Description: ${action.description}, Arguments (STRICTLY REQUIRED): { ${schemaShape} }`;
9
9
  return actionString;
10
10
  });
11
11
  };
package/test.ts DELETED
@@ -1,148 +0,0 @@
1
- import Parser from "rss-parser";
2
- import { z } from "zod";
3
- import { Agent } from "./agent";
4
- import { Orchestrator } from "./llm/orchestrator";
5
- import { PersistentMemory } from "./memory/persistent";
6
-
7
- interface ChainTVL {
8
- name: string;
9
- tvl: number;
10
- tokenSymbol: string | null;
11
- chainId: number | string | null;
12
- gecko_id: string | null;
13
- cmcId: string | null;
14
- }
15
-
16
- export const getChainsTVL = {
17
- name: "get_chains_tvl",
18
- description:
19
- "Get current TVL (Total Value Locked) of all chains from DeFiLlama",
20
- parameters: z.object({
21
- limit: z
22
- .number()
23
- .optional()
24
- .default(10)
25
- .describe("Number of top chains to return (default: 10)"),
26
- }),
27
- execute: async ({ limit }: { limit: number }) => {
28
- try {
29
- const response = await fetch("https://api.llama.fi/v2/chains", {
30
- headers: { accept: "*/*" },
31
- });
32
-
33
- if (!response.ok) {
34
- throw new Error(`HTTP error! status: ${response.status}`);
35
- }
36
-
37
- const chains = (await response.json()) as ChainTVL[];
38
-
39
- // Sort chains by TVL in descending order and take top N
40
- const topChains = chains
41
- .sort((a, b) => b.tvl - a.tvl)
42
- .slice(0, limit)
43
- .map((chain) => ({
44
- name: chain.name,
45
- tvl: chain.tvl,
46
- tokenSymbol: chain.tokenSymbol,
47
- }));
48
-
49
- const totalTVL = chains.reduce((sum, chain) => sum + chain.tvl, 0);
50
-
51
- return {
52
- summary: {
53
- totalTVL,
54
- numberOfChains: chains.length,
55
- },
56
- topChains,
57
- };
58
- } catch (error) {
59
- console.error("Error retrieving chains TVL data:", error);
60
- throw new Error(
61
- `Failed to fetch chains TVL data: ${(error as Error).message}`
62
- );
63
- }
64
- },
65
- };
66
-
67
- const RSS_FEEDS = ["https://www.investing.com/rss/news_301.rss"];
68
-
69
- const parser = new Parser();
70
-
71
- function stripHtmlTags(content: string): string {
72
- if (!content) return "";
73
- return content
74
- .replace(/<[^>]*>/g, "")
75
- .replace(/\n/g, "")
76
- .replace(" ", "");
77
- }
78
-
79
- export const getRssNews = {
80
- name: "get-news-rss",
81
- description: "Get latest news about on website",
82
- parameters: z.object({}),
83
- execute: async () => {
84
- const itemsPerSource = 5;
85
-
86
- try {
87
- const feedPromises = RSS_FEEDS.map((url) => parser.parseURL(url));
88
- const results = await Promise.allSettled(feedPromises);
89
- const successfulFeeds = results
90
- .filter(
91
- (result): result is PromiseFulfilledResult<Parser.Output<any>> => {
92
- return (
93
- result.status === "fulfilled" && result.value?.items?.length > 0
94
- );
95
- }
96
- )
97
- .map((result) => result.value);
98
- const allItems = successfulFeeds
99
- .flatMap((feed) => feed.items.slice(0, itemsPerSource))
100
- .sort((a, b) => {
101
- const dateA = a.pubDate ? new Date(a.pubDate).getTime() : 0;
102
- const dateB = b.pubDate ? new Date(b.pubDate).getTime() : 0;
103
- return dateB - dateA;
104
- })
105
- .slice(0, 5)
106
- .map((item) => ({
107
- title: item.title,
108
- content: stripHtmlTags(item.content),
109
- link: item.link,
110
- date: item.pubDate,
111
- source: item.creator || new URL(item.link).hostname,
112
- }));
113
-
114
- const result = {
115
- status: "success",
116
- items: allItems,
117
- };
118
- return result;
119
- } catch (error: any) {
120
- throw error;
121
- }
122
- },
123
- };
124
-
125
- (async () => {
126
- const memory = new PersistentMemory({
127
- host: "http://localhost:7700",
128
- apiKey: "aSampleMasterKey",
129
- });
130
- const orchestrator = new Orchestrator([], memory);
131
- const agent = new Agent({
132
- user: {
133
- id: "1",
134
- },
135
- orchestrator,
136
- persistentMemory: memory,
137
- stream: false,
138
- maxEvaluatorIteration: 1,
139
- });
140
-
141
- const prompt = "fais moi une analyse ethereum";
142
- const context = prompt;
143
- const result = await agent.process(prompt, context, {
144
- onMessage: (message) => {
145
- console.log({ message });
146
- },
147
- });
148
- })();