generated from tailored/router-template
update
This commit is contained in:
parent
a150cbc533
commit
ce7cd03cb3
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,3 +15,5 @@ logs
|
|||||||
|
|
||||||
.env*
|
.env*
|
||||||
!.env.example
|
!.env.example
|
||||||
|
|
||||||
|
.turbo
|
@ -18,6 +18,7 @@
|
|||||||
"build": "rimraf dist && bun run bun.config.mjs",
|
"build": "rimraf dist && bun run bun.config.mjs",
|
||||||
"test": "tsx test/**/*.ts",
|
"test": "tsx test/**/*.ts",
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
|
"turbo:build": "turbo run build",
|
||||||
"pub": "npm run build && envision pack -p -u",
|
"pub": "npm run build && envision pack -p -u",
|
||||||
"cmd": "tsx cmd/index.ts "
|
"cmd": "tsx cmd/index.ts "
|
||||||
},
|
},
|
||||||
@ -34,7 +35,7 @@
|
|||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kevisual/ai": "^0.0.6",
|
"@kevisual/ai": "^0.0.8",
|
||||||
"@kevisual/code-center-module": "0.0.23",
|
"@kevisual/code-center-module": "0.0.23",
|
||||||
"@kevisual/context": "^0.0.3",
|
"@kevisual/context": "^0.0.3",
|
||||||
"@kevisual/router": "0.0.23",
|
"@kevisual/router": "0.0.23",
|
||||||
@ -47,6 +48,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/app-assistant": "workspace:*",
|
"@kevisual/app-assistant": "workspace:*",
|
||||||
|
"@kevisual/logger": "^0.0.4",
|
||||||
"@kevisual/social-prompts": "workspace:*",
|
"@kevisual/social-prompts": "workspace:*",
|
||||||
"@kevisual/types": "^0.0.10",
|
"@kevisual/types": "^0.0.10",
|
||||||
"@kevisual/use-config": "^1.0.19",
|
"@kevisual/use-config": "^1.0.19",
|
||||||
@ -56,7 +58,7 @@
|
|||||||
"@types/formidable": "^3.4.5",
|
"@types/formidable": "^3.4.5",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^24.0.3",
|
"@types/node": "^24.0.3",
|
||||||
"bullmq": "^5.54.3",
|
"bullmq": "^5.55.0",
|
||||||
"commander": "^14.0.0",
|
"commander": "^14.0.0",
|
||||||
"concurrently": "^9.1.2",
|
"concurrently": "^9.1.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
@ -64,6 +66,7 @@
|
|||||||
"inquire": "^0.4.8",
|
"inquire": "^0.4.8",
|
||||||
"ioredis": "^5.6.1",
|
"ioredis": "^5.6.1",
|
||||||
"nodemon": "^3.1.10",
|
"nodemon": "^3.1.10",
|
||||||
|
"openai": "^5.6.0",
|
||||||
"pg": "^8.16.2",
|
"pg": "^8.16.2",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"sequelize": "^6.37.7",
|
"sequelize": "^6.37.7",
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"types": "app.d.ts",
|
"types": "app.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "bun run bun.config.mjs",
|
"build": "bun run bun.config.mjs",
|
||||||
"postbuild": "dts -i src/index.ts -o app.d.ts",
|
"postbuild2": "dts -i src/index.ts -o app.d.ts",
|
||||||
"cmd": "tsx src/test/command.ts ",
|
"cmd": "tsx src/test/command.ts ",
|
||||||
"dts": "dts -i src/index.js -o app.d.ts"
|
"dts": "dts -i src/index.js -o app.d.ts"
|
||||||
},
|
},
|
||||||
|
@ -75,17 +75,31 @@ app
|
|||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { note_id, comment_id, content } = ctx.query;
|
const { note_id, comment_id, content } = ctx.query;
|
||||||
const client = xhsServices.getClient();
|
const client = xhsServices.getClient();
|
||||||
const res = await client.postComment({
|
// content 300个字内,超过cai fen
|
||||||
note_id: note_id,
|
const textArr: string[] = [];
|
||||||
comment_id: comment_id,
|
if (content.length > 300) {
|
||||||
content,
|
const num = Math.ceil(content.length / 300);
|
||||||
});
|
for (let i = 0; i < num; i++) {
|
||||||
if (res.code === 0) {
|
textArr.push(content.slice(i * 300, (i + 1) * 300));
|
||||||
ctx.body = res.data;
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('添加评论失败', res.code);
|
textArr.push(content);
|
||||||
ctx.throw(res.code, '添加评论失败');
|
|
||||||
}
|
}
|
||||||
|
const resArr: any[] = [];
|
||||||
|
for (const text of textArr) {
|
||||||
|
const res = await client.postComment({
|
||||||
|
note_id: note_id,
|
||||||
|
comment_id: comment_id,
|
||||||
|
content: text,
|
||||||
|
});
|
||||||
|
if (res.code === 0) {
|
||||||
|
resArr.push(res.data);
|
||||||
|
} else {
|
||||||
|
console.log('添加评论失败', res.code);
|
||||||
|
ctx.throw(res.code, '添加评论失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.body = resArr;
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
app
|
app
|
||||||
|
43
pnpm-lock.yaml
generated
43
pnpm-lock.yaml
generated
@ -9,8 +9,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/ai':
|
'@kevisual/ai':
|
||||||
specifier: ^0.0.6
|
specifier: ^0.0.8
|
||||||
version: 0.0.6
|
version: 0.0.8
|
||||||
'@kevisual/code-center-module':
|
'@kevisual/code-center-module':
|
||||||
specifier: 0.0.23
|
specifier: 0.0.23
|
||||||
version: 0.0.23(dotenv@16.5.0)
|
version: 0.0.23(dotenv@16.5.0)
|
||||||
@ -42,6 +42,9 @@ importers:
|
|||||||
'@kevisual/app-assistant':
|
'@kevisual/app-assistant':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:packages/app-assistant
|
version: link:packages/app-assistant
|
||||||
|
'@kevisual/logger':
|
||||||
|
specifier: ^0.0.4
|
||||||
|
version: 0.0.4
|
||||||
'@kevisual/social-prompts':
|
'@kevisual/social-prompts':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:packages/social-prompts
|
version: link:packages/social-prompts
|
||||||
@ -67,8 +70,8 @@ importers:
|
|||||||
specifier: ^24.0.3
|
specifier: ^24.0.3
|
||||||
version: 24.0.3
|
version: 24.0.3
|
||||||
bullmq:
|
bullmq:
|
||||||
specifier: ^5.54.3
|
specifier: ^5.55.0
|
||||||
version: 5.54.3
|
version: 5.55.0
|
||||||
commander:
|
commander:
|
||||||
specifier: ^14.0.0
|
specifier: ^14.0.0
|
||||||
version: 14.0.0
|
version: 14.0.0
|
||||||
@ -90,6 +93,9 @@ importers:
|
|||||||
nodemon:
|
nodemon:
|
||||||
specifier: ^3.1.10
|
specifier: ^3.1.10
|
||||||
version: 3.1.10
|
version: 3.1.10
|
||||||
|
openai:
|
||||||
|
specifier: ^5.6.0
|
||||||
|
version: 5.6.0(ws@8.18.1)(zod@3.25.67)
|
||||||
pg:
|
pg:
|
||||||
specifier: ^8.16.2
|
specifier: ^8.16.2
|
||||||
version: 8.16.2
|
version: 8.16.2
|
||||||
@ -215,8 +221,8 @@ packages:
|
|||||||
'@jridgewell/sourcemap-codec@1.5.0':
|
'@jridgewell/sourcemap-codec@1.5.0':
|
||||||
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
||||||
|
|
||||||
'@kevisual/ai@0.0.6':
|
'@kevisual/ai@0.0.8':
|
||||||
resolution: {integrity: sha512-khTCGsDMjGL9VN8ZB2HzEPUXcSTHu1fHXKBRmyojxy9gt+lMCx7JFgqLKiENkekOUwS2Xg6Fe5jwQDNJRwGwDA==}
|
resolution: {integrity: sha512-MvK4U1iWf8hz7lj/+YBQV3qWRRDy42VH8fInKFVxjpEGPGaxfXOMP73C85T4Cf82OGU/fxOayiR0xLi2SyBTLw==}
|
||||||
|
|
||||||
'@kevisual/auth@1.0.5':
|
'@kevisual/auth@1.0.5':
|
||||||
resolution: {integrity: sha512-GwsLj7unKXi7lmMiIIgdig4LwwLiDJnOy15HHZR5gMbyK6s5/uJiMY5RXPB2+onGzTNDqFo/hXjsD2wkerHPVg==}
|
resolution: {integrity: sha512-GwsLj7unKXi7lmMiIIgdig4LwwLiDJnOy15HHZR5gMbyK6s5/uJiMY5RXPB2+onGzTNDqFo/hXjsD2wkerHPVg==}
|
||||||
@ -574,8 +580,8 @@ packages:
|
|||||||
bullmq@5.51.1:
|
bullmq@5.51.1:
|
||||||
resolution: {integrity: sha512-JEZokH5Sb6p66HRjbfQjPNYuSilDRcB8UREmJzOBqTTaJFza8I92vsBF3J/zmtzd7KVv3dxhZyH9CYSLOJALRA==}
|
resolution: {integrity: sha512-JEZokH5Sb6p66HRjbfQjPNYuSilDRcB8UREmJzOBqTTaJFza8I92vsBF3J/zmtzd7KVv3dxhZyH9CYSLOJALRA==}
|
||||||
|
|
||||||
bullmq@5.54.3:
|
bullmq@5.55.0:
|
||||||
resolution: {integrity: sha512-MVK2pOkB3hvrIcubwI8dS4qWHJLNKakKPpgRBTw91sIpPZArmvZ4t2hvryyEaJXJbAS/JHd6pKYOUd+RGRkWQQ==}
|
resolution: {integrity: sha512-LKaQZroyXBYSQd/SNP9EcmCZgiZjIImtQHBlnupUvhX1GmmJfIXjn0bf8lek3bvajMUbvVf8FrYdFD0ajAuy0g==}
|
||||||
|
|
||||||
bun-types@1.2.16:
|
bun-types@1.2.16:
|
||||||
resolution: {integrity: sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A==}
|
resolution: {integrity: sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A==}
|
||||||
@ -1458,6 +1464,18 @@ packages:
|
|||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
|
||||||
|
openai@5.6.0:
|
||||||
|
resolution: {integrity: sha512-jNH5z+hYAdOMZXyEt0yZ7246s+UZjg2AwFQqkAhZIPPjxNtHHO5mykOefau6FkOqj16aC94MOdJl/rZBcKj/cQ==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
ws: ^8.18.0
|
||||||
|
zod: ^3.23.8
|
||||||
|
peerDependenciesMeta:
|
||||||
|
ws:
|
||||||
|
optional: true
|
||||||
|
zod:
|
||||||
|
optional: true
|
||||||
|
|
||||||
own-keys@1.0.1:
|
own-keys@1.0.1:
|
||||||
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
|
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -2182,7 +2200,7 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.0': {}
|
'@jridgewell/sourcemap-codec@1.5.0': {}
|
||||||
|
|
||||||
'@kevisual/ai@0.0.6':
|
'@kevisual/ai@0.0.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@kevisual/logger': 0.0.4
|
'@kevisual/logger': 0.0.4
|
||||||
|
|
||||||
@ -2550,7 +2568,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
bullmq@5.54.3:
|
bullmq@5.55.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cron-parser: 4.9.0
|
cron-parser: 4.9.0
|
||||||
ioredis: 5.6.1
|
ioredis: 5.6.1
|
||||||
@ -3629,6 +3647,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
|
|
||||||
|
openai@5.6.0(ws@8.18.1)(zod@3.25.67):
|
||||||
|
optionalDependencies:
|
||||||
|
ws: 8.18.1
|
||||||
|
zod: 3.25.67
|
||||||
|
|
||||||
own-keys@1.0.1:
|
own-keys@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.2.7
|
||||||
|
3
src/agent/agent.ts
Normal file
3
src/agent/agent.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { QueryRouterServer } from '@kevisual/router';
|
||||||
|
|
||||||
|
export const agent = new QueryRouterServer();
|
16
src/agent/ai.ts
Normal file
16
src/agent/ai.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { SiliconFlowProvider } from '@kevisual/ai';
|
||||||
|
import { config } from '../modules/config.ts';
|
||||||
|
|
||||||
|
export const ai = new SiliconFlowProvider({
|
||||||
|
model: 'Qwen/Qwen3-32B',
|
||||||
|
// model: 'Pro/deepseek-ai/DeepSeek-R1',// 只有充值能用
|
||||||
|
apiKey: config.SILICONFLOW_API_KEY,
|
||||||
|
});
|
||||||
|
|
||||||
|
ai.getUsageInfo()
|
||||||
|
.then((usage) => {
|
||||||
|
console.log('AI usage info:', usage);
|
||||||
|
})
|
||||||
|
.catch((res) => {
|
||||||
|
console.error('Error fetching AI usage info:', res.status);
|
||||||
|
});
|
95
src/agent/analyze/content.ts
Normal file
95
src/agent/analyze/content.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { agent } from '@/agent/agent.ts';
|
||||||
|
import { ai } from '../ai.ts';
|
||||||
|
import { logger } from '@/agent/logger.ts';
|
||||||
|
const getJsonFromString = (str: string) => {
|
||||||
|
// 尝试从字符串中提取JSON对象
|
||||||
|
try {
|
||||||
|
const jsonMatch = str.match(/```json\s*([\s\S]*?)\s*```/);
|
||||||
|
if (jsonMatch && jsonMatch[1]) {
|
||||||
|
return JSON.parse(jsonMatch[1]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing JSON from string:', error);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
agent
|
||||||
|
.route({
|
||||||
|
path: 'analyze',
|
||||||
|
key: 'content',
|
||||||
|
description: '分析文本内容,意图分析,判断是否需要获取上下文包函小红书的图片,视频,文本。',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const text = ctx.query?.text || '';
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
image: false,
|
||||||
|
video: false,
|
||||||
|
text: false,
|
||||||
|
comment: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const prompt = `
|
||||||
|
请分析<context>包函的内容,判断是否需要包含小红书的图片、视频或文本信息,返回一个JSON对象,包含三个布尔值:image(是否包含图片)、video(是否包含视频)、text(是否包含小红书文本),comment(是否是评论信息)。
|
||||||
|
如果文本中提到图片或视频,请返回true,否则返回false。
|
||||||
|
|
||||||
|
文本示例:
|
||||||
|
1. "解答一下这个笔记。" , text为true
|
||||||
|
2. "分析一下这个图片。", image为true
|
||||||
|
3. "这个视频介绍的是什么。", video为true
|
||||||
|
4. "评价一下这个评论。", comment为true
|
||||||
|
|
||||||
|
返回内容示例:
|
||||||
|
\`\`\`json
|
||||||
|
{
|
||||||
|
"image": true,
|
||||||
|
"video": false,
|
||||||
|
"text": true,
|
||||||
|
"comment": false
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
分析的文本的内容是:
|
||||||
|
<context>
|
||||||
|
${text}
|
||||||
|
</context>
|
||||||
|
`;
|
||||||
|
const now = Date.now();
|
||||||
|
console.log('start');
|
||||||
|
const res = await ai
|
||||||
|
.chat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: prompt,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
enable_thinking: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log('AI service error:', err.status);
|
||||||
|
ctx.throw(500, 'AI service error: ' + err.status);
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('end', Date.now() - now, 'ms');
|
||||||
|
const ans = res.choices[0]?.message?.content || '';
|
||||||
|
if (!ans) {
|
||||||
|
logger.error('Empty response from AI:', res);
|
||||||
|
}
|
||||||
|
const json = getJsonFromString(ans);
|
||||||
|
if (!json) {
|
||||||
|
logger.error('Invalid JSON format in response:', ans);
|
||||||
|
ctx.throw(400, 'Invalid JSON format in response');
|
||||||
|
}
|
||||||
|
result = {
|
||||||
|
image: json.image || false,
|
||||||
|
video: json.video || false,
|
||||||
|
text: json.text || false,
|
||||||
|
comment: json.comment || false,
|
||||||
|
};
|
||||||
|
ctx.body = result;
|
||||||
|
})
|
||||||
|
.addTo(agent);
|
64
src/agent/fix/prompt.ts
Normal file
64
src/agent/fix/prompt.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { agent } from '@/agent/agent.ts';
|
||||||
|
import { ai } from '../ai.ts';
|
||||||
|
import { logger } from '@/agent/logger.ts';
|
||||||
|
|
||||||
|
const getTagContent = (text: string) => {
|
||||||
|
const match = text.match(/<content>([\s\S]*?)<\/content>/);
|
||||||
|
return match ? match[1].trim() : text;
|
||||||
|
};
|
||||||
|
agent
|
||||||
|
.route({
|
||||||
|
path: 'fix',
|
||||||
|
key: 'xhs',
|
||||||
|
description: '对小红书的提示词进行修正和优化',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const text = ctx.query?.text || '';
|
||||||
|
const now = Date.now();
|
||||||
|
console.log('start');
|
||||||
|
const res = await ai
|
||||||
|
.chat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: `
|
||||||
|
你是一个提示词优化的专家,请根据用户提供的提示词进行修正和优化,其中用户的提示词返回的要求如果没有或者不明确,请你都修正为要求返回的文本在500字以内,且内容是纯文本格式,不能是markdown模式,也不包含任何HTML标签或其他格式化内容。
|
||||||
|
|
||||||
|
只对提示词进行优化,并且不需要对内容进行分析或总结。
|
||||||
|
|
||||||
|
示例1. 用户提示词
|
||||||
|
<content>总结笔记</content>
|
||||||
|
优化后的提示词
|
||||||
|
<content>请总结一下这个笔记,要求返回的内容是纯文本格式,字数不超过500字。</content>
|
||||||
|
示例2. 用户提示词
|
||||||
|
<content>分析一下这个图片</content>
|
||||||
|
优化后的提示词
|
||||||
|
<content>请分析一下这个图片,要求返回的内容是纯文本格式,字数不超过500字。</content>
|
||||||
|
|
||||||
|
|
||||||
|
用户的提示词是
|
||||||
|
<content>
|
||||||
|
${text}
|
||||||
|
</content>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
enable_thinking: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
console.log('AI service error:', err.status);
|
||||||
|
ctx.throw(500, 'AI service error: ' + err.status);
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('end', Date.now() - now, 'ms');
|
||||||
|
const ans = res.choices[0]?.message?.content || '';
|
||||||
|
if (!ans) {
|
||||||
|
logger.error('Empty response from AI:', res);
|
||||||
|
}
|
||||||
|
ctx.body = getTagContent(ans)
|
||||||
|
})
|
||||||
|
.addTo(agent);
|
7
src/agent/index.ts
Normal file
7
src/agent/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { agent } from './agent.ts';
|
||||||
|
import './analyze/content.ts';
|
||||||
|
import './fix/prompt.ts';
|
||||||
|
|
||||||
|
import './xhs.ts';
|
||||||
|
|
||||||
|
export { agent };
|
3
src/agent/logger.ts
Normal file
3
src/agent/logger.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Logger } from '@kevisual/logger';
|
||||||
|
|
||||||
|
export const logger = new Logger();
|
19
src/agent/test/analyze.ts
Normal file
19
src/agent/test/analyze.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { agent } from '../index.ts';
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const text1 = '解答一下这个笔记。';
|
||||||
|
const text2 = '分析一下这个图片';
|
||||||
|
const text3 = '这个视频介绍的是什么';
|
||||||
|
const text4 = '评价一下这个评论。';
|
||||||
|
const text5 = '关于这个评论。';
|
||||||
|
const text6 = '1+1=';
|
||||||
|
const res = await agent.call({
|
||||||
|
path: 'analyze',
|
||||||
|
key: 'content',
|
||||||
|
payload: {
|
||||||
|
text: text6,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log('analyze content res', res.code, 'content', res.body);
|
||||||
|
};
|
||||||
|
main();
|
0
src/agent/test/common.ts
Normal file
0
src/agent/test/common.ts
Normal file
18
src/agent/test/prompt-fix.ts
Normal file
18
src/agent/test/prompt-fix.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 其中回复的要求是以纯文本,具体的内容在<content></content>当中
|
||||||
|
import { agent } from '../index.ts';
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const text = '请总结一下这个笔记。';
|
||||||
|
const text2 = '告诉我1+1的值';
|
||||||
|
const text3 = 'html和css的大纲是什么?';
|
||||||
|
const text4 = '1+1=';
|
||||||
|
const res = await agent.call({
|
||||||
|
path: 'fix',
|
||||||
|
key: 'xhs',
|
||||||
|
payload: {
|
||||||
|
text: text4,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log('fix xhs res', res.code, 'content', res.body);
|
||||||
|
};
|
||||||
|
main();
|
53
src/agent/xhs.ts
Normal file
53
src/agent/xhs.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
import { agent } from './agent.ts';
|
||||||
|
import { ai } from './ai.ts';
|
||||||
|
/**
|
||||||
|
* 清除文本中的@信息
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
|
const clearAtInfo = (text: string = '') => {
|
||||||
|
const newText = text.replace(/@[\u4e00-\u9fa5\w]+/g, '').replace(/#.*?#/g, '');
|
||||||
|
return newText.trim();
|
||||||
|
};
|
||||||
|
agent
|
||||||
|
.route({
|
||||||
|
path: 'xhs',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { text = '' } = ctx.query || {};
|
||||||
|
const id = nanoid();
|
||||||
|
const no_at_text = clearAtInfo(text);
|
||||||
|
const resFix = await agent.call({
|
||||||
|
path: 'fix',
|
||||||
|
key: 'xhs',
|
||||||
|
payload: {
|
||||||
|
text: no_at_text,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (resFix.code !== 200) {
|
||||||
|
ctx.throw(500, 'AI 小红书prompt优化错误: ' + resFix.message);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.log('小红书优化的文本', resFix.body);
|
||||||
|
}
|
||||||
|
const prompt_text = resFix.body || '';
|
||||||
|
const res = await ai
|
||||||
|
.chat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: prompt_text,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
enable_thinking: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
ctx.throw(500, 'AI 服务错误: ' + error.status);
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
ctx.body = res.choices?.[0]?.message?.content || '';
|
||||||
|
})
|
||||||
|
.addTo(agent);
|
3
src/modules/notify.ts
Normal file
3
src/modules/notify.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const notify = () => {
|
||||||
|
//
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
import { agent } from '@/agent/index.ts';
|
||||||
import { taskApp, queue, xhsApp } from '../task.ts';
|
import { taskApp, queue, xhsApp } from '../task.ts';
|
||||||
import { random, omit } from 'lodash-es';
|
import { random, omit } from 'lodash-es';
|
||||||
import util from 'node:util';
|
import util from 'node:util';
|
||||||
@ -10,6 +11,7 @@ taskApp
|
|||||||
.route({
|
.route({
|
||||||
path: 'task',
|
path: 'task',
|
||||||
key: 'getUnread',
|
key: 'getUnread',
|
||||||
|
description: '获取未读提及消息',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const res = await xhsApp.call({
|
const res = await xhsApp.call({
|
||||||
@ -50,6 +52,7 @@ taskApp
|
|||||||
.route({
|
.route({
|
||||||
path: 'task',
|
path: 'task',
|
||||||
key: 'getMention',
|
key: 'getMention',
|
||||||
|
description: '获取提及消息',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { unread_count } = ctx.query;
|
const { unread_count } = ctx.query;
|
||||||
@ -61,11 +64,9 @@ taskApp
|
|||||||
num: unread_count,
|
num: unread_count,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log('mentionRes', mentionRes.body);
|
|
||||||
if (mentionRes.code === 200) {
|
if (mentionRes.code === 200) {
|
||||||
let data = mentionRes.body || [];
|
let data = mentionRes.body || [];
|
||||||
// data = data.map((item) => omit(item, 'mention'));
|
// data = data.map((item) => omit(item, 'mention'));
|
||||||
console.log('queryMention', util.inspect(data, { depth: 10 }));
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const item = data[i];
|
const item = data[i];
|
||||||
queue.add(
|
queue.add(
|
||||||
@ -86,7 +87,6 @@ taskApp
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
console.log('add mention task', item);
|
|
||||||
await sleep(200);
|
await sleep(200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,9 +94,7 @@ taskApp
|
|||||||
path: 'mention',
|
path: 'mention',
|
||||||
key: 'postRead',
|
key: 'postRead',
|
||||||
});
|
});
|
||||||
console.log('postRead', postRead.body);
|
|
||||||
}
|
}
|
||||||
await sleep(1000);
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
job: unread_count,
|
job: unread_count,
|
||||||
};
|
};
|
||||||
@ -109,7 +107,7 @@ taskApp
|
|||||||
key: 'ai',
|
key: 'ai',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const data = ctx.query.data;
|
const data = ctx.query.data; // 为提及的相关信息
|
||||||
const note_id = data.note_id;
|
const note_id = data.note_id;
|
||||||
const xsec_token = data.xsec_token;
|
const xsec_token = data.xsec_token;
|
||||||
const comment_id = data.comment.comment_id;
|
const comment_id = data.comment.comment_id;
|
||||||
@ -119,6 +117,21 @@ taskApp
|
|||||||
content,
|
content,
|
||||||
comment_id,
|
comment_id,
|
||||||
};
|
};
|
||||||
|
const resAgent = await agent.call({
|
||||||
|
path: 'xhs',
|
||||||
|
payload: {
|
||||||
|
text: content,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let responseText = '';
|
||||||
|
let errorText = '';
|
||||||
|
if (resAgent.code !== 200) {
|
||||||
|
errorText = '【调用错误】';
|
||||||
|
responseText = `${resAgent.message}`;
|
||||||
|
} else {
|
||||||
|
responseText = resAgent.body;
|
||||||
|
}
|
||||||
|
postData.content = responseText;
|
||||||
const res = await xhsApp.call({
|
const res = await xhsApp.call({
|
||||||
path: 'mention',
|
path: 'mention',
|
||||||
key: 'addComment',
|
key: 'addComment',
|
||||||
|
22
turbo.json
Normal file
22
turbo.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://turbo.build/schema.json",
|
||||||
|
"tasks": {
|
||||||
|
"build": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^build"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"dist/**"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dev:lib": {
|
||||||
|
"persistent": true,
|
||||||
|
"cache": true
|
||||||
|
},
|
||||||
|
"build:lib": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^build:lib"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user