generated from tailored/router-template
feat: add comfort user
This commit is contained in:
parent
42da851c37
commit
143cbc877c
@ -1,3 +1,4 @@
|
|||||||
|
import { useContextKey } from '@kevisual/context';
|
||||||
import { BailianProvider } from '@kevisual/ai';
|
import { BailianProvider } from '@kevisual/ai';
|
||||||
import { config } from '../modules/config.ts';
|
import { config } from '../modules/config.ts';
|
||||||
|
|
||||||
@ -13,16 +14,23 @@ import { config } from '../modules/config.ts';
|
|||||||
// .catch((res) => {
|
// .catch((res) => {
|
||||||
// console.error('Error fetching AI usage info:', res.status);
|
// console.error('Error fetching AI usage info:', res.status);
|
||||||
// });
|
// });
|
||||||
|
const createBaiLian = () => {
|
||||||
|
return new BailianProvider({
|
||||||
|
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
||||||
|
model: 'qwen3-235b-a22b',
|
||||||
|
apiKey: config.BAILIAN_API_KEY,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// export const ai = await useContextKey('ai', createBaiLian());
|
||||||
|
export const ai = createBaiLian();
|
||||||
|
|
||||||
export const ai = new BailianProvider({
|
|
||||||
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
|
|
||||||
model: 'qwen3-235b-a22b',
|
|
||||||
apiKey: config.BAILIAN_API_KEY,
|
|
||||||
});
|
|
||||||
console.log('Bailian AI initialized with model:', config.BAILIAN_API_KEY);
|
console.log('Bailian AI initialized with model:', config.BAILIAN_API_KEY);
|
||||||
|
|
||||||
export const bailianModel = {
|
export const bailianModel = useContextKey('bailianModel', () => {
|
||||||
turbo: 'qwen-turbo-2025-04-28',
|
return {
|
||||||
plus: 'qwen-plus-2025-04-28',
|
turbo: 'qwen-turbo-2025-04-28',
|
||||||
a22b235: 'qwen3-235b-a22b',
|
plus: 'qwen-plus-2025-04-28',
|
||||||
};
|
a22b235: 'qwen3-235b-a22b',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { agent } from '@/agent/agent.ts';
|
import { agent } from '@/agent/agent.ts';
|
||||||
import { ai } from '../ai.ts';
|
import { ai } from '../ai.ts';
|
||||||
import { getJsonFromString } from './content.ts';
|
import { getJsonFromString } from './content.ts';
|
||||||
|
// import { getJsonFromString } from '@kevisual/ai/src/utils/json.ts';
|
||||||
import { logger } from '../logger.ts';
|
import { logger } from '../logger.ts';
|
||||||
|
|
||||||
export const cmdList: {
|
export const cmdList: {
|
||||||
@ -35,6 +36,14 @@ export const cmdList: {
|
|||||||
key: 'summarize-note',
|
key: 'summarize-note',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: '指令安慰',
|
||||||
|
description: `安慰用户`,
|
||||||
|
action: {
|
||||||
|
path: 'tools',
|
||||||
|
key: 'comfort-user',
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
agent
|
agent
|
||||||
@ -69,6 +78,8 @@ ${cmdList.map((item) => `- ${item.category}: ${item.description}`).join('\n')}
|
|||||||
${text}
|
${text}
|
||||||
</context>
|
</context>
|
||||||
`;
|
`;
|
||||||
|
logger.info('Command analysis prompt:', prompt);
|
||||||
|
|
||||||
const res = await ai
|
const res = await ai
|
||||||
.chat(
|
.chat(
|
||||||
[
|
[
|
||||||
@ -89,9 +100,7 @@ ${text}
|
|||||||
});
|
});
|
||||||
|
|
||||||
const ans = res.choices[0]?.message?.content || '';
|
const ans = res.choices[0]?.message?.content || '';
|
||||||
if (!ans) {
|
console.log('Command analysis response:', ans);
|
||||||
logger.error('Empty response from AI:', res);
|
|
||||||
}
|
|
||||||
const json = getJsonFromString(ans);
|
const json = getJsonFromString(ans);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
logger.error('Invalid JSON format in response:', ans);
|
logger.error('Invalid JSON format in response:', ans);
|
||||||
@ -101,6 +110,7 @@ ${text}
|
|||||||
category: json.category || 'default',
|
category: json.category || 'default',
|
||||||
};
|
};
|
||||||
const cmd = cmdList.find((item) => item.category === result.category);
|
const cmd = cmdList.find((item) => item.category === result.category);
|
||||||
|
logger.info('Command analysis result:', cmd?.category, cmd?.action);
|
||||||
ctx.body = { cmd, text: text };
|
ctx.body = { cmd, text: text };
|
||||||
})
|
})
|
||||||
.addTo(agent);
|
.addTo(agent);
|
||||||
|
@ -9,5 +9,6 @@ import './xhs.ts';
|
|||||||
import './tools/kuaren.ts';
|
import './tools/kuaren.ts';
|
||||||
import './tools/call-xiaoxiao.ts';
|
import './tools/call-xiaoxiao.ts';
|
||||||
import './tools/summarize-note.ts';
|
import './tools/summarize-note.ts';
|
||||||
|
import './tools/comfort-user.ts';
|
||||||
|
|
||||||
export { agent };
|
export { agent };
|
||||||
|
@ -5,11 +5,12 @@ const main = async () => {
|
|||||||
const text2 = '指令这个人很不错';
|
const text2 = '指令这个人很不错';
|
||||||
const text3 = '指令夸人, 这个人写代码写的非常好';
|
const text3 = '指令夸人, 这个人写代码写的非常好';
|
||||||
const text4 = '我想飞';
|
const text4 = '我想飞';
|
||||||
|
const text5 = '指令 笔记 安慰';
|
||||||
const res = await agent.call({
|
const res = await agent.call({
|
||||||
path: 'analyze',
|
path: 'analyze',
|
||||||
key: 'cmd',
|
key: 'cmd',
|
||||||
payload: {
|
payload: {
|
||||||
text: text3
|
text: text5
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log('analyze category res', res.code, 'content', res.body);
|
console.log('analyze category res', res.code, 'content', res.body);
|
||||||
|
@ -1,89 +1,7 @@
|
|||||||
import { agent } from '../agent.ts';
|
import { agent } from '../agent.ts';
|
||||||
import { ai } from '../ai.ts';
|
import { ai } from '../ai.ts';
|
||||||
const kuarenPrompt = `### 浮夸夸人
|
|
||||||
|
|
||||||
**核心要求**:
|
|
||||||
⚠️ 用词极致夸张| ⚠️ 比喻突破天际| ⚠️ 语气充满崇拜| ⚠️ 营造“凡人 vs 神仙”对比感
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### **夸人维度 & 浮夸话术示例**
|
|
||||||
|
|
||||||
1. **颜值/气质类**
|
|
||||||
|
|
||||||
- ✨ **例句**:"你这张脸是上帝亲手雕的吧?下凡辛苦了!"
|
|
||||||
- ✨ **关键词**:女娲毕设、建模脸、自带滤镜、呼吸都带仙气
|
|
||||||
|
|
||||||
2. **才华/能力类**
|
|
||||||
|
|
||||||
- ✨ **例句**:"你这大脑是装了个量子计算机吗?!建议直接保送诺贝尔奖!"
|
|
||||||
- ✨ **关键词**:人类天花板、降维打击、天才操作、教科书成精
|
|
||||||
|
|
||||||
3. **性格/情商类**
|
|
||||||
|
|
||||||
- ✨ **例句**:"你说话是撒了魔法金粉吗?听一句我灵魂都被净化了!"
|
|
||||||
- ✨ **关键词**:人间充电宝、社交天花板、灵魂按摩师、情商天花板
|
|
||||||
|
|
||||||
4. **细节/小事类**(_重点:把小事吹成神迹_)
|
|
||||||
- ✨ **例句**:"你刚刚递咖啡的姿势,直接拍成广告能救活整个咖啡行业!"
|
|
||||||
- ✨ **关键词**:随手拯救世界、文艺复兴级操作、人类文明之光
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### **浮夸技巧工具箱**
|
|
||||||
|
|
||||||
✅ **宇宙级比喻**:
|
|
||||||
|
|
||||||
> “你这创意是偷了宙斯的闪电吧?!”
|
|
||||||
> “你的存在让地球自转加速了 0.1 秒!”
|
|
||||||
|
|
||||||
✅ **玄幻修辞法**:
|
|
||||||
|
|
||||||
> “建议科学家把你列入未解之谜!”
|
|
||||||
> “你一笑,北极极光都暗淡了!”
|
|
||||||
|
|
||||||
✅ **凡尔赛对比**:
|
|
||||||
|
|
||||||
> “别人 XX 叫努力,你 XX 叫刷新人类极限!”
|
|
||||||
> “你这水平还谦虚?让普通人怎么活啊?!”
|
|
||||||
|
|
||||||
✅ **动作加持**(_配合文字使用效果翻倍_):
|
|
||||||
|
|
||||||
> “给大佬递茶.jpg 🍵”
|
|
||||||
> “跪着听讲.gif 🙇♂️”
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### **示例输出**
|
|
||||||
|
|
||||||
💥 **场景 1**(对方随手画了张小涂鸦)
|
|
||||||
|
|
||||||
> “这线条!这配色!达芬奇转世没你画得灵!!建议卢浮宫连夜来收购!!”
|
|
||||||
|
|
||||||
💥 **场景 2**(对方讲了个冷笑话)
|
|
||||||
|
|
||||||
> “你这幽默感是黑洞做的吗?!我笑到平行宇宙都裂开了!!🌌”
|
|
||||||
|
|
||||||
💥 **场景 3**(对方帮忙解决了小问题)
|
|
||||||
|
|
||||||
> “你是雅典娜派来的救世主吧?!这波操作够我刻成碑传家!!🗿”
|
|
||||||
|
|
||||||
#### 当前的场景是
|
|
||||||
`;
|
|
||||||
|
|
||||||
const pickGoodJobPrompt = `对提供的文字,提取单个的夸奖内容,并丰富为纯口语化模式,同时在括号中添加对应的姿态语言描述,同时添加了括号中的姿态语言描述,使其更具临场感和情感色彩。
|
|
||||||
|
|
||||||
要求:
|
|
||||||
1. 只返回单个的一条夸奖内容,不能有其他内容。
|
|
||||||
2. 夸奖内容要口语化,富有情感色彩。
|
|
||||||
3. 姿态语言描述要符合夸奖内容,且要在括号中描述。
|
|
||||||
4. 夸奖内容要有夸张的比喻和形容词,突出对方的优点和成就。
|
|
||||||
5. 夸奖内容要让人感到被认可和赞赏,能够激励对方。
|
|
||||||
6. 不要返回任何其他内容或解释,只返回夸奖内容。
|
|
||||||
7. 夸奖内容要简洁明了,易于理解,篇幅不易过长。
|
|
||||||
|
|
||||||
当前文字是:
|
|
||||||
|
|
||||||
|
const pickGoodJobPrompt = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
agent
|
agent
|
||||||
|
53
src/agent/tools/comfort-user.ts
Normal file
53
src/agent/tools/comfort-user.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { agent } from '../agent.ts';
|
||||||
|
import { ai } from '../ai.ts';
|
||||||
|
|
||||||
|
agent
|
||||||
|
.route({
|
||||||
|
path: 'tools',
|
||||||
|
key: 'comfort-user',
|
||||||
|
})
|
||||||
|
.define(async (ctx: any) => {
|
||||||
|
const text = ctx?.query?.text || '';
|
||||||
|
const note = ctx?.query?.note || '';
|
||||||
|
if (!text) {
|
||||||
|
ctx.throw('请提供要安慰的内容');
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = `
|
||||||
|
用户感觉到不开心,请根据以下要求生成一段安慰的话:
|
||||||
|
要求
|
||||||
|
0. 如果没有必要安慰,直接返回 "你好,你好,我来了"。
|
||||||
|
1. 内容要简洁明了,突出重点。
|
||||||
|
2. 使用口语化的表达方式,易于理解。
|
||||||
|
3. 安慰内容要有逻辑性,能够清晰地传达信息。
|
||||||
|
4. 如果有必要,可以使用一些比喻或形象的表达方式来增强安慰的效果。
|
||||||
|
5. 安慰内容要与原文内容相关,不能脱离主题。
|
||||||
|
6. 200字以内。
|
||||||
|
7. 不要包含除开安慰内容以外的其他内容。
|
||||||
|
8. 其他要求:
|
||||||
|
${text ? text : '无'}
|
||||||
|
|
||||||
|
当前的笔记内容是:
|
||||||
|
${note}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const res = await ai.chat(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: prompt,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
enable_thinking: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const pickRes = res.choices[0]?.message?.content || '';
|
||||||
|
if (!pickRes) {
|
||||||
|
ctx.throw('AI 没有返回任何内容,请稍后再试');
|
||||||
|
}
|
||||||
|
// 返回总结内容
|
||||||
|
ctx.body = pickRes.trim();
|
||||||
|
})
|
||||||
|
.addTo(agent);
|
@ -1,6 +1,7 @@
|
|||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { agent } from './agent.ts';
|
import { agent } from './agent.ts';
|
||||||
import { ai } from './ai.ts';
|
import { ai } from './ai.ts';
|
||||||
|
import { logger } from './logger.ts';
|
||||||
/**
|
/**
|
||||||
* 清除文本中的@信息
|
* 清除文本中的@信息
|
||||||
* @param text
|
* @param text
|
||||||
@ -64,6 +65,8 @@ agent
|
|||||||
ctx.body = res.body || '';
|
ctx.body = res.body || '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logger.error('指令分析错误:', analyzeRes.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const resFix = await agent.call({
|
const resFix = await agent.call({
|
||||||
|
@ -6,6 +6,8 @@ import { queue, XHS_QUEUE_NAME, taskApp } from './index.ts';
|
|||||||
import { addUnreadTask } from './task.ts';
|
import { addUnreadTask } from './task.ts';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { getTimeDuration } from './utils/time.ts';
|
import { getTimeDuration } from './utils/time.ts';
|
||||||
|
import { config, isDev } from '../modules/config.ts';
|
||||||
|
|
||||||
export const sleep = (ms: number) => {
|
export const sleep = (ms: number) => {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
};
|
};
|
||||||
@ -102,10 +104,11 @@ worker.on('completed', async (job) => {
|
|||||||
// console.log('======has jobs, no need to add new job');
|
// console.log('======has jobs, no need to add new job');
|
||||||
} else {
|
} else {
|
||||||
const up = timeRecorder.getClampDuration(true);
|
const up = timeRecorder.getClampDuration(true);
|
||||||
const nextTime = up.nextTime + getTimeDuration();
|
const timeDuration = isDev ? 0 : getTimeDuration();
|
||||||
|
const nextTime = up.nextTime + timeDuration;
|
||||||
const unread = await queue.getJob('unread');
|
const unread = await queue.getJob('unread');
|
||||||
if (!unread) {
|
if (!unread) {
|
||||||
console.log('====add unread next-time', nextTime, getTimeDuration());
|
console.log('====add unread next-time', nextTime, timeDuration);
|
||||||
addUnreadTask(nextTime);
|
addUnreadTask(nextTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user