@axiom-lattice/examples-deep_research 1.0.10 → 1.0.12
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/.env +10 -21
- package/.turbo/turbo-build.log +7 -6
- package/CHANGELOG.md +13 -0
- package/dist/index.js +118 -11
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/src/agents/research/index.ts +14 -10
- package/src/index.ts +60 -5
- package/tsup.config.ts +12 -0
- package/src/agents/property_viewing/README.md +0 -178
- package/src/agents/property_viewing/index.ts +0 -135
- package/src/agents/property_viewing/tools.ts +0 -347
- package/src/agents/todo/index.ts +0 -21
- package/src/agents/todo/tools/create_todo_item.ts +0 -37
- package/src/agents/todo/tools/read_todo_list.ts +0 -22
package/.env
CHANGED
|
@@ -2,39 +2,28 @@
|
|
|
2
2
|
PORT=4001
|
|
3
3
|
NODE_ENV=development
|
|
4
4
|
|
|
5
|
-
# Supabase Configuration
|
|
6
|
-
|
|
7
|
-
SUPABASE_URL = "https://ldejdqkwvlllycysuvsr.supabase.co"
|
|
8
|
-
SUPABASE_KEY =
|
|
9
|
-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxkZWpkcWt3dmxsbHljeXN1dnNyIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTczNDQxNTQxMCwiZXhwIjoyMDQ5OTkxNDEwfQ.wXCjWe8wuQbb4H1ZlGORDjMlNwmsnhd_aHIGlNEQqm4"
|
|
10
|
-
# LangGraph Configuration
|
|
11
|
-
# LANGGRAPH_API_KEY=your_langgraph_api_key
|
|
12
|
-
|
|
13
5
|
# Webhook Configuration (Optional)
|
|
14
6
|
WEBHOOK_URL=your_webhook_url
|
|
15
7
|
|
|
16
|
-
DASHSCOPE_API_KEY = sk-fc1771ebd6d146b58b7a23cc6c85a257
|
|
17
|
-
|
|
18
8
|
|
|
9
|
+
# DEEPSEEK_API_KEY=sk-83fd32abdac74106a5c35cd208b4b11c
|
|
19
10
|
|
|
20
|
-
|
|
11
|
+
# DEEPSEEK_API_KEY2=sk-fd6982eb19b34c0a85555f5a95e9b675
|
|
21
12
|
|
|
22
|
-
|
|
13
|
+
# SILICONCLOUD_API_KEY=sk-omhkuwebiotihbmgthgrcrzzneundgkeqmfrxnkzeldohpfi
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
VOLCENGINE_API_KEY=3c11b06b-3d48-4cce-a1c7-d9e0f5fab80c
|
|
15
|
+
# VOLCENGINE_API_KEY=3c11b06b-3d48-4cce-a1c7-d9e0f5fab80c
|
|
27
16
|
VOLCENGINE_API_KEY2=a0533576-d6ed-4ca4-a308-473cbf7ebd10
|
|
28
|
-
|
|
17
|
+
# KIMI_API_KEY=sk-9FlkLQyuBD5ULCEGFMFgnqHA5TtV0gYPTYkfBOWAarsaWzaq
|
|
29
18
|
|
|
30
19
|
TAVILY_API_KEY=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
|
|
31
20
|
|
|
32
|
-
DATABASE_URL=postgresql://postgres.ldejdqkwvlllycysuvsr:jfd4whz@GPF2nqx7zhm@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
|
|
33
|
-
QUEUE_NAME=simon_tasks
|
|
34
|
-
REDIS_URL=redis://localhost:6379
|
|
35
|
-
REDIS_PASSWORD=fina
|
|
21
|
+
# DATABASE_URL=postgresql://postgres.ldejdqkwvlllycysuvsr:jfd4whz@GPF2nqx7zhm@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
|
|
22
|
+
# QUEUE_NAME=simon_tasks
|
|
23
|
+
# REDIS_URL=redis://localhost:6379
|
|
24
|
+
# REDIS_PASSWORD=fina
|
|
36
25
|
|
|
37
26
|
LANGSMITH_TRACING=true
|
|
38
27
|
LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
|
|
39
28
|
LANGSMITH_API_KEY="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"
|
|
40
|
-
LANGSMITH_PROJECT=
|
|
29
|
+
LANGSMITH_PROJECT=deepsearch
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
|
|
2
|
-
> @axiom-lattice/examples-deep_research@1.0.
|
|
3
|
-
> tsup
|
|
2
|
+
> @axiom-lattice/examples-deep_research@1.0.12 build /home/runner/work/agentic/agentic/examples/deep_research
|
|
3
|
+
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.5.0
|
|
8
|
+
[34mCLI[39m Using tsup config: /home/runner/work/agentic/agentic/examples/deep_research/tsup.config.ts
|
|
8
9
|
[34mCLI[39m Target: es2020
|
|
9
10
|
[34mCLI[39m Cleaning output folder
|
|
10
11
|
[34mCJS[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
12
|
+
[32mCJS[39m [1mdist/index.js [22m[32m14.28 KB[39m
|
|
13
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m16.33 KB[39m
|
|
14
|
+
[32mCJS[39m ⚡️ Build success in 34ms
|
|
14
15
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 4981ms
|
|
16
17
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m13.00 B[39m
|
package/CHANGELOG.md
ADDED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
"use strict";
|
|
2
3
|
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
@@ -5,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
8
12
|
var __copyProps = (to, from, except, desc) => {
|
|
9
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -22,6 +26,59 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
24
28
|
|
|
29
|
+
// package.json
|
|
30
|
+
var require_package = __commonJS({
|
|
31
|
+
"package.json"(exports2, module2) {
|
|
32
|
+
module2.exports = {
|
|
33
|
+
name: "@axiom-lattice/examples-deep_research",
|
|
34
|
+
version: "1.0.12",
|
|
35
|
+
main: "dist/index.js",
|
|
36
|
+
bin: {
|
|
37
|
+
"lattice-deep-research": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
scripts: {
|
|
40
|
+
build: "tsup",
|
|
41
|
+
start: "node dist/index.js",
|
|
42
|
+
dev: 'tsup src/index.ts --format cjs --dts --watch --onSuccess "node dist/index.js"',
|
|
43
|
+
"dev:nodemon": "nodemon --watch 'src/**/*.ts' --watch '../../packages/core/dist/**/*' --exec 'ts-node' -r tsconfig-paths/register src/index.ts",
|
|
44
|
+
"dev:serve": "tsup src/index.ts --format cjs --dts --watch --serve dist/index.js",
|
|
45
|
+
"dev:inspect": 'tsup src/index.ts --format cjs --dts --watch --onSuccess "node --inspect dist/index.js"',
|
|
46
|
+
lint: "tsc --noEmit",
|
|
47
|
+
test: "jest",
|
|
48
|
+
"test:watch": "jest --watch",
|
|
49
|
+
"test:coverage": "jest --coverage"
|
|
50
|
+
},
|
|
51
|
+
keywords: [],
|
|
52
|
+
author: "",
|
|
53
|
+
license: "ISC",
|
|
54
|
+
description: "Deep Research Server for Axiom Lattice",
|
|
55
|
+
dependencies: {
|
|
56
|
+
"@axiom-lattice/core": "workspace:*",
|
|
57
|
+
"@axiom-lattice/gateway": "workspace:*",
|
|
58
|
+
dotenv: "^16.6.1",
|
|
59
|
+
uuid: "^9.0.1",
|
|
60
|
+
zod: "^3.24.2",
|
|
61
|
+
"zod-to-json-schema": "^3.24.3"
|
|
62
|
+
},
|
|
63
|
+
devDependencies: {
|
|
64
|
+
"@types/jest": "^29.5.14",
|
|
65
|
+
"@types/lodash": "^4.17.16",
|
|
66
|
+
"@types/node": "^20.17.23",
|
|
67
|
+
"@types/uuid": "^9.0.8",
|
|
68
|
+
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
69
|
+
"@typescript-eslint/parser": "^7.2.0",
|
|
70
|
+
eslint: "^8.57.0",
|
|
71
|
+
jest: "^29.7.0",
|
|
72
|
+
nodemon: "^3.1.9",
|
|
73
|
+
"ts-jest": "^29.4.0",
|
|
74
|
+
"ts-node": "^10.9.2",
|
|
75
|
+
tsup: "^8.5.0",
|
|
76
|
+
typescript: "^5.8.2"
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
25
82
|
// src/index.ts
|
|
26
83
|
var import_dotenv = __toESM(require("dotenv"));
|
|
27
84
|
var import_gateway = require("@axiom-lattice/gateway");
|
|
@@ -29,6 +86,7 @@ var import_core2 = require("@axiom-lattice/core");
|
|
|
29
86
|
|
|
30
87
|
// src/agents/research/index.ts
|
|
31
88
|
var import_core = require("@axiom-lattice/core");
|
|
89
|
+
var import_zod = __toESM(require("zod"));
|
|
32
90
|
var subResearchPrompt = `You are a dedicated researcher. Your job is to conduct research based on the users questions.
|
|
33
91
|
|
|
34
92
|
Conduct thorough research and then reply to the user with a detailed answer to their question
|
|
@@ -144,6 +202,18 @@ You have access to a few tools.
|
|
|
144
202
|
Use this to run an internet search for a given query. You can specify the number of results, the topic, and whether raw content should be included.
|
|
145
203
|
`;
|
|
146
204
|
var research_agents = [
|
|
205
|
+
{
|
|
206
|
+
key: "deep_research_agent",
|
|
207
|
+
name: "Deep Research Agent",
|
|
208
|
+
description: "Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.",
|
|
209
|
+
type: import_core.AgentType.DEEP_AGENT,
|
|
210
|
+
tools: ["internet_search"],
|
|
211
|
+
prompt: researchInstructions,
|
|
212
|
+
subAgents: ["critique-agent", "research-agent"],
|
|
213
|
+
schema: import_zod.default.object({
|
|
214
|
+
test: import_zod.default.string().optional()
|
|
215
|
+
})
|
|
216
|
+
},
|
|
147
217
|
{
|
|
148
218
|
key: "research-agent",
|
|
149
219
|
name: "research-agent",
|
|
@@ -158,22 +228,47 @@ var research_agents = [
|
|
|
158
228
|
type: import_core.AgentType.REACT,
|
|
159
229
|
description: "Used to critique the final report. Give this agent some infomration about how you want it to critique the report.",
|
|
160
230
|
prompt: subCritiquePrompt
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
key: "main",
|
|
164
|
-
name: "deep_research_agent",
|
|
165
|
-
description: "Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.",
|
|
166
|
-
type: import_core.AgentType.DEEP_AGENT,
|
|
167
|
-
tools: ["internet_search"],
|
|
168
|
-
prompt: researchInstructions,
|
|
169
|
-
subAgents: ["critique-agent", "research-agent"]
|
|
170
231
|
}
|
|
171
232
|
];
|
|
172
233
|
(0, import_core.registerAgentLattices)(research_agents);
|
|
173
234
|
|
|
174
235
|
// src/index.ts
|
|
175
236
|
var import_path = __toESM(require("path"));
|
|
237
|
+
var PACKAGE_VERSION = require_package().version;
|
|
238
|
+
var BUILD_TIME = (/* @__PURE__ */ new Date()).toISOString();
|
|
239
|
+
var IS_DEV = process.env.NODE_ENV !== "production";
|
|
240
|
+
console.log(`
|
|
241
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
242
|
+
\u2551 Lattice Deep Research Server \u2551
|
|
243
|
+
\u2551 Version: ${PACKAGE_VERSION} \u2551
|
|
244
|
+
\u2551 Build Time: ${BUILD_TIME} \u2551
|
|
245
|
+
\u2551 Environment: ${IS_DEV ? "Development" : "Production"} \u2551
|
|
246
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
247
|
+
`);
|
|
176
248
|
import_dotenv.default.config({ path: import_path.default.resolve(__dirname, "../.env") });
|
|
249
|
+
function parsePort() {
|
|
250
|
+
const args = process.argv.slice(2);
|
|
251
|
+
const portIndex = args.findIndex((arg) => arg === "--port" || arg === "-p");
|
|
252
|
+
if (portIndex !== -1 && args[portIndex + 1]) {
|
|
253
|
+
const port2 = parseInt(args[portIndex + 1], 10);
|
|
254
|
+
if (!isNaN(port2) && port2 > 0 && port2 < 65536) {
|
|
255
|
+
return port2;
|
|
256
|
+
}
|
|
257
|
+
console.warn(
|
|
258
|
+
`Invalid port value: ${args[portIndex + 1]}, using default port 4001`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
if (process.env.PORT) {
|
|
262
|
+
const port2 = parseInt(process.env.PORT, 10);
|
|
263
|
+
if (!isNaN(port2) && port2 > 0 && port2 < 65536) {
|
|
264
|
+
return port2;
|
|
265
|
+
}
|
|
266
|
+
console.warn(
|
|
267
|
+
`Invalid PORT environment variable: ${process.env.PORT}, using default port 4001`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return 4001;
|
|
271
|
+
}
|
|
177
272
|
(0, import_core2.registerModelLattice)(
|
|
178
273
|
"default",
|
|
179
274
|
// {
|
|
@@ -193,12 +288,19 @@ import_dotenv.default.config({ path: import_path.default.resolve(__dirname, "../
|
|
|
193
288
|
// streaming: false,
|
|
194
289
|
// },
|
|
195
290
|
{
|
|
196
|
-
model: "kimi-k2-
|
|
291
|
+
model: "kimi-k2-250905",
|
|
197
292
|
provider: "volcengine",
|
|
198
293
|
streaming: true,
|
|
199
294
|
apiKeyEnvName: "VOLCENGINE_API_KEY2"
|
|
200
295
|
}
|
|
201
296
|
// {
|
|
297
|
+
// model: "kimi-k2-0711-preview",
|
|
298
|
+
// provider: "openai",
|
|
299
|
+
// streaming: true,
|
|
300
|
+
// apiKeyEnvName: "KIMI_API_KEY",
|
|
301
|
+
// baseURL: "https://api.moonshot.cn/v1",
|
|
302
|
+
// }
|
|
303
|
+
// {
|
|
202
304
|
// model: "qwen-plus",
|
|
203
305
|
// provider: "openai",
|
|
204
306
|
// streaming: false,
|
|
@@ -207,5 +309,10 @@ import_dotenv.default.config({ path: import_path.default.resolve(__dirname, "../
|
|
|
207
309
|
// }
|
|
208
310
|
);
|
|
209
311
|
import_gateway.LatticeGateway.registerLatticeRoutes(import_gateway.LatticeGateway.app);
|
|
210
|
-
|
|
312
|
+
var port = parsePort();
|
|
313
|
+
console.log(`Starting server on port ${port}`);
|
|
314
|
+
import_gateway.LatticeGateway.startAsHttpEndpoint({
|
|
315
|
+
port,
|
|
316
|
+
queueServiceConfig: { type: "memory", defaultStartPollingQueue: true }
|
|
317
|
+
});
|
|
211
318
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agents/research/index.ts"],"sourcesContent":["import dotenv from \"dotenv\";\n\nimport { LatticeGateway } from \"@axiom-lattice/gateway\";\nimport {\n registerCheckpointSaver,\n registerModelLattice,\n} from \"@axiom-lattice/core\";\nimport \"./agents\";\nimport path from \"path\";\n\n// 加载环境变量\ndotenv.config({ path: path.resolve(__dirname, \"../.env\") });\n\n// 注册默认模型Lattice\nregisterModelLattice(\n \"default\",\n // {\n // model: \"deepseek-chat\",\n // provider: \"deepseek\",\n // streaming: false,\n // }\n // {\n // model: \"deepseek-chat\",\n // provider: \"deepseek\",\n // streaming: false,\n // apiKeyEnvName: \"DEEPSEEK_API_KEY2\",\n // },\n // {\n // model: \"deepseek-v3-250324\",\n // provider: \"volcengine\",\n // streaming: false,\n // },\n {\n model: \"kimi-k2-250711\",\n provider: \"volcengine\",\n streaming: true,\n apiKeyEnvName: \"VOLCENGINE_API_KEY2\",\n }\n // {\n // model: \"qwen-plus\",\n // provider: \"openai\",\n // streaming: false,\n // apiKeyEnvName: \"DASHSCOPE_API_KEY\",\n // baseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n // }\n);\n\nLatticeGateway.registerLatticeRoutes(LatticeGateway.app);\n\nLatticeGateway.startAsHttpEndpoint({ port: 4001 });\n","/* eslint-disable no-console */\n\nimport {\n registerAgentLattices,\n AgentType,\n AgentConfig,\n} from \"@axiom-lattice/core\";\n\nconst subResearchPrompt = `You are a dedicated researcher. Your job is to conduct research based on the users questions.\n\nConduct thorough research and then reply to the user with a detailed answer to their question\n\nonly your FINAL answer will be passed on to the user. They will have NO knowledge of anything except your final message, so your final report should be your final message!`;\n\nconst subCritiquePrompt = `You are a dedicated editor. You are being tasked to critique a report.\n\nYou can find the report at \\`final_report.md\\`.\n\nYou can find the question/topic for this report at \\`question.txt\\`.\n\nThe user may ask for specific areas to critique the report in. Respond to the user with a detailed critique of the report. Things that could be improved.\n\nYou can use the search tool to search for information, if that will help you critique the report\n\nDo not write to the \\`final_report.md\\` yourself.\n\nThings to check:\n- Check that each section is appropriately named\n- Check that the report is written as you would find in an essay or a textbook - it should be text heavy, do not let it just be a list of bullet points!\n- Check that the report is comprehensive. If any paragraphs or sections are short, or missing important details, point it out.\n- Check that the article covers key areas of the industry, ensures overall understanding, and does not omit important parts.\n- Check that the article deeply analyzes causes, impacts, and trends, providing valuable insights\n- Check that the article closely follows the research topic and directly answers questions\n- Check that the article has a clear structure, fluent language, and is easy to understand.\n`;\n\n// Prompt prefix to steer the agent to be an expert researcher\nconst researchInstructions = `You are an expert researcher. Your job is to conduct thorough research, and then write a polished report.\n\nThe first thing you should do is to write the original user question to \\`question.txt\\` so you have a record of it.\n\nUse the research-agent to conduct deep research. It will respond to your questions/topics with a detailed answer.\n\nWhen you think you enough information to write a final report, write it to \\`final_report.md\\`\n\nYou can call the critique-agent to get a critique of the final report. After that (if needed) you can do more research and edit the \\`final_report.md\\`\nYou can do this however many times you want until are you satisfied with the result.\n\nOnly edit the file once at a time (if you call this tool in parallel, there may be conflicts).\n\nHere are instructions for writing the final report:\n\n<report_instructions>\n\nCRITICAL: Make sure the answer is written in the same language as the human messages! If you make a todo plan - you should note in the plan what language the report should be in so you dont forget!\nNote: the language the report should be in is the language the QUESTION is in, not the language/country that the question is ABOUT.\n\nPlease create a detailed answer to the overall research brief that:\n1. Is well-organized with proper headings (# for title, ## for sections, ### for subsections)\n2. Includes specific facts and insights from the research\n3. References relevant sources using [Title](URL) format\n4. Provides a balanced, thorough analysis. Be as comprehensive as possible, and include all information that is relevant to the overall research question. People are using you for deep research and will expect detailed, comprehensive answers.\n5. Includes a \"Sources\" section at the end with all referenced links\n\nYou can structure your report in a number of different ways. Here are some examples:\n\nTo answer a question that asks you to compare two things, you might structure your report like this:\n1/ intro\n2/ overview of topic A\n3/ overview of topic B\n4/ comparison between A and B\n5/ conclusion\n\nTo answer a question that asks you to return a list of things, you might only need a single section which is the entire list.\n1/ list of things or table of things\nOr, you could choose to make each item in the list a separate section in the report. When asked for lists, you don't need an introduction or conclusion.\n1/ item 1\n2/ item 2\n3/ item 3\n\nTo answer a question that asks you to summarize a topic, give a report, or give an overview, you might structure your report like this:\n1/ overview of topic\n2/ concept 1\n3/ concept 2\n4/ concept 3\n5/ conclusion\n\nIf you think you can answer the question with a single section, you can do that too!\n1/ answer\n\nREMEMBER: Section is a VERY fluid and loose concept. You can structure your report however you think is best, including in ways that are not listed above!\nMake sure that your sections are cohesive, and make sense for the reader.\n\nFor each section of the report, do the following:\n- Use simple, clear language\n- Use ## for section title (Markdown format) for each section of the report\n- Do NOT ever refer to yourself as the writer of the report. This should be a professional report without any self-referential language.\n- Do not say what you are doing in the report. Just write the report without any commentary from yourself.\n- Each section should be as long as necessary to deeply answer the question with the information you have gathered. It is expected that sections will be fairly long and verbose. You are writing a deep research report, and users will expect a thorough answer.\n- Use bullet points to list out information when appropriate, but by default, write in paragraph form.\n\nREMEMBER:\nThe brief and research may be in English, but you need to translate this information to the right language when writing the final answer.\nMake sure the final answer report is in the SAME language as the human messages in the message history.\n\nFormat the report in clear markdown with proper structure and include source references where appropriate.\n\n<Citation Rules>\n- Assign each unique URL a single citation number in your text\n- End with ### Sources that lists each source with corresponding numbers\n- IMPORTANT: Number sources sequentially without gaps (1,2,3,4...) in the final list regardless of which sources you choose\n- Each source should be a separate line item in a list, so that in markdown it is rendered as a list.\n- Example format:\n [1] Source Title: URL\n [2] Source Title: URL\n- Citations are extremely important. Make sure to include these, and pay a lot of attention to getting these right. Users will often use these citations to look into more information.\n</Citation Rules>\n</report_instructions>\n\nYou have access to a few tools.\n\n## \\`internet_search\\`\n\nUse this to run an internet search for a given query. You can specify the number of results, the topic, and whether raw content should be included.\n`;\n\nconst research_agents: AgentConfig[] = [\n {\n key: \"research-agent\",\n name: \"research-agent\",\n type: AgentType.REACT,\n description:\n \"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.\",\n prompt: subResearchPrompt,\n tools: [\"internet_search\"],\n },\n {\n key: \"critique-agent\",\n name: \"critique-agent\",\n type: AgentType.REACT,\n description:\n \"Used to critique the final report. Give this agent some infomration about how you want it to critique the report.\",\n prompt: subCritiquePrompt,\n },\n {\n key: \"main\",\n name: \"deep_research_agent\",\n description:\n \"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.\",\n type: AgentType.DEEP_AGENT,\n tools: [\"internet_search\"],\n prompt: researchInstructions,\n subAgents: [\"critique-agent\", \"research-agent\"],\n },\n];\n\nregisterAgentLattices(research_agents);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oBAAmB;AAEnB,qBAA+B;AAC/B,IAAAA,eAGO;;;ACJP,kBAIO;AAEP,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAM1B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuB1B,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyF7B,IAAM,kBAAiC;AAAA,EACrC;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM,sBAAU;AAAA,IAChB,aACE;AAAA,IACF,QAAQ;AAAA,IACR,OAAO,CAAC,iBAAiB;AAAA,EAC3B;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM,sBAAU;AAAA,IAChB,aACE;AAAA,IACF,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,IACN,aACE;AAAA,IACF,MAAM,sBAAU;AAAA,IAChB,OAAO,CAAC,iBAAiB;AAAA,IACzB,QAAQ;AAAA,IACR,WAAW,CAAC,kBAAkB,gBAAgB;AAAA,EAChD;AACF;AAAA,IAEA,mCAAsB,eAAe;;;ADpJrC,kBAAiB;AAGjB,cAAAC,QAAO,OAAO,EAAE,MAAM,YAAAC,QAAK,QAAQ,WAAW,SAAS,EAAE,CAAC;AAAA,IAG1D;AAAA,EACE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA;AAAA,IACE,OAAO;AAAA,IACP,UAAU;AAAA,IACV,WAAW;AAAA,IACX,eAAe;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQF;AAEA,8BAAe,sBAAsB,8BAAe,GAAG;AAEvD,8BAAe,oBAAoB,EAAE,MAAM,KAAK,CAAC;","names":["import_core","dotenv","path"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/index.ts","../src/agents/research/index.ts"],"sourcesContent":["{\n \"name\": \"@axiom-lattice/examples-deep_research\",\n \"version\": \"1.0.12\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"lattice-deep-research\": \"./dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"start\": \"node dist/index.js\",\n \"dev\": \"tsup src/index.ts --format cjs --dts --watch --onSuccess \\\"node dist/index.js\\\"\",\n \"dev:nodemon\": \"nodemon --watch 'src/**/*.ts' --watch '../../packages/core/dist/**/*' --exec 'ts-node' -r tsconfig-paths/register src/index.ts\",\n \"dev:serve\": \"tsup src/index.ts --format cjs --dts --watch --serve dist/index.js\",\n \"dev:inspect\": \"tsup src/index.ts --format cjs --dts --watch --onSuccess \\\"node --inspect dist/index.js\\\"\",\n \"lint\": \"tsc --noEmit\",\n \"test\": \"jest\",\n \"test:watch\": \"jest --watch\",\n \"test:coverage\": \"jest --coverage\"\n },\n \"keywords\": [],\n \"author\": \"\",\n \"license\": \"ISC\",\n \"description\": \"Deep Research Server for Axiom Lattice\",\n \"dependencies\": {\n \"@axiom-lattice/core\": \"workspace:*\",\n \"@axiom-lattice/gateway\": \"workspace:*\",\n \"dotenv\": \"^16.6.1\",\n \"uuid\": \"^9.0.1\",\n \"zod\": \"^3.24.2\",\n \"zod-to-json-schema\": \"^3.24.3\"\n },\n \"devDependencies\": {\n \"@types/jest\": \"^29.5.14\",\n \"@types/lodash\": \"^4.17.16\",\n \"@types/node\": \"^20.17.23\",\n \"@types/uuid\": \"^9.0.8\",\n \"@typescript-eslint/eslint-plugin\": \"^7.2.0\",\n \"@typescript-eslint/parser\": \"^7.2.0\",\n \"eslint\": \"^8.57.0\",\n \"jest\": \"^29.7.0\",\n \"nodemon\": \"^3.1.9\",\n \"ts-jest\": \"^29.4.0\",\n \"ts-node\": \"^10.9.2\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.2\"\n }\n}\n","import dotenv from \"dotenv\";\n\nimport { LatticeGateway } from \"@axiom-lattice/gateway\";\nimport {\n registerCheckpointSaver,\n registerModelLattice,\n} from \"@axiom-lattice/core\";\nimport \"./agents\";\nimport path from \"path\";\n// 在文件开头添加\nconst PACKAGE_VERSION = require(\"../package.json\").version;\nconst BUILD_TIME = new Date().toISOString();\nconst IS_DEV = process.env.NODE_ENV !== \"production\";\n\n// 在启动时输出\nconsole.log(`\n╔═══════════════════════════════════════╗\n║ Lattice Deep Research Server ║\n║ Version: ${PACKAGE_VERSION} ║\n║ Build Time: ${BUILD_TIME} ║\n║ Environment: ${IS_DEV ? \"Development\" : \"Production\"} ║\n╚═══════════════════════════════════════╝\n`);\n// Load environment variables\ndotenv.config({ path: path.resolve(__dirname, \"../.env\") });\n\n// Parse command line arguments for port configuration\nfunction parsePort(): number {\n const args = process.argv.slice(2);\n const portIndex = args.findIndex((arg) => arg === \"--port\" || arg === \"-p\");\n\n if (portIndex !== -1 && args[portIndex + 1]) {\n const port = parseInt(args[portIndex + 1], 10);\n if (!isNaN(port) && port > 0 && port < 65536) {\n return port;\n }\n console.warn(\n `Invalid port value: ${args[portIndex + 1]}, using default port 4001`\n );\n }\n\n // Check environment variable\n if (process.env.PORT) {\n const port = parseInt(process.env.PORT, 10);\n if (!isNaN(port) && port > 0 && port < 65536) {\n return port;\n }\n console.warn(\n `Invalid PORT environment variable: ${process.env.PORT}, using default port 4001`\n );\n }\n\n // Default port\n return 4001;\n}\n\n// Register default model Lattice\nregisterModelLattice(\n \"default\",\n // {\n // model: \"deepseek-chat\",\n // provider: \"deepseek\",\n // streaming: false,\n // }\n // {\n // model: \"deepseek-chat\",\n // provider: \"deepseek\",\n // streaming: false,\n // apiKeyEnvName: \"DEEPSEEK_API_KEY2\",\n // },\n // {\n // model: \"deepseek-v3-250324\",\n // provider: \"volcengine\",\n // streaming: false,\n // },\n {\n model: \"kimi-k2-250905\",\n provider: \"volcengine\",\n streaming: true,\n apiKeyEnvName: \"VOLCENGINE_API_KEY2\",\n }\n // {\n // model: \"kimi-k2-0711-preview\",\n // provider: \"openai\",\n // streaming: true,\n // apiKeyEnvName: \"KIMI_API_KEY\",\n // baseURL: \"https://api.moonshot.cn/v1\",\n // }\n // {\n // model: \"qwen-plus\",\n // provider: \"openai\",\n // streaming: false,\n // apiKeyEnvName: \"DASHSCOPE_API_KEY\",\n // baseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n // }\n);\nLatticeGateway.registerLatticeRoutes(LatticeGateway.app);\n\nconst port = parsePort();\nconsole.log(`Starting server on port ${port}`);\n\nLatticeGateway.startAsHttpEndpoint({\n port,\n queueServiceConfig: { type: \"memory\", defaultStartPollingQueue: true },\n});\n","/* eslint-disable no-console */\n\nimport {\n registerAgentLattices,\n AgentType,\n AgentConfig,\n} from \"@axiom-lattice/core\";\nimport z from \"zod\";\n\nconst subResearchPrompt = `You are a dedicated researcher. Your job is to conduct research based on the users questions.\n\nConduct thorough research and then reply to the user with a detailed answer to their question\n\nonly your FINAL answer will be passed on to the user. They will have NO knowledge of anything except your final message, so your final report should be your final message!`;\n\nconst subCritiquePrompt = `You are a dedicated editor. You are being tasked to critique a report.\n\nYou can find the report at \\`final_report.md\\`.\n\nYou can find the question/topic for this report at \\`question.txt\\`.\n\nThe user may ask for specific areas to critique the report in. Respond to the user with a detailed critique of the report. Things that could be improved.\n\nYou can use the search tool to search for information, if that will help you critique the report\n\nDo not write to the \\`final_report.md\\` yourself.\n\nThings to check:\n- Check that each section is appropriately named\n- Check that the report is written as you would find in an essay or a textbook - it should be text heavy, do not let it just be a list of bullet points!\n- Check that the report is comprehensive. If any paragraphs or sections are short, or missing important details, point it out.\n- Check that the article covers key areas of the industry, ensures overall understanding, and does not omit important parts.\n- Check that the article deeply analyzes causes, impacts, and trends, providing valuable insights\n- Check that the article closely follows the research topic and directly answers questions\n- Check that the article has a clear structure, fluent language, and is easy to understand.\n`;\n\n// Prompt prefix to steer the agent to be an expert researcher\nconst researchInstructions = `You are an expert researcher. Your job is to conduct thorough research, and then write a polished report.\n\nThe first thing you should do is to write the original user question to \\`question.txt\\` so you have a record of it.\n\nUse the research-agent to conduct deep research. It will respond to your questions/topics with a detailed answer.\n\nWhen you think you enough information to write a final report, write it to \\`final_report.md\\`\n\nYou can call the critique-agent to get a critique of the final report. After that (if needed) you can do more research and edit the \\`final_report.md\\`\nYou can do this however many times you want until are you satisfied with the result.\n\nOnly edit the file once at a time (if you call this tool in parallel, there may be conflicts).\n\nHere are instructions for writing the final report:\n\n<report_instructions>\n\nCRITICAL: Make sure the answer is written in the same language as the human messages! If you make a todo plan - you should note in the plan what language the report should be in so you dont forget!\nNote: the language the report should be in is the language the QUESTION is in, not the language/country that the question is ABOUT.\n\nPlease create a detailed answer to the overall research brief that:\n1. Is well-organized with proper headings (# for title, ## for sections, ### for subsections)\n2. Includes specific facts and insights from the research\n3. References relevant sources using [Title](URL) format\n4. Provides a balanced, thorough analysis. Be as comprehensive as possible, and include all information that is relevant to the overall research question. People are using you for deep research and will expect detailed, comprehensive answers.\n5. Includes a \"Sources\" section at the end with all referenced links\n\nYou can structure your report in a number of different ways. Here are some examples:\n\nTo answer a question that asks you to compare two things, you might structure your report like this:\n1/ intro\n2/ overview of topic A\n3/ overview of topic B\n4/ comparison between A and B\n5/ conclusion\n\nTo answer a question that asks you to return a list of things, you might only need a single section which is the entire list.\n1/ list of things or table of things\nOr, you could choose to make each item in the list a separate section in the report. When asked for lists, you don't need an introduction or conclusion.\n1/ item 1\n2/ item 2\n3/ item 3\n\nTo answer a question that asks you to summarize a topic, give a report, or give an overview, you might structure your report like this:\n1/ overview of topic\n2/ concept 1\n3/ concept 2\n4/ concept 3\n5/ conclusion\n\nIf you think you can answer the question with a single section, you can do that too!\n1/ answer\n\nREMEMBER: Section is a VERY fluid and loose concept. You can structure your report however you think is best, including in ways that are not listed above!\nMake sure that your sections are cohesive, and make sense for the reader.\n\nFor each section of the report, do the following:\n- Use simple, clear language\n- Use ## for section title (Markdown format) for each section of the report\n- Do NOT ever refer to yourself as the writer of the report. This should be a professional report without any self-referential language.\n- Do not say what you are doing in the report. Just write the report without any commentary from yourself.\n- Each section should be as long as necessary to deeply answer the question with the information you have gathered. It is expected that sections will be fairly long and verbose. You are writing a deep research report, and users will expect a thorough answer.\n- Use bullet points to list out information when appropriate, but by default, write in paragraph form.\n\nREMEMBER:\nThe brief and research may be in English, but you need to translate this information to the right language when writing the final answer.\nMake sure the final answer report is in the SAME language as the human messages in the message history.\n\nFormat the report in clear markdown with proper structure and include source references where appropriate.\n\n<Citation Rules>\n- Assign each unique URL a single citation number in your text\n- End with ### Sources that lists each source with corresponding numbers\n- IMPORTANT: Number sources sequentially without gaps (1,2,3,4...) in the final list regardless of which sources you choose\n- Each source should be a separate line item in a list, so that in markdown it is rendered as a list.\n- Example format:\n [1] Source Title: URL\n [2] Source Title: URL\n- Citations are extremely important. Make sure to include these, and pay a lot of attention to getting these right. Users will often use these citations to look into more information.\n</Citation Rules>\n</report_instructions>\n\nYou have access to a few tools.\n\n## \\`internet_search\\`\n\nUse this to run an internet search for a given query. You can specify the number of results, the topic, and whether raw content should be included.\n`;\n\nconst research_agents: AgentConfig[] = [\n {\n key: \"deep_research_agent\",\n name: \"Deep Research Agent\",\n description:\n \"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.\",\n type: AgentType.DEEP_AGENT,\n tools: [\"internet_search\"],\n prompt: researchInstructions,\n subAgents: [\"critique-agent\", \"research-agent\"],\n schema: z.object({\n test: z.string().optional(),\n }),\n },\n {\n key: \"research-agent\",\n name: \"research-agent\",\n type: AgentType.REACT,\n description:\n \"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.\",\n prompt: subResearchPrompt,\n tools: [\"internet_search\"],\n },\n {\n key: \"critique-agent\",\n name: \"critique-agent\",\n type: AgentType.REACT,\n description:\n \"Used to critique the final report. Give this agent some infomration about how you want it to critique the report.\",\n prompt: subCritiquePrompt,\n },\n];\n\nregisterAgentLattices(research_agents);\n"],"mappings":"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","names":["exports","module","import_core","z","dotenv","path","port"]}
|
package/package.json
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiom-lattice/examples-deep_research",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"lattice-deep-research": "./dist/index.js"
|
|
7
|
+
},
|
|
5
8
|
"keywords": [],
|
|
6
9
|
"author": "",
|
|
7
10
|
"license": "ISC",
|
|
8
|
-
"description": "
|
|
11
|
+
"description": "Deep Research Server for Axiom Lattice",
|
|
9
12
|
"dependencies": {
|
|
10
13
|
"dotenv": "^16.6.1",
|
|
11
14
|
"uuid": "^9.0.1",
|
|
12
15
|
"zod": "^3.24.2",
|
|
13
16
|
"zod-to-json-schema": "^3.24.3",
|
|
14
|
-
"@axiom-lattice/core": "2.
|
|
15
|
-
"@axiom-lattice/gateway": "2.
|
|
17
|
+
"@axiom-lattice/core": "2.1.12",
|
|
18
|
+
"@axiom-lattice/gateway": "2.1.17"
|
|
16
19
|
},
|
|
17
20
|
"devDependencies": {
|
|
18
21
|
"@types/jest": "^29.5.14",
|
|
@@ -30,7 +33,7 @@
|
|
|
30
33
|
"typescript": "^5.8.2"
|
|
31
34
|
},
|
|
32
35
|
"scripts": {
|
|
33
|
-
"build": "tsup
|
|
36
|
+
"build": "tsup",
|
|
34
37
|
"start": "node dist/index.js",
|
|
35
38
|
"dev": "tsup src/index.ts --format cjs --dts --watch --onSuccess \"node dist/index.js\"",
|
|
36
39
|
"dev:nodemon": "nodemon --watch 'src/**/*.ts' --watch '../../packages/core/dist/**/*' --exec 'ts-node' -r tsconfig-paths/register src/index.ts",
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
AgentType,
|
|
6
6
|
AgentConfig,
|
|
7
7
|
} from "@axiom-lattice/core";
|
|
8
|
+
import z from "zod";
|
|
8
9
|
|
|
9
10
|
const subResearchPrompt = `You are a dedicated researcher. Your job is to conduct research based on the users questions.
|
|
10
11
|
|
|
@@ -125,6 +126,19 @@ Use this to run an internet search for a given query. You can specify the number
|
|
|
125
126
|
`;
|
|
126
127
|
|
|
127
128
|
const research_agents: AgentConfig[] = [
|
|
129
|
+
{
|
|
130
|
+
key: "deep_research_agent",
|
|
131
|
+
name: "Deep Research Agent",
|
|
132
|
+
description:
|
|
133
|
+
"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.",
|
|
134
|
+
type: AgentType.DEEP_AGENT,
|
|
135
|
+
tools: ["internet_search"],
|
|
136
|
+
prompt: researchInstructions,
|
|
137
|
+
subAgents: ["critique-agent", "research-agent"],
|
|
138
|
+
schema: z.object({
|
|
139
|
+
test: z.string().optional(),
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
128
142
|
{
|
|
129
143
|
key: "research-agent",
|
|
130
144
|
name: "research-agent",
|
|
@@ -142,16 +156,6 @@ const research_agents: AgentConfig[] = [
|
|
|
142
156
|
"Used to critique the final report. Give this agent some infomration about how you want it to critique the report.",
|
|
143
157
|
prompt: subCritiquePrompt,
|
|
144
158
|
},
|
|
145
|
-
{
|
|
146
|
-
key: "main",
|
|
147
|
-
name: "deep_research_agent",
|
|
148
|
-
description:
|
|
149
|
-
"Used to research more in depth questions. Only give this researcher one topic at a time. Do not pass multiple sub questions to this researcher. Instead, you should break down a large topic into the necessary components, and then call multiple research agents in parallel, one for each sub question.",
|
|
150
|
-
type: AgentType.DEEP_AGENT,
|
|
151
|
-
tools: ["internet_search"],
|
|
152
|
-
prompt: researchInstructions,
|
|
153
|
-
subAgents: ["critique-agent", "research-agent"],
|
|
154
|
-
},
|
|
155
159
|
];
|
|
156
160
|
|
|
157
161
|
registerAgentLattices(research_agents);
|
package/src/index.ts
CHANGED
|
@@ -7,11 +7,54 @@ import {
|
|
|
7
7
|
} from "@axiom-lattice/core";
|
|
8
8
|
import "./agents";
|
|
9
9
|
import path from "path";
|
|
10
|
+
// 在文件开头添加
|
|
11
|
+
const PACKAGE_VERSION = require("../package.json").version;
|
|
12
|
+
const BUILD_TIME = new Date().toISOString();
|
|
13
|
+
const IS_DEV = process.env.NODE_ENV !== "production";
|
|
10
14
|
|
|
11
|
-
//
|
|
15
|
+
// 在启动时输出
|
|
16
|
+
console.log(`
|
|
17
|
+
╔═══════════════════════════════════════╗
|
|
18
|
+
║ Lattice Deep Research Server ║
|
|
19
|
+
║ Version: ${PACKAGE_VERSION} ║
|
|
20
|
+
║ Build Time: ${BUILD_TIME} ║
|
|
21
|
+
║ Environment: ${IS_DEV ? "Development" : "Production"} ║
|
|
22
|
+
╚═══════════════════════════════════════╝
|
|
23
|
+
`);
|
|
24
|
+
// Load environment variables
|
|
12
25
|
dotenv.config({ path: path.resolve(__dirname, "../.env") });
|
|
13
26
|
|
|
14
|
-
//
|
|
27
|
+
// Parse command line arguments for port configuration
|
|
28
|
+
function parsePort(): number {
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
const portIndex = args.findIndex((arg) => arg === "--port" || arg === "-p");
|
|
31
|
+
|
|
32
|
+
if (portIndex !== -1 && args[portIndex + 1]) {
|
|
33
|
+
const port = parseInt(args[portIndex + 1], 10);
|
|
34
|
+
if (!isNaN(port) && port > 0 && port < 65536) {
|
|
35
|
+
return port;
|
|
36
|
+
}
|
|
37
|
+
console.warn(
|
|
38
|
+
`Invalid port value: ${args[portIndex + 1]}, using default port 4001`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check environment variable
|
|
43
|
+
if (process.env.PORT) {
|
|
44
|
+
const port = parseInt(process.env.PORT, 10);
|
|
45
|
+
if (!isNaN(port) && port > 0 && port < 65536) {
|
|
46
|
+
return port;
|
|
47
|
+
}
|
|
48
|
+
console.warn(
|
|
49
|
+
`Invalid PORT environment variable: ${process.env.PORT}, using default port 4001`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Default port
|
|
54
|
+
return 4001;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Register default model Lattice
|
|
15
58
|
registerModelLattice(
|
|
16
59
|
"default",
|
|
17
60
|
// {
|
|
@@ -31,12 +74,19 @@ registerModelLattice(
|
|
|
31
74
|
// streaming: false,
|
|
32
75
|
// },
|
|
33
76
|
{
|
|
34
|
-
model: "kimi-k2-
|
|
77
|
+
model: "kimi-k2-250905",
|
|
35
78
|
provider: "volcengine",
|
|
36
79
|
streaming: true,
|
|
37
80
|
apiKeyEnvName: "VOLCENGINE_API_KEY2",
|
|
38
81
|
}
|
|
39
82
|
// {
|
|
83
|
+
// model: "kimi-k2-0711-preview",
|
|
84
|
+
// provider: "openai",
|
|
85
|
+
// streaming: true,
|
|
86
|
+
// apiKeyEnvName: "KIMI_API_KEY",
|
|
87
|
+
// baseURL: "https://api.moonshot.cn/v1",
|
|
88
|
+
// }
|
|
89
|
+
// {
|
|
40
90
|
// model: "qwen-plus",
|
|
41
91
|
// provider: "openai",
|
|
42
92
|
// streaming: false,
|
|
@@ -44,7 +94,12 @@ registerModelLattice(
|
|
|
44
94
|
// baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
45
95
|
// }
|
|
46
96
|
);
|
|
47
|
-
|
|
48
97
|
LatticeGateway.registerLatticeRoutes(LatticeGateway.app);
|
|
49
98
|
|
|
50
|
-
|
|
99
|
+
const port = parsePort();
|
|
100
|
+
console.log(`Starting server on port ${port}`);
|
|
101
|
+
|
|
102
|
+
LatticeGateway.startAsHttpEndpoint({
|
|
103
|
+
port,
|
|
104
|
+
queueServiceConfig: { type: "memory", defaultStartPollingQueue: true },
|
|
105
|
+
});
|
package/tsup.config.ts
ADDED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
# 房产带看助手 (Property Viewing Assistant Agent)
|
|
2
|
-
|
|
3
|
-
## 概述 (Overview)
|
|
4
|
-
|
|
5
|
-
房产带看助手旨在帮助销售人员记录房产带看,通过收集有关客户详情、带看具体信息以及客户对房产的反馈来创建结构化记录。该助手使用 REACT 方法系统地收集信息并生成结构化记录。
|
|
6
|
-
|
|
7
|
-
## 功能 (Functionality)
|
|
8
|
-
|
|
9
|
-
该助手执行以下关键功能:
|
|
10
|
-
|
|
11
|
-
1. 优先收集 6 个必填项,其他信息可选,减少销售人员输入压力
|
|
12
|
-
2. 从销售人员那里收集有关房产带看的全面信息
|
|
13
|
-
3. 识别缺失的必填项并明确提示用户还缺少哪些必填项
|
|
14
|
-
4. 验证必填信息是否符合预期的格式和约束条件
|
|
15
|
-
5. 当所有 6 个必填项收集完毕后生成结构化的 JSON 记录
|
|
16
|
-
6. 将最终提取的数据保存到状态的 final_output 字段中
|
|
17
|
-
|
|
18
|
-
## 数据结构 (Data Structure)
|
|
19
|
-
|
|
20
|
-
助手收集并结构化三个主要类别的数据,按必填项和可选项分类:
|
|
21
|
-
|
|
22
|
-
### 必填信息(6 项核心字段)
|
|
23
|
-
|
|
24
|
-
#### 1. 渠道联系的客户信息和联系方式 (leads)
|
|
25
|
-
|
|
26
|
-
- 客户姓名 (name) ⭐ 必填
|
|
27
|
-
- 联系电话 (phone) ⭐ 必填
|
|
28
|
-
- 来源渠道 (source_channel) ⭐ 必填
|
|
29
|
-
|
|
30
|
-
#### 2. 客户居住计划 (leads)
|
|
31
|
-
|
|
32
|
-
- 计划入住时间 (planned_move_in_date) ⭐ 必填
|
|
33
|
-
- 居住人数 (number_of_people) ⭐ 必填
|
|
34
|
-
- 预算范围(最低和最高)(budget_min, budget_max) ⭐ 必填
|
|
35
|
-
- 意向户型 (preferred_room_types) ⭐ 必填
|
|
36
|
-
- 计划看的其他项目 (other_projects) 可选
|
|
37
|
-
- 客户痛点和主要考虑因素 (pain_points) ⭐ 必填
|
|
38
|
-
|
|
39
|
-
#### 3. 查看的房间信息 (property_viewings)
|
|
40
|
-
|
|
41
|
-
- 带看日期 (viewing_date) ⭐ 必填
|
|
42
|
-
- 查看的房屋 ID 列表 (viewed_property_ids) ⭐ 必填
|
|
43
|
-
- 带看时间 (viewing_time) 可选
|
|
44
|
-
- 带看类型(线下 OFFLINE 或线上 ONLINE)(viewing_type) 可选
|
|
45
|
-
|
|
46
|
-
#### 4. 客户对不同房间的反馈 (property_feedbacks)
|
|
47
|
-
|
|
48
|
-
对于每个看过的房屋:
|
|
49
|
-
|
|
50
|
-
- 房屋 ID (property_id) ⭐ 必填
|
|
51
|
-
- 价格评分 (price_rating, 1-5 分) ⭐ 必填
|
|
52
|
-
- 采光评分 (lighting_rating, 1-5 分) ⭐ 必填
|
|
53
|
-
- 格局评分 (layout_rating, 1-5 分) ⭐ 必填
|
|
54
|
-
- 装修评分 (decoration_rating, 1-5 分) ⭐ 必填
|
|
55
|
-
- 家具配置评分 (furniture_rating, 1-5 分) ⭐ 必填
|
|
56
|
-
- 家电配置评分 (appliances_rating, 1-5 分) ⭐ 必填
|
|
57
|
-
|
|
58
|
-
#### 5. 带看结论 (property_viewings)
|
|
59
|
-
|
|
60
|
-
- 结论类型 (conclusion_type: 已签约 SIGNED、考虑中 CONSIDERING、已关黑 BLACKLISTED) ⭐ 必填
|
|
61
|
-
- 签约的房屋 ID(如适用)(signed_property_id) ⭐ 必填(如果已签约)
|
|
62
|
-
- 关黑原因(如适用)(blacklist_reason) ⭐ 必填(如果已关黑)
|
|
63
|
-
|
|
64
|
-
#### 6. 客户需要考虑的痛点和主因 (leads)
|
|
65
|
-
|
|
66
|
-
- 客户痛点和主要考虑因素 (pain_points) ⭐ 必填
|
|
67
|
-
|
|
68
|
-
### 可选信息
|
|
69
|
-
|
|
70
|
-
以下信息如果客户提到可以记录,但不是必须收集的:
|
|
71
|
-
|
|
72
|
-
- 详细反馈内容 (price_feedback, lighting_feedback, layout_feedback, decoration_feedback, furniture_feedback, appliances_feedback)
|
|
73
|
-
- 总体评分 (overall_rating)
|
|
74
|
-
- 总体反馈 (overall_feedback)
|
|
75
|
-
- 房屋优点 (advantages)
|
|
76
|
-
- 房屋缺点 (disadvantages)
|
|
77
|
-
- 客户兴趣程度 (interest_level)
|
|
78
|
-
- 下次跟进时间 (next_follow_up_date)
|
|
79
|
-
- 是否设置跟进提醒 (follow_up_reminder)
|
|
80
|
-
|
|
81
|
-
## 输出格式 (Output Format)
|
|
82
|
-
|
|
83
|
-
助手生成具有以下格式的结构化 JSON 对象:
|
|
84
|
-
|
|
85
|
-
```json
|
|
86
|
-
{
|
|
87
|
-
"leads": {
|
|
88
|
-
"name": "张三",
|
|
89
|
-
"phone": "13812345678",
|
|
90
|
-
"source_channel": "朋友推荐",
|
|
91
|
-
"planned_move_in_date": "2023-12-01",
|
|
92
|
-
"number_of_people": 3,
|
|
93
|
-
"budget_min": 5000,
|
|
94
|
-
"budget_max": 8000,
|
|
95
|
-
"preferred_room_types": "两室一厅,三室一厅",
|
|
96
|
-
"other_projects": "项目A, 项目B",
|
|
97
|
-
"pain_points": "需要好的学区和安静的环境"
|
|
98
|
-
},
|
|
99
|
-
"property_viewings": {
|
|
100
|
-
"viewing_date": "2023-11-15",
|
|
101
|
-
"viewing_time": "14:30",
|
|
102
|
-
"viewing_type": "OFFLINE",
|
|
103
|
-
"viewed_property_ids": "PROP001,PROP002",
|
|
104
|
-
"conclusion_type": "CONSIDERING",
|
|
105
|
-
"signed_property_id": "",
|
|
106
|
-
"blacklist_reason": "",
|
|
107
|
-
"next_follow_up_date": "2023-11-22",
|
|
108
|
-
"follow_up_reminder": true
|
|
109
|
-
},
|
|
110
|
-
"property_feedbacks": [
|
|
111
|
-
{
|
|
112
|
-
"property_id": "PROP001",
|
|
113
|
-
"price_rating": 4,
|
|
114
|
-
"lighting_rating": 5,
|
|
115
|
-
"layout_rating": 3,
|
|
116
|
-
"decoration_rating": 4,
|
|
117
|
-
"furniture_rating": 3,
|
|
118
|
-
"appliances_rating": 4,
|
|
119
|
-
"price_feedback": "价格对于该区域来说合理",
|
|
120
|
-
"lighting_feedback": "全天采光非常好",
|
|
121
|
-
"layout_feedback": "厨房布局可以改进",
|
|
122
|
-
"decoration_feedback": "现代风格符合偏好",
|
|
123
|
-
"furniture_feedback": "需要更换一些家具",
|
|
124
|
-
"appliances_feedback": "所有家电都是新的且高品质",
|
|
125
|
-
"overall_rating": 4,
|
|
126
|
-
"overall_feedback": "满足大部分需求的好选择",
|
|
127
|
-
"advantages": "位置、设施、自然光",
|
|
128
|
-
"disadvantages": "厨房布局、部分家具不理想",
|
|
129
|
-
"interest_level": "HIGH"
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
"property_id": "PROP002",
|
|
133
|
-
"// 第二个房产的额外反馈...": ""
|
|
134
|
-
}
|
|
135
|
-
]
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## 实现 (Implementation)
|
|
140
|
-
|
|
141
|
-
该助手作为 REACT 类型的代理使用 Axiom Lattice 框架实现。它以对话方式处理用户输入,同时系统地收集所需信息,然后生成最终的结构化输出。
|
|
142
|
-
|
|
143
|
-
## 工具 (Tools)
|
|
144
|
-
|
|
145
|
-
### 更新最终输出工具 (update_final_output)
|
|
146
|
-
|
|
147
|
-
这个工具用于将提取的带看信息数据保存到状态的 final_output 字段中。
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
export const updateFinalOutput = tool(
|
|
151
|
-
(input: { data: Record<string, any> }, config: ToolRunnableConfig) => {
|
|
152
|
-
return new Command({
|
|
153
|
-
update: {
|
|
154
|
-
final_output: input.data,
|
|
155
|
-
messages: [
|
|
156
|
-
new ToolMessage({
|
|
157
|
-
content: `已将提取的数据保存到最终输出`,
|
|
158
|
-
tool_call_id: config.toolCall?.id as string,
|
|
159
|
-
}),
|
|
160
|
-
],
|
|
161
|
-
},
|
|
162
|
-
});
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: "update_final_output",
|
|
166
|
-
description: "将提取的带看信息数据保存到最终输出字段中",
|
|
167
|
-
schema: z.object({
|
|
168
|
-
data: z
|
|
169
|
-
.record(z.any())
|
|
170
|
-
.describe(
|
|
171
|
-
"提取的结构化数据,包含leads、property_viewings和property_feedbacks"
|
|
172
|
-
),
|
|
173
|
-
}),
|
|
174
|
-
}
|
|
175
|
-
);
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
当助手收集完所有必要信息后,它会使用此工具将最终的 JSON 数据保存到系统状态中,以便后续处理或存储。
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
registerAgentLattices,
|
|
5
|
-
AgentType,
|
|
6
|
-
AgentConfig,
|
|
7
|
-
} from "@axiom-lattice/core";
|
|
8
|
-
import "./tools";
|
|
9
|
-
import z from "zod";
|
|
10
|
-
|
|
11
|
-
const propertyViewingAssistantPrompt = `你是一位白居易公司专业的租房带看助手。你的工作是从销售人员那里收集有关租房带看的信息(他可能是语音转文字提供信息的),并提取关键数据点以创建结构化记录到笔记本中,重点关注客户画像、房屋状态和带看反馈,你的工作语言是中文。
|
|
12
|
-
|
|
13
|
-
## 目标
|
|
14
|
-
帮助销售人员记录租房带看,收集以下关键信息:
|
|
15
|
-
1. 客户画像
|
|
16
|
-
2. 房屋状态
|
|
17
|
-
3. 带看反馈
|
|
18
|
-
|
|
19
|
-
## 信息分类与必填标识
|
|
20
|
-
|
|
21
|
-
### 🔴 必填项(带*的为必填项)
|
|
22
|
-
|
|
23
|
-
#### 1. 渠道联系的客户信息和联系方式 (电话号码和微信号至少填写一个)
|
|
24
|
-
- 姓名 (name) *
|
|
25
|
-
- 电话号码 (phone)
|
|
26
|
-
- 来源渠道 (source) * - ONLINE/REFERRAL/WALK_IN/PHONE_CALL/EXHIBITION/ADVERTISEMENT/OTHER
|
|
27
|
-
- 性别 (gender) - MALE/FEMALE
|
|
28
|
-
- 年龄 (age)
|
|
29
|
-
- 微信号 (wechat)
|
|
30
|
-
- 邮箱 (email)
|
|
31
|
-
|
|
32
|
-
#### 2. 客户居住和工作地址
|
|
33
|
-
- 当前居住地址 (currentAddress)
|
|
34
|
-
- 工作地址 (workAddress)
|
|
35
|
-
|
|
36
|
-
#### 3. 客户职业和收入信息
|
|
37
|
-
- 职业 (occupation)
|
|
38
|
-
- 公司名称 (company)
|
|
39
|
-
- 月收入 (monthlyIncome)
|
|
40
|
-
|
|
41
|
-
#### 4. 租房需求和预算
|
|
42
|
-
- 偏好类型 (propertyType) - 如'一居室'、'两居室'、'公寓'、'别墅'等
|
|
43
|
-
- 月租金预算范围(最低和最高)(budgetMin, budgetMax) *
|
|
44
|
-
- 意向区域 (preferredAreas) - 字符串格式
|
|
45
|
-
- 面积范围(最小和最大)(areaMin, areaMax)
|
|
46
|
-
- 房间数量 (roomCount)
|
|
47
|
-
- 租房目的 (rentalPurpose) - SELF_USE/INVESTMENT/SHARED
|
|
48
|
-
- 期望入住日期 (expectedMoveInDate) *
|
|
49
|
-
|
|
50
|
-
#### 5. 客户来源和推荐信息
|
|
51
|
-
- 来源详情 (sourceDetail)
|
|
52
|
-
- 推荐人 (referrer)
|
|
53
|
-
|
|
54
|
-
#### 6. 查看的房间信息和带看安排
|
|
55
|
-
- 带看预约时间 (scheduledAt) * - 标准的日期时间格式ISO 8601,例子:2024-01-25T10:00:35Z
|
|
56
|
-
- 实际带看时间 (actualViewingAt) * - 标准的日期时间格式ISO 8601,例子:2024-01-25T10:00:35Z
|
|
57
|
-
- 带看状态 (status) - SCHEDULED/COMPLETED/CANCELLED
|
|
58
|
-
- 取消原因 (cancellationReason)
|
|
59
|
-
|
|
60
|
-
#### 7. 客户对不同房屋的反馈(租金、采光、格局、配置等)
|
|
61
|
-
- 🔴 针对每个查看的房屋单独收集反馈,必须为每个房屋ID提供完整的反馈信息
|
|
62
|
-
- 房屋ID (propertyId) *
|
|
63
|
-
- 房屋名称 (propertyName)
|
|
64
|
-
- 房屋类型 (roomType)
|
|
65
|
-
- 总体评分 (overallRating) - 1-10分
|
|
66
|
-
- 总体反馈 (overallFeedback) * - 针对该房屋的具体反馈,包括租金、采光、格局、配置等各个方面的评价
|
|
67
|
-
- 房屋优点 (advantages) - 该房屋的具体优点
|
|
68
|
-
- 房屋缺点 (disadvantages) - 该房屋的具体缺点
|
|
69
|
-
|
|
70
|
-
#### 8. 客户状态和跟进信息
|
|
71
|
-
- 客户状态 (status) - NEW/CONTACTED/QUALIFIED/VIEWING/RENTED/LOST
|
|
72
|
-
- 优先级 (priority) - HIGH/MEDIUM/LOW
|
|
73
|
-
- 兴趣评分 (interestScore) - 1-10分
|
|
74
|
-
- 下次跟进时间 (nextFollowUpAt) - 标准的日期时间格式ISO 8601,例子:2024-01-25T10:00:35Z
|
|
75
|
-
- 备注 (notes)
|
|
76
|
-
- 特殊需求 (specialRequirements)
|
|
77
|
-
- 标签 (tags) - 字符串格式
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
## 工作要求
|
|
81
|
-
- 与销售人员交流,收集有关租房带看的信息,优先收集必填项
|
|
82
|
-
- 涉及到看房/预约/下次跟进时间,请使用“获取当前日期时间”工具先了解下当前日期时间
|
|
83
|
-
- 针对每个房屋单独收集反馈:询问销售人员查看了哪些房屋后,逐个房屋收集完整的反馈信息
|
|
84
|
-
- 反馈组织:在 propertyViewing.propertyFeedbacks 数组中记录所有查看房屋的反馈,每个房屋对应一个反馈对象
|
|
85
|
-
- 识别缺失的必要信息并提示补充,明确标注哪些是必填项 *
|
|
86
|
-
- 要做记录时候,请先调用 get_final_output 工具查看当前已存在的数据,然后使用 update_final_output 工具记录到笔记本
|
|
87
|
-
- 无论必填项是否完整,发生对话只要产生了你认为需要收集的信息点,请提取信息并使用 update_final_output 工具记录到笔记本
|
|
88
|
-
- 客户的性别可以通过姓名的称呼来推断,如果能够推断出来,则填写,如果不能推断出来,则不填写
|
|
89
|
-
|
|
90
|
-
## 数据记录策略
|
|
91
|
-
- 带看反馈结构:每个 propertyViewing 对象必须包含 propertyFeedbacks 数组,用于记录该次带看中所有查看房屋的反馈信息到笔记本
|
|
92
|
-
- 枚举值使用:确保使用正确的枚举值,如 gender: "MALE"/"FEMALE", status: "NEW"/"CONTACTED"/"VIEWING"/"RENTED", rentalPurpose: "SELF_USE"/"SHARED"等
|
|
93
|
-
- 如果用户提供的信息中中没有发生带看行为,则不记录带看信息,propertyViewing 对象必须为null
|
|
94
|
-
|
|
95
|
-
## 枚举值定义和描述
|
|
96
|
-
|
|
97
|
-
### 来源渠道 (Source)
|
|
98
|
-
| 枚举值 | 中文翻译 | 描述 |
|
|
99
|
-
|--------|----------|------|
|
|
100
|
-
| ONLINE | 线上 | 线上渠道 |
|
|
101
|
-
| REFERRAL | 推荐 | 客户推荐 |
|
|
102
|
-
| WALK_IN | 上门 | 上门客户 |
|
|
103
|
-
| PHONE_CALL | 电话 | 电话咨询 |
|
|
104
|
-
| EXHIBITION | 展会 | 展会活动 |
|
|
105
|
-
| ADVERTISEMENT | 广告 | 广告宣传 |
|
|
106
|
-
| OTHER | 其他 | 其他渠道 |
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
## 对话指南
|
|
111
|
-
- 交谈时保持对话性但高效地收集信息,优先处理必填项
|
|
112
|
-
- 针对缺失的信息提出具体问题,明确标注是否为必填项
|
|
113
|
-
- 响应用户的时候,请简洁一些,不要过于啰嗦,并具有陪伴用户的感觉
|
|
114
|
-
- 响应用户的时候,请使用中文回答,有些字段是枚举类型的,记录笔记本的时候使用枚举,对用户总结的时候请使用中文回答
|
|
115
|
-
|
|
116
|
-
`;
|
|
117
|
-
|
|
118
|
-
// 工具已在 tools.ts 中注册
|
|
119
|
-
|
|
120
|
-
const property_viewing_agents: AgentConfig[] = [
|
|
121
|
-
{
|
|
122
|
-
key: "main",
|
|
123
|
-
name: "property-viewing-assistant",
|
|
124
|
-
type: AgentType.REACT,
|
|
125
|
-
description:
|
|
126
|
-
"一个租房带看助手,收集有关租房带看的信息,提取关键数据点,并生成结构化记录。",
|
|
127
|
-
prompt: propertyViewingAssistantPrompt,
|
|
128
|
-
tools: ["get_current_date_time", "get_final_output", "update_final_output"],
|
|
129
|
-
schema: z.object({
|
|
130
|
-
final_output: z.record(z.any()),
|
|
131
|
-
}),
|
|
132
|
-
},
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
registerAgentLattices(property_viewing_agents);
|
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import { registerToolLattice } from "@axiom-lattice/core";
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
import { Command, getCurrentTaskInput } from "@langchain/langgraph";
|
|
6
|
-
import { ToolMessage } from "@langchain/core/messages";
|
|
7
|
-
|
|
8
|
-
// Zod schema definitions for property viewing data
|
|
9
|
-
const LeadSchema = z.object({
|
|
10
|
-
name: z
|
|
11
|
-
.string()
|
|
12
|
-
.describe("客户姓名 - 完整的真实姓名,如'张小明'、'李女士'等")
|
|
13
|
-
.optional(),
|
|
14
|
-
gender: z
|
|
15
|
-
.enum(["MALE", "FEMALE"])
|
|
16
|
-
.describe("客户性别 - MALE表示男性,FEMALE表示女性")
|
|
17
|
-
.optional(),
|
|
18
|
-
age: z
|
|
19
|
-
.number()
|
|
20
|
-
.int()
|
|
21
|
-
.describe("客户年龄 - 整数值,通常在18-80岁之间")
|
|
22
|
-
.optional(),
|
|
23
|
-
phone: z
|
|
24
|
-
.string()
|
|
25
|
-
.describe("联系电话 - 手机号码,格式如13812345678或138-1234-5678")
|
|
26
|
-
.optional(),
|
|
27
|
-
wechat: z
|
|
28
|
-
.string()
|
|
29
|
-
.describe("微信号 - 微信账号ID或微信昵称,用于后续联系")
|
|
30
|
-
.optional(),
|
|
31
|
-
email: z
|
|
32
|
-
.string()
|
|
33
|
-
.describe("电子邮箱 - 有效的邮箱地址,格式如example@domain.com")
|
|
34
|
-
.optional(),
|
|
35
|
-
currentAddress: z
|
|
36
|
-
.string()
|
|
37
|
-
.describe("当前居住地址 - 详细的居住地址,包括区域、街道、门牌号等")
|
|
38
|
-
.optional(),
|
|
39
|
-
workAddress: z
|
|
40
|
-
.string()
|
|
41
|
-
.describe("工作地址 - 上班地点的详细地址,用于评估通勤距离")
|
|
42
|
-
.optional(),
|
|
43
|
-
occupation: z
|
|
44
|
-
.string()
|
|
45
|
-
.describe("职业 - 具体的工作职位或行业,如'软件工程师'、'销售经理'等")
|
|
46
|
-
.optional(),
|
|
47
|
-
company: z.string().describe("工作单位 - 公司名称或机构名称").optional(),
|
|
48
|
-
monthlyIncome: z
|
|
49
|
-
.number()
|
|
50
|
-
.describe("月收入 - 税前月收入金额,单位为人民币元")
|
|
51
|
-
.optional(),
|
|
52
|
-
propertyType: z
|
|
53
|
-
.string()
|
|
54
|
-
.describe("房屋类型偏好 - 如'一居室'、'两居室'、'公寓'、'别墅'等")
|
|
55
|
-
.optional(),
|
|
56
|
-
budgetMin: z
|
|
57
|
-
.number()
|
|
58
|
-
.describe("预算下限 - 最低可接受的租金或房价,单位为人民币元")
|
|
59
|
-
.optional(),
|
|
60
|
-
budgetMax: z
|
|
61
|
-
.number()
|
|
62
|
-
.describe("预算上限 - 最高可接受的租金或房价,单位为人民币元")
|
|
63
|
-
.optional(),
|
|
64
|
-
preferredAreas: z
|
|
65
|
-
.string()
|
|
66
|
-
.describe("偏好区域 - 希望居住的区域或地段,可以是多个区域的描述")
|
|
67
|
-
.optional(),
|
|
68
|
-
areaMin: z
|
|
69
|
-
.number()
|
|
70
|
-
.describe("面积需求下限 - 最小可接受的房屋面积,单位为平方米")
|
|
71
|
-
.optional(),
|
|
72
|
-
areaMax: z
|
|
73
|
-
.number()
|
|
74
|
-
.describe("面积需求上限 - 最大可接受的房屋面积,单位为平方米")
|
|
75
|
-
.optional(),
|
|
76
|
-
roomCount: z
|
|
77
|
-
.number()
|
|
78
|
-
.int()
|
|
79
|
-
.describe("房间数量要求 - 需要的房间数量,如1表示一居室,2表示两居室等")
|
|
80
|
-
.optional(),
|
|
81
|
-
purchasePurpose: z
|
|
82
|
-
.enum(["SELF_USE", "SHARED"])
|
|
83
|
-
.describe("租住目的 - SELF_USE表示自住,SHARED表示合租或共享")
|
|
84
|
-
.optional(),
|
|
85
|
-
expectedPurchaseDate: z
|
|
86
|
-
.string()
|
|
87
|
-
.describe(
|
|
88
|
-
"期望入住时间 - 客户希望的入住日期或时间范围,格式如'2024年3月'或具体日期"
|
|
89
|
-
)
|
|
90
|
-
.optional(),
|
|
91
|
-
source: z
|
|
92
|
-
.enum([
|
|
93
|
-
"ONLINE",
|
|
94
|
-
"REFERRAL",
|
|
95
|
-
"WALK_IN",
|
|
96
|
-
"PHONE_CALL",
|
|
97
|
-
"EXHIBITION",
|
|
98
|
-
"ADVERTISEMENT",
|
|
99
|
-
"OTHER",
|
|
100
|
-
])
|
|
101
|
-
.describe(
|
|
102
|
-
"客户来源渠道 - ONLINE线上渠道, REFERRAL客户推荐, WALK_IN上门客户, PHONE_CALL电话咨询, EXHIBITION展会活动, ADVERTISEMENT广告宣传, OTHER其他渠道"
|
|
103
|
-
)
|
|
104
|
-
.optional(),
|
|
105
|
-
sourceDetail: z
|
|
106
|
-
.string()
|
|
107
|
-
.describe("来源详情 - 具体的来源信息,如'58同城'、'链家网'、'张三介绍'等")
|
|
108
|
-
.optional(),
|
|
109
|
-
referrer: z
|
|
110
|
-
.string()
|
|
111
|
-
.describe("推荐人 - 介绍该客户的具体人员姓名或联系方式")
|
|
112
|
-
.optional(),
|
|
113
|
-
status: z
|
|
114
|
-
.enum(["NEW", "CONTACTED", "VIEWING", "RENTED"])
|
|
115
|
-
.describe(
|
|
116
|
-
"客户状态 - NEW新客户,CONTACTED已联系,VIEWING看房中,RENTED已成交"
|
|
117
|
-
)
|
|
118
|
-
.optional(),
|
|
119
|
-
priority: z
|
|
120
|
-
.string()
|
|
121
|
-
.describe("优先级 - 客户的重要程度或跟进优先级,如'高'、'中'、'低'")
|
|
122
|
-
.optional(),
|
|
123
|
-
interestScore: z
|
|
124
|
-
.number()
|
|
125
|
-
.int()
|
|
126
|
-
.min(1)
|
|
127
|
-
.max(10)
|
|
128
|
-
.describe("意向评分 - 客户购买意向强度评分,1分最低,10分最高")
|
|
129
|
-
.optional(),
|
|
130
|
-
firstContactAt: z
|
|
131
|
-
.string()
|
|
132
|
-
.describe(
|
|
133
|
-
"首次联系时间 - 与客户第一次接触的具体时间,标准ISO 8601格式,例:2024-01-25T10:00:35Z"
|
|
134
|
-
)
|
|
135
|
-
.optional(),
|
|
136
|
-
nextFollowUpAt: z
|
|
137
|
-
.string()
|
|
138
|
-
.describe(
|
|
139
|
-
"下次跟进时间 - 计划下次联系客户的时间,标准ISO 8601格式,例:2024-01-25T10:00:35Z"
|
|
140
|
-
)
|
|
141
|
-
.optional(),
|
|
142
|
-
notes: z
|
|
143
|
-
.string()
|
|
144
|
-
.describe("客户备注 - 关于客户的详细备注信息,包括沟通记录、特殊情况等")
|
|
145
|
-
.optional(),
|
|
146
|
-
specialRequirements: z
|
|
147
|
-
.string()
|
|
148
|
-
.describe("特殊需求 - 客户的特殊要求或条件,如'需要停车位'、'宠物友好'等")
|
|
149
|
-
.optional(),
|
|
150
|
-
tags: z
|
|
151
|
-
.string()
|
|
152
|
-
.describe(
|
|
153
|
-
"客户标签 - 用于分类的标签,如'VIP客户'、'首次购房'、'投资客户'等"
|
|
154
|
-
)
|
|
155
|
-
.optional(),
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const PropertyFeedbackSchema = z.object({
|
|
159
|
-
// leadId: z.number().int().describe("Lead ID").optional(),
|
|
160
|
-
// viewingId: z.number().int().describe("Viewing record ID").optional(),
|
|
161
|
-
propertyId: z
|
|
162
|
-
.string()
|
|
163
|
-
.describe("房源编号 - 房屋的唯一标识符或房间号,如'A001'、'1栋2单元301'等")
|
|
164
|
-
.optional(),
|
|
165
|
-
propertyName: z
|
|
166
|
-
.string()
|
|
167
|
-
.describe("房源名称 - 房屋项目名称或具体地址描述,用于记录和核实房源信息")
|
|
168
|
-
.optional(),
|
|
169
|
-
roomType: z
|
|
170
|
-
.string()
|
|
171
|
-
.describe(
|
|
172
|
-
"房型 - 房屋户型描述,如'一居室'、'两室一厅'、'三室两厅两卫'、'Loft'等"
|
|
173
|
-
)
|
|
174
|
-
.optional(),
|
|
175
|
-
overallRating: z
|
|
176
|
-
.number()
|
|
177
|
-
.int()
|
|
178
|
-
.min(1)
|
|
179
|
-
.max(10)
|
|
180
|
-
.describe(
|
|
181
|
-
"整体满意度评分 - 客户对该房源的总体满意程度,1分最不满意,10分最满意"
|
|
182
|
-
)
|
|
183
|
-
.optional(),
|
|
184
|
-
overallFeedback: z
|
|
185
|
-
.string()
|
|
186
|
-
.describe("整体反馈 - 客户对房源的总体评价和感受的详细描述")
|
|
187
|
-
.optional(),
|
|
188
|
-
advantages: z
|
|
189
|
-
.string()
|
|
190
|
-
.describe(
|
|
191
|
-
"房源优点 - 客户认为该房源的优势和亮点,如位置好、装修新、采光佳等"
|
|
192
|
-
)
|
|
193
|
-
.optional(),
|
|
194
|
-
disadvantages: z
|
|
195
|
-
.string()
|
|
196
|
-
.describe("房源缺点 - 客户指出的房源不足之处,如噪音大、楼层高、设施老旧等")
|
|
197
|
-
.optional(),
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const PropertyViewingSchema = z.object({
|
|
201
|
-
// id: z
|
|
202
|
-
// .number()
|
|
203
|
-
// .int()
|
|
204
|
-
// .describe("Viewing record ID (if exists, update; if not, create)")
|
|
205
|
-
// .optional(),
|
|
206
|
-
// aiThreadId: z.string().describe("AI thread ID").optional(),
|
|
207
|
-
// leadId: z.number().int().describe("Lead ID").optional(),
|
|
208
|
-
// agentId: z.number().int().describe("Viewing agent ID").optional(),
|
|
209
|
-
scheduledAt: z
|
|
210
|
-
.string()
|
|
211
|
-
.describe(
|
|
212
|
-
"预约看房时间 - 计划的看房时间,标准ISO 8601格式,例:2024-01-25T14:00:00Z"
|
|
213
|
-
)
|
|
214
|
-
.optional(),
|
|
215
|
-
actualViewingAt: z
|
|
216
|
-
.string()
|
|
217
|
-
.describe(
|
|
218
|
-
"实际看房时间 - 真实发生的看房时间,标准ISO 8601格式,可能与预约时间不同"
|
|
219
|
-
)
|
|
220
|
-
.optional(),
|
|
221
|
-
status: z
|
|
222
|
-
.string()
|
|
223
|
-
.describe(
|
|
224
|
-
"看房状态 - 当前看房记录的状态,如'已预约'、'进行中'、'已完成'、'已取消'等"
|
|
225
|
-
)
|
|
226
|
-
.optional(),
|
|
227
|
-
cancellationReason: z
|
|
228
|
-
.string()
|
|
229
|
-
.describe(
|
|
230
|
-
"取消原因 - 如果看房被取消,记录具体的取消原因,如'客户临时有事'、'房源不可用'等"
|
|
231
|
-
)
|
|
232
|
-
.optional(),
|
|
233
|
-
notes: z
|
|
234
|
-
.string()
|
|
235
|
-
.describe(
|
|
236
|
-
"看房备注 - 看房过程中的详细记录,包括客户反应、沟通要点、注意事项等"
|
|
237
|
-
)
|
|
238
|
-
.optional(),
|
|
239
|
-
propertyFeedbacks: z
|
|
240
|
-
.array(PropertyFeedbackSchema)
|
|
241
|
-
.describe(
|
|
242
|
-
"房源反馈列表 - 客户对本次看房中所有房源的详细反馈评价,将替换所有现有反馈记录"
|
|
243
|
-
)
|
|
244
|
-
.optional(),
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const PropertyViewingDataSchema = z.object({
|
|
248
|
-
leads: LeadSchema.describe(
|
|
249
|
-
"客户线索信息 - 包含客户的基本信息、联系方式、需求偏好等完整客户档案"
|
|
250
|
-
),
|
|
251
|
-
propertyViewing: PropertyViewingSchema.optional().describe(
|
|
252
|
-
"看房记录信息 - 客户看房活动的详细记录,包括时间安排、状态跟踪和房源反馈等"
|
|
253
|
-
),
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* 读取最终输出工具 - 获取已保存的最终输出数据
|
|
258
|
-
*/
|
|
259
|
-
registerToolLattice(
|
|
260
|
-
"get_final_output",
|
|
261
|
-
{
|
|
262
|
-
name: "get_final_output",
|
|
263
|
-
description: "获取当前保存的最终输出数据,用于查看或验证已收集的信息",
|
|
264
|
-
schema: z.object({}),
|
|
265
|
-
},
|
|
266
|
-
async (input: {}, config: any) => {
|
|
267
|
-
// 从配置中获取当前状态的 final_output
|
|
268
|
-
|
|
269
|
-
const state =
|
|
270
|
-
getCurrentTaskInput<z.infer<z.ZodObject<any, any, any, any, any>>>();
|
|
271
|
-
|
|
272
|
-
const final_output = state?.final_output;
|
|
273
|
-
|
|
274
|
-
if (!final_output || Object.keys(final_output).length === 0) {
|
|
275
|
-
return new Command({
|
|
276
|
-
update: {
|
|
277
|
-
messages: [
|
|
278
|
-
new ToolMessage({
|
|
279
|
-
content: `暂无保存的最终输出数据,请先收集并保存带看信息。`,
|
|
280
|
-
tool_call_id: config.toolCall?.id as string,
|
|
281
|
-
}),
|
|
282
|
-
],
|
|
283
|
-
},
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// 直接返回 JSON 格式
|
|
288
|
-
const content = JSON.stringify(state.final_output, null, 2);
|
|
289
|
-
return new Command({
|
|
290
|
-
update: {
|
|
291
|
-
messages: [
|
|
292
|
-
new ToolMessage({
|
|
293
|
-
content: content,
|
|
294
|
-
tool_call_id: config.toolCall?.id as string,
|
|
295
|
-
}),
|
|
296
|
-
],
|
|
297
|
-
},
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* 更新最终输出工具 - 将提取的数据保存到状态中
|
|
304
|
-
*/
|
|
305
|
-
registerToolLattice(
|
|
306
|
-
"update_final_output",
|
|
307
|
-
{
|
|
308
|
-
name: "update_final_output",
|
|
309
|
-
description:
|
|
310
|
-
"将提取的带看信息数据保存到最终输出字段中 - 用于将从对话中提取并结构化的客户信息和看房记录保存到系统中,确保所有重要信息都被准确记录和存储",
|
|
311
|
-
schema: z.object({
|
|
312
|
-
data: PropertyViewingDataSchema.describe(
|
|
313
|
-
"提取的结构化数据 - 完整的客户带看信息,包含客户基本资料(leads)、看房安排记录(propertyViewing)和具体房源反馈(propertyFeedbacks),所有数据将按照规范格式保存"
|
|
314
|
-
),
|
|
315
|
-
}),
|
|
316
|
-
},
|
|
317
|
-
async (
|
|
318
|
-
input: { data: z.infer<typeof PropertyViewingDataSchema> },
|
|
319
|
-
config: any
|
|
320
|
-
) => {
|
|
321
|
-
const state =
|
|
322
|
-
getCurrentTaskInput<z.infer<z.ZodObject<any, any, any, any, any>>>();
|
|
323
|
-
const leadId = state?.final_output?.leads?.id;
|
|
324
|
-
const viewingId = state?.final_output?.propertyViewing?.id;
|
|
325
|
-
const finalOutput: any = input.data;
|
|
326
|
-
if (leadId && finalOutput.leads) {
|
|
327
|
-
finalOutput.leads.id = leadId;
|
|
328
|
-
}
|
|
329
|
-
if (viewingId && finalOutput.propertyViewing) {
|
|
330
|
-
finalOutput.propertyViewing.id = viewingId;
|
|
331
|
-
finalOutput.propertyViewing.leadId = leadId;
|
|
332
|
-
}
|
|
333
|
-
return new Command({
|
|
334
|
-
update: {
|
|
335
|
-
// files: {
|
|
336
|
-
final_output: finalOutput,
|
|
337
|
-
// },
|
|
338
|
-
messages: [
|
|
339
|
-
new ToolMessage({
|
|
340
|
-
content: `已将提取的数据保存到最终输出`,
|
|
341
|
-
tool_call_id: config.toolCall?.id as string,
|
|
342
|
-
}),
|
|
343
|
-
],
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
);
|
package/src/agents/todo/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AgentConfig,
|
|
3
|
-
AgentType,
|
|
4
|
-
registerAgentLattice,
|
|
5
|
-
} from "@axiom-lattice/core";
|
|
6
|
-
import "./tools/read_todo_list";
|
|
7
|
-
import "./tools/create_todo_item";
|
|
8
|
-
|
|
9
|
-
export const TODO_AGENT_NAME = "maintodo";
|
|
10
|
-
|
|
11
|
-
const todo_agent_definition: AgentConfig = {
|
|
12
|
-
key: "todo",
|
|
13
|
-
type: AgentType.PLAN_EXECUTE,
|
|
14
|
-
name: TODO_AGENT_NAME,
|
|
15
|
-
description: "todo_agent可以分析用户的输入,整理并生成待办事项",
|
|
16
|
-
prompt:
|
|
17
|
-
"你是一个todo助手,请根据用户输入生成待办事项,每次生成待办时都需要用户进行确认,而且需要先查询下待办列表,再根据待办列表生成待办事项",
|
|
18
|
-
tools: ["读取待办列表", "创建待办事项", "获取当前日期时间"],
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
registerAgentLattice(todo_agent_definition);
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { registerToolLattice } from "@axiom-lattice/core";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
registerToolLattice(
|
|
5
|
-
"create_todo_item",
|
|
6
|
-
{
|
|
7
|
-
name: "创建待办事项",
|
|
8
|
-
description: "创建待办事项",
|
|
9
|
-
needUserApprove: true,
|
|
10
|
-
schema: z.object({
|
|
11
|
-
title: z.string(),
|
|
12
|
-
description: z.string().nullable(),
|
|
13
|
-
due_date: z.string().nullable(),
|
|
14
|
-
priority: z.string().nullable(),
|
|
15
|
-
status: z.string().nullable(),
|
|
16
|
-
tags: z.array(z.string()).nullable(),
|
|
17
|
-
category: z.string().nullable(),
|
|
18
|
-
}),
|
|
19
|
-
},
|
|
20
|
-
async (
|
|
21
|
-
input: {
|
|
22
|
-
title: string;
|
|
23
|
-
description: string;
|
|
24
|
-
due_date: string;
|
|
25
|
-
priority: string;
|
|
26
|
-
status: string;
|
|
27
|
-
tags: string[];
|
|
28
|
-
},
|
|
29
|
-
config: any
|
|
30
|
-
) => {
|
|
31
|
-
(globalThis as any)["todo_list"].push(input);
|
|
32
|
-
|
|
33
|
-
return genUIMarkdown("todo_item_view", input);
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
(globalThis as any)["todo_list"] = [];
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { registerToolLattice } from "@core/tool_lattice/ToolLatticeManager";
|
|
2
|
-
import { genUIMarkdown } from "@core/util/genUIMarkdown";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
|
|
5
|
-
registerToolLattice(
|
|
6
|
-
"read_todo_list",
|
|
7
|
-
{
|
|
8
|
-
name: "读取待办列表",
|
|
9
|
-
description: "读取待办事项列表",
|
|
10
|
-
schema: z.object({
|
|
11
|
-
search_text: z.string().optional().nullable(),
|
|
12
|
-
}),
|
|
13
|
-
},
|
|
14
|
-
async (input: { search_text: string }) => {
|
|
15
|
-
const md = genUIMarkdown("generic_data_table", {
|
|
16
|
-
dataSource: (globalThis as any)["todo_list"],
|
|
17
|
-
message: "待办事项列表",
|
|
18
|
-
});
|
|
19
|
-
console.log(md);
|
|
20
|
-
return md;
|
|
21
|
-
}
|
|
22
|
-
);
|