257 lines
6.6 KiB
TypeScript
257 lines
6.6 KiB
TypeScript
import {
|
||
genCardMsg,
|
||
getActionOption,
|
||
getActionValue,
|
||
getChatId,
|
||
getMessageId,
|
||
LarkAction,
|
||
} from "@egg/lark-msg-tool"
|
||
|
||
import { Context } from "../../../types"
|
||
import llm from "../../../utils/llm"
|
||
import cardTemplateMap from "./cards"
|
||
|
||
enum CardTemplate {
|
||
groupSelector = "ctp_AA0LgXOkJpIn",
|
||
functionSelector = "ctp_AA0xqIITeUex",
|
||
timeScopeSelector = "ctp_AA00oqPWT1Hq",
|
||
resultReport = "ctp_AA00oqPWTHWP",
|
||
successMsg = "ctp_AA0LgXOkEOPK",
|
||
errorMsg = "ctp_AA0LgXOkEuqi",
|
||
}
|
||
|
||
/**
|
||
* 发送群组选择器
|
||
* @param ctx - 上下文数据,包含body和larkService
|
||
*/
|
||
const sendGroupSelector = async ({
|
||
larkService,
|
||
body,
|
||
logger,
|
||
requestId,
|
||
}: Context.Data) => {
|
||
const { data: innerList } = await larkService.chat.getInnerList()
|
||
logger.info(`Inner list: ${JSON.stringify(innerList)}`)
|
||
// 组织群组数据
|
||
const groups = innerList.map((v) => ({
|
||
text: v.name,
|
||
value: `${v.chat_id}|${v.name}`,
|
||
}))
|
||
larkService.message.sendTemp(
|
||
"chat_id",
|
||
getChatId(body),
|
||
CardTemplate.groupSelector,
|
||
{
|
||
groups,
|
||
requestId,
|
||
}
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 发送功能选择器
|
||
* @param ctx - 上下文数据
|
||
*/
|
||
const sendFunctionSelector = async (ctx: Context.Data) => {
|
||
const { logger, requestId } = ctx
|
||
const body = ctx.body as LarkAction.Data
|
||
const option = getActionOption(body)
|
||
logger.debug(`Action option: ${JSON.stringify(option)}`)
|
||
const [chatId, chatName] = option.split("|")
|
||
if (!chatId || !chatName) {
|
||
logger.error(
|
||
`Invalid targetChatId or targetChatName: ${JSON.stringify(option)}`
|
||
)
|
||
return genCardMsg(
|
||
cardTemplateMap.errorMsg,
|
||
{
|
||
content: "Invalid targetChatId or targetChatName",
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
// 组织功能数据
|
||
const functions = [
|
||
{
|
||
text: "总结消息",
|
||
value: "summary-gpt-4o|总结消息",
|
||
},
|
||
]
|
||
return genCardMsg(
|
||
cardTemplateMap.functionSelector,
|
||
{
|
||
functions,
|
||
chatId,
|
||
chatName,
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 发送时间范围选择器
|
||
* @param ctx - 上下文数据,包含body和larkService
|
||
*/
|
||
const sendTimeScopeSelector = async (ctx: Context.Data) => {
|
||
const { logger, requestId } = ctx
|
||
const body = ctx.body as LarkAction.Data
|
||
const option = getActionOption(body)
|
||
logger.debug(`Action option: ${JSON.stringify(option)}`)
|
||
const [functionId, functionName] = option.split("|")
|
||
if (!functionId || !functionName) {
|
||
logger.error(`Invalid functionId or functionName: ${option}`)
|
||
return genCardMsg(
|
||
cardTemplateMap.errorMsg,
|
||
{
|
||
content: "Invalid functionId or functionName",
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
const value = getActionValue(body)
|
||
logger.debug(`Action value: ${JSON.stringify(value)}`)
|
||
const { chatId, chatName } = value
|
||
if (!chatName || !chatId) {
|
||
logger.error(`Invalid chatName or chatId: ${JSON.stringify(value)}`)
|
||
return genCardMsg(
|
||
cardTemplateMap.errorMsg,
|
||
{
|
||
content: "Invalid chatName or chatId",
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
return genCardMsg(
|
||
cardTemplateMap.timeScopeSelector,
|
||
{
|
||
chatId,
|
||
chatName,
|
||
functionId,
|
||
functionName,
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
|
||
const sendGroupReport = async (ctx: Context.Data) => {
|
||
const { larkService, logger, requestId } = ctx
|
||
const body = ctx.body as LarkAction.Data
|
||
const { chatId, chatName, functionId, functionName, timeScope } =
|
||
getActionValue(body)
|
||
|
||
// 记录发送loading消息后的时间戳
|
||
const startTime = Date.now()
|
||
|
||
// 获取历史消息,timeScope为1、3、7,分别代表1天、3天、7天
|
||
// 获取服务器的时区偏移量(以分钟为单位)
|
||
const serverTimezoneOffset = new Date().getTimezoneOffset()
|
||
// 上海时区的偏移量(UTC+8,以分钟为单位)
|
||
const shanghaiTimezoneOffset = -8 * 60
|
||
// 计算时间戳,调整为上海时区
|
||
const endTimeTimestamp =
|
||
Math.round(new Date().getTime() / 1000) +
|
||
(shanghaiTimezoneOffset - serverTimezoneOffset) * 60
|
||
const startTimeTimestamp = endTimeTimestamp - Number(timeScope) * 24 * 60 * 60
|
||
// 获取群聊中的历史记录
|
||
const { data: chatHistory } = await larkService.message.getHistory(
|
||
chatId,
|
||
String(startTimeTimestamp),
|
||
String(endTimeTimestamp)
|
||
)
|
||
// 如果没有历史记录则返回错误消息
|
||
if (chatHistory.length === 0) {
|
||
logger.error("Chat history is empty")
|
||
await larkService.message.updateTemp(
|
||
getMessageId(body),
|
||
CardTemplate.errorMsg,
|
||
{
|
||
content: "未找到聊天记录",
|
||
requestId,
|
||
}
|
||
)
|
||
return
|
||
}
|
||
logger.debug(`Chat history: ${JSON.stringify(chatHistory)}`)
|
||
try {
|
||
const llmRes = await llm.invoke(functionId, {
|
||
chatHistory: JSON.stringify(chatHistory),
|
||
time: new Date().toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" }),
|
||
})
|
||
// 记录大模型返回结果后的时间戳
|
||
const endTime = Date.now()
|
||
// 计算时间差并存储在processingTime变量中,以秒为单位
|
||
const processingTime = ((endTime - startTime) / 1000).toFixed(2)
|
||
logger.info(`LLM takes time: ${processingTime}s, result: ${llmRes}`)
|
||
await larkService.message.updateTemp(
|
||
getMessageId(body),
|
||
CardTemplate.resultReport,
|
||
{
|
||
chatName,
|
||
functionName,
|
||
llmRes,
|
||
timeScope,
|
||
requestId,
|
||
processingTime,
|
||
}
|
||
)
|
||
} catch (error: any) {
|
||
logger.error(`LLM error: ${error.message}`)
|
||
await larkService.message.updateTemp(
|
||
getMessageId(body),
|
||
CardTemplate.errorMsg,
|
||
{
|
||
content: "LLM调用失败: " + error.message,
|
||
requestId,
|
||
}
|
||
)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 发送结果报告
|
||
* @param ctx - 上下文数据,包含body和larkService
|
||
*/
|
||
const manageGroupMsg = async (ctx: Context.Data) => {
|
||
const { logger, requestId } = ctx
|
||
const body = ctx.body as LarkAction.Data
|
||
const value = getActionValue(body)
|
||
logger.debug(`Action value: ${JSON.stringify(value)}`)
|
||
const { chatId, chatName, functionId, functionName, timeScope } = value
|
||
if (!chatId || !chatName || !functionId || !functionName || !timeScope) {
|
||
logger.error(`Invalid value: ${JSON.stringify(value)}`)
|
||
return genCardMsg(
|
||
cardTemplateMap.errorMsg,
|
||
{
|
||
content: "Invalid value",
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
// 处理群组消息
|
||
sendGroupReport(ctx)
|
||
// 发送一个loading的消息
|
||
return genCardMsg(
|
||
cardTemplateMap.successMsg,
|
||
{
|
||
content: "Group Agent 正在爬楼中,请稍等...",
|
||
requestId,
|
||
},
|
||
false
|
||
)
|
||
}
|
||
|
||
const groupAgent = {
|
||
sendGroupSelector,
|
||
sendFunctionSelector,
|
||
sendTimeScopeSelector,
|
||
manageGroupMsg,
|
||
}
|
||
|
||
export default groupAgent
|