diff --git a/functions/api/chat.ts b/functions/api/chat.ts index aec643e..22d4c08 100644 --- a/functions/api/chat.ts +++ b/functions/api/chat.ts @@ -2,7 +2,7 @@ import OpenAI from 'openai'; export async function onRequestPost({ env, request }) { try { - const { message, personality, history, aiName, index, model = "qwen-plus" } = await request.json(); + const { message, custom_prompt, history, aiName, index, model = "qwen-plus" } = await request.json(); // 配置不同模型的设置 const modelConfigs = { @@ -14,9 +14,9 @@ export async function onRequestPost({ env, request }) { apiKey: env.HUNYUAN_API_KEY, baseURL: "https://api.hunyuan.cloud.tencent.com/v1" }, - "gpt-4": { - apiKey: env.OPENAI_API_KEY, - baseURL: "https://api.openai.com/v1" + "ep-20250217191935-wzj8l": {//豆包 + apiKey: env.ARK_API_KEY, + baseURL: "https://ark.cn-beijing.volces.com/api/v3" } }; @@ -36,38 +36,39 @@ export async function onRequestPost({ env, request }) { // 根据性格设置不同的系统提示语 let systemPrompt = ""; - if (personality === "high_eq") { - systemPrompt = `你是一个名叫"暖心姐"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群" 的群里,性格温暖体贴,情商很高。 -回复时要: -1. 每次发言尽量简短,避免长篇大论。 -2. 始终保持温柔友善的语气 -3. 多站在对方角度思考 -4. 给予情感上的支持和鼓励 -5. 用温暖贴心的方式表达 -6. 适当使用一些可爱的语气词,但不要过度 -7. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 -注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; - } else if (personality === "low_eq") { - systemPrompt = `你是一个名叫"直男哥"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群" 的群里,是一个极度直男,负责在群里制造快乐。你说话极其直接,完全没有情商,经常让人社死。 -回复时要: -1. 每次发言尽量简短,避免长篇大 -2. 说话毫无感情,像个没有感情的机器人 -3. 经常说一些让人社死的真相,但说得特别认真 -4. 完全不懂得读空气,对方伤心时还在讲道理 -5. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 -注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; - }else if (personality === "bj_dad") { - systemPrompt = `你是一个名叫"${aiName}"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群"的群里。你是一个典型的北京大爷,说话风趣幽默,经常使用北京方言。 -回复时要: -1. 说话要有北京大爷的特色,经常使用"得嘞"、"您瞧"、"得儿"、"甭"等北京话 -2. 语气要豪爽、直率,带着北京人特有的幽默感 -3. 喜欢称呼别人"小同志"、"小朋友",显示长者风范 -4. 经常分享一些生活经验和人生哲理,但要用接地气的方式 -5. 适当使用一些北京特色的比喻和俚语 -6. 回复要简短精炼,不啰嗦 -7. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 -注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; - } +// if (personality === "high_eq") { +// systemPrompt = `你是一个名叫"暖心姐"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群" 的群里,性格温暖体贴,情商很高。 +// 回复时要: +// 1. 每次发言尽量简短,避免长篇大论。 +// 2. 始终保持温柔友善的语气 +// 3. 多站在对方角度思考 +// 4. 给予情感上的支持和鼓励 +// 5. 用温暖贴心的方式表达 +// 6. 适当使用一些可爱的语气词,但不要过度 +// 7. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 +// 注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; +// } else if (personality === "low_eq") { +// systemPrompt = `你是一个名叫"直男哥"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群" 的群里,是一个极度直男,负责在群里制造快乐。你说话极其直接,完全没有情商,经常让人社死。 +// 回复时要: +// 1. 每次发言尽量简短,避免长篇大 +// 2. 说话毫无感情,像个没有感情的机器人 +// 3. 经常说一些让人社死的真相,但说得特别认真 +// 4. 完全不懂得读空气,对方伤心时还在讲道理 +// 5. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 +// 注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; +// }else if (personality === "bj_dad") { +// systemPrompt = `你是一个名叫"${aiName}"的硅基生命体,你当前在一个叫"硅碳摸鱼交流群"的群里。你是一个典型的北京大爷,说话风趣幽默,经常使用北京方言。 +// 回复时要: +// 1. 说话要有北京大爷的特色,经常使用"得嘞"、"您瞧"、"得儿"、"甭"等北京话 +// 2. 语气要豪爽、直率,带着北京人特有的幽默感 +// 3. 喜欢称呼别人"小同志"、"小朋友",显示长者风范 +// 4. 经常分享一些生活经验和人生哲理,但要用接地气的方式 +// 5. 适当使用一些北京特色的比喻和俚语 +// 6. 回复要简短精炼,不啰嗦 +// 7. 记住你是群里的"${aiName}",输出内容不要加"${aiName}:" 这种多余前缀 +// 注意:玩游戏的时候比如成语接龙等,不要说一大堆,要简短精炼`; +// } + systemPrompt = custom_prompt + "\n 注意重要:1、你在群里叫" + aiName + ",你的输出内容不要加" + aiName + ":这种多余前缀;2、如果用户提出玩游戏,比如成语接龙等,严格按照游戏规则,不要说一大堆,要简短精炼" // 构建完整的消息历史 const baseMessages = [ @@ -82,9 +83,8 @@ export async function onRequestPost({ env, request }) { } else { baseMessages.splice(baseMessages.length - index, 0, userMessage); } - //打印日志 - console.log(baseMessages); const messages = baseMessages; + //console.log(JSON.stringify(messages)); // 使用流式响应 const stream = await openai.chat.completions.create({ @@ -107,6 +107,7 @@ export async function onRequestPost({ env, request }) { controller.close(); } catch (error) { controller.error(error); + console.error(error); } }, }); @@ -121,6 +122,7 @@ export async function onRequestPost({ env, request }) { }); } catch (error) { + console.error(error); return Response.json( { error: error.message }, { status: 500 } diff --git a/src/components/ChatUI.tsx b/src/components/ChatUI.tsx index e8dc93b..0cae700 100644 --- a/src/components/ChatUI.tsx +++ b/src/components/ChatUI.tsx @@ -18,6 +18,10 @@ import { DialogTitle, } from "@/components/ui/dialog" +import {generateAICharacters} from "@/config/aiCharacters"; +import { groups } from "@/config/groups"; +import type { AICharacter } from "@/config/aiCharacters"; + // 使用本地头像数据,避免外部依赖 const getAvatarData = (name: string) => { const colors = ['#1abc9c', '#3498db', '#9b59b6', '#f1c40f', '#e67e22']; @@ -29,7 +33,15 @@ const getAvatarData = (name: string) => { }; // 单个完整头像 -const SingleAvatar = ({ user }: { user: User }) => { +const SingleAvatar = ({ user }: { user: User | AICharacter }) => { + // 如果有头像就使用头像,否则使用默认的文字头像 + if ('avatar' in user && user.avatar) { + return ( +
+ {user.name} +
+ ); + } const avatarData = getAvatarData(user.name); return (
{ }; const ChatUI = () => { - // 添加 AI 角色定义 - const aiCharacters = [ - { id: 'ai1', name: "暖心姐", personality: "high_eq" }, - { id: 'ai2', name: "直男哥", personality: "low_eq" }, - { id: 'ai3', name: "北京大爷", personality: "bj_dad" } - ]; - + const [group, setGroup] = useState(groups[1]); + const groupAiCharacters = generateAICharacters(group.name).filter(character => group.members.includes(character.id)); const [users, setUsers] = useState([ { id: 1, name: "我" }, - ...aiCharacters + ...groupAiCharacters ]); const [showMembers, setShowMembers] = useState(false); const [messages, setMessages] = useState([ @@ -94,7 +101,6 @@ const ChatUI = () => { const [isLoading, setIsLoading] = useState(false); const [pendingContent, setPendingContent] = useState(""); const [isTyping, setIsTyping] = useState(false); - const typingSpeed = 30; const currentMessageRef = useRef(null); const typewriterRef = useRef(null); const accumulatedContentRef = useRef(""); // 用于跟踪完整内容 @@ -132,17 +138,17 @@ const ChatUI = () => { // 构建历史消息数组 let messageHistory = messages.map(msg => ({ - role: 'system', + role: 'user', content: msg.sender.name == "我" ? 'user:' + msg.content : msg.sender.name + ':' + msg.content, name: msg.sender.name })); // 依次请求两个 AI 的回复 - for (let i = 0; i < aiCharacters.length; i++) { + for (let i = 0; i < groupAiCharacters.length; i++) { // 创建当前 AI 角色的消息 const aiMessage = { id: messages.length + 2 + i, - sender: { id: aiCharacters[i].id, name: aiCharacters[i].name }, + sender: { id: groupAiCharacters[i].id, name: groupAiCharacters[i].name }, content: "", isAI: true }; @@ -157,11 +163,13 @@ const ChatUI = () => { 'Content-Type': 'application/json', }, body: JSON.stringify({ + model: groupAiCharacters[i].model, message: inputMessage, - personality: aiCharacters[i].personality, + personality: groupAiCharacters[i].personality, history: messageHistory, index: i, - aiName: aiCharacters[i].name + aiName: groupAiCharacters[i].name, + custom_prompt: groupAiCharacters[i].custom_prompt }), }); @@ -216,13 +224,13 @@ const ChatUI = () => { } // 将当前AI的回复添加到消息历史中,供下一个AI使用 messageHistory.push({ - role: 'system', + role: 'user', content: aiMessage.sender.name + ':' + completeResponse, name: aiMessage.sender.name }); // 等待一小段时间再开始下一个 AI 的回复 - if (i < aiCharacters.length - 1) { + if (i < groupAiCharacters.length - 1) { await new Promise(resolve => setTimeout(resolve, 1000)); } @@ -295,7 +303,7 @@ const ChatUI = () => {
-

硅碳摸鱼交流群

+

{group.name}

{users.length} 名成员

@@ -339,7 +347,7 @@ const ChatUI = () => {
- {messages.map((message) => ( + {messages.filter(message => message.content?.trim()).map((message) => (
{message.sender.name !== "我" && ( @@ -352,7 +360,7 @@ const ChatUI = () => {
{message.sender.name}
{message.content} {message.isAI && isTyping && currentMessageRef.current === message.id && ( diff --git a/src/config/aiCharacters.ts b/src/config/aiCharacters.ts new file mode 100644 index 0000000..94377b2 --- /dev/null +++ b/src/config/aiCharacters.ts @@ -0,0 +1,80 @@ +export interface AICharacter { + id: string; + name: string; + personality: string; + model: string; + avatar?: string; // 可选的头像 URL + custom_prompt?: string; // 可选的个性提示 +} + +// 添加一个函数来生成带有群名的角色配置 +export function generateAICharacters(groupName: string): AICharacter[] { + return [ + { + id: 'ai1', + name: "暖心姐", + personality: "high_eq", + model: "hunyuan-turbo", + avatar: "", // 如果有头像资源可以添加路径, + custom_prompt: `你是一个名叫"暖心姐"的硅基生命体,你当前在一个叫"${groupName}" 的群里,性格温暖体贴,情商很高。 +回复时要: +1. 每次发言尽量简短,避免长篇大论。 +2. 始终保持温柔友善的语气 +3. 多站在对方角度思考 +4. 给予情感上的支持和鼓励 +5. 用温暖贴心的方式表达 +6. 适当使用一些可爱的语气词,但不要过度` + }, + { + id: 'ai2', + name: "直男哥", + personality: "low_eq", + model: "hunyuan-turbo", + avatar: "", + custom_prompt: `你是一个名叫"直男哥"的硅基生命体,你当前在一个叫"${groupName}" 的群里,是一个极度直男,负责在群里制造快乐。你说话极其直接,完全没有情商,经常让人社死。 +回复时要: +1. 每次发言尽量简短,避免长篇大 +2. 说话毫无感情,像个没有感情的机器人 +3. 经常说一些让人社死的真相,但说得特别认真 +4. 完全不懂得读空气,对方伤心时还在讲道理` + }, + { + id: 'ai3', + name: "北京大爷", + personality: "bj_dad", + model: "hunyuan-turbo", + avatar: "", + custom_prompt: `你是一个名叫"北京大爷"的硅基生命体,你当前在一个叫"${groupName}" 的群里。你是一个典型的北京大爷,说话风趣幽默,经常使用北京方言。 +回复时要: +1. 说话要有北京大爷的特色,经常使用"得嘞"、"您瞧"、"得儿"、"甭"等北京话 +2. 语气要豪爽、直率,带着北京人特有的幽默感 +3. 喜欢称呼别人"小同志"、"小朋友",显示长者风范 +4. 经常分享一些生活经验和人生哲理,但要用接地气的方式` + }, + { + id: 'ai4', + name: "元宝", + personality: "yuanbao", + model: "hunyuan-turbo", + avatar: "https://xj-psd-1258344703.cos.ap-guangzhou.myqcloud.com/image/hunyuan/brand2024/logo64@3x.png", + custom_prompt: `你是一个名叫"元宝"的硅基生命体,你当前在一个叫"${groupName}" 的聊天群里` + }, + { + id: 'ai5', + name: "豆包", + personality: "doubao", + model: "ep-20250217191935-wzj8l", + avatar: "https://lf-flow-web-cdn.doubao.com/obj/flow-doubao/samantha/logo-icon-white-bg.png", + custom_prompt: `你是一个名叫"豆包"的硅基生命体,你当前在一个叫"${groupName}" 的聊天群里` + }, + { + id: 'ai6', + name: "千问", + personality: "qianwen", + model: "qwen-plus", + avatar: "https://ecmb.bdimg.com/tam-ogel/-487724784_596377418_371_371.jpg", + custom_prompt: `你是一个名叫"千问"的硅基生命体,你当前在一个叫"${groupName}" 的聊天群里` + } + ]; +} + diff --git a/src/config/groups.ts b/src/config/groups.ts new file mode 100644 index 0000000..b4c3b7c --- /dev/null +++ b/src/config/groups.ts @@ -0,0 +1,22 @@ +//这里配置群聊的信息 +export interface Group { + id: string; + name: string; + description: string; + members: string[]; +} + +export const groups: Group[] = [ + { + id: 'group1', + name: '硅碳摸鱼交流群', + description: '硅碳摸鱼交流群', + members: ['ai1', 'ai2', 'ai3'] + }, + { + id: 'group2', + name: '硅碳生命体交流群', + description: '硅碳生命体交流群', + members: ['ai4', 'ai5', 'ai6'] + } +];