| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- "use strict";
- /**
- * 学习路径生成服务
- * 支持两种模式:
- * 1. progressive(渐进确认) - 用户在每步确认后继续
- * 2. multi-agent(多Agent并行) - 全自动并行生成
- */
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.createLearningPath = createLearningPath;
- exports.getLearningPathDetail = getLearningPathDetail;
- exports.getUserTasks = getUserTasks;
- exports.getPendingConfirmation = getPendingConfirmation;
- exports.confirmAndContinue = confirmAndContinue;
- exports.regenerateNode = regenerateNode;
- exports.getAgentStatus = getAgentStatus;
- const axios_1 = __importDefault(require("axios"));
- const config_1 = require("../../config");
- const models_1 = require("../../models");
- /**
- * 获取可用模型列表
- */
- function getAvailableModels() {
- return config_1.config.models.getModelsByType('text').filter((m) => m.enabled !== false);
- }
- function getRandomModel() {
- const models = getAvailableModels();
- return models[Math.floor(Math.random() * models.length)].id;
- }
- /**
- * 调用 LLM API
- */
- async function callLLM(prompt) {
- const modelId = getRandomModel();
- const modelConfig = config_1.config.models.getModel(modelId);
- if (!modelConfig) {
- throw new Error(`模型 ${modelId} 不存在`);
- }
- const { apiKey, baseUrl } = modelConfig;
- if (!apiKey || !baseUrl) {
- throw new Error(`模型 ${modelId} 缺少 API 配置`);
- }
- try {
- const response = await axios_1.default.post(`${baseUrl}/chat/completions`, {
- model: modelId,
- messages: [{ role: 'user', content: prompt }],
- }, {
- headers: {
- 'Authorization': `Bearer ${apiKey}`,
- 'Content-Type': 'application/json',
- },
- timeout: 180000,
- });
- const data = response.data;
- return data.choices?.[0]?.message?.content || '';
- }
- catch (error) {
- console.error('❌ LLM 调用失败:', error.message);
- throw new Error(error.message || 'AI 生成失败');
- }
- }
- /**
- * 解析 AI 返回的 JSON 列表
- */
- function parseJsonList(aiResponse) {
- const jsonMatch = aiResponse.match(/\[[\s\S]*\]/);
- if (jsonMatch) {
- try {
- const parsed = JSON.parse(jsonMatch[0]);
- if (Array.isArray(parsed)) {
- return parsed.map(item => {
- if (typeof item === 'string')
- return item;
- if (typeof item === 'object' && item !== null) {
- return item.title || item.name || item.chapter_title || item.section_title || item.section || item.chapter || JSON.stringify(item);
- }
- return String(item);
- });
- }
- }
- catch (e) { }
- }
- const lines = aiResponse.split(/[,,\n]/).filter(line => line.trim().length > 0);
- return lines.map(line => line.replace(/^[\d一二三四五六七八九十]+[.、::]\s*/, '').trim()).filter(line => line.length > 0);
- }
- // ============ 通用函数 ============
- /**
- * 创建学习路径任务
- * @param userId 用户ID
- * @param topic 学习主题
- * @param mode 生成模式: progressive | multi-agent
- */
- async function createLearningPath(userId, topic, mode = 'progressive') {
- const task = await models_1.prisma.learningPath.create({
- data: {
- userId,
- topic,
- status: 'pending',
- progress: 0,
- generationMode: mode,
- currentStep: 'pending',
- },
- });
- // 根据模式选择生成方式
- if (mode === 'multi-agent') {
- // 多Agent模式:直接开始全量生成
- generateMultiAgent(task.id).catch(error => {
- console.error('❌ 多Agent生成失败:', error);
- models_1.prisma.learningPath.update({
- where: { id: task.id },
- data: { status: 'failed', errorMsg: error.message },
- }).catch(console.error);
- });
- }
- else {
- // 渐进模式:先生成学科列表等待用户确认
- generateSubjectsStep(task.id).catch(error => {
- console.error('❌ 学科生成失败:', error);
- models_1.prisma.learningPath.update({
- where: { id: task.id },
- data: { status: 'failed', errorMsg: error.message },
- }).catch(console.error);
- });
- }
- return task;
- }
- /**
- * 获取学习路径详情
- */
- async function getLearningPathDetail(id) {
- const task = await models_1.prisma.learningPath.findUnique({
- where: { id },
- include: {
- subjects: {
- orderBy: { orderIndex: 'asc' },
- include: {
- chapters: {
- orderBy: { orderIndex: 'asc' },
- include: {
- sections: {
- orderBy: { orderIndex: 'asc' },
- include: {
- contentBlocks: {
- orderBy: { orderIndex: 'asc' },
- },
- },
- },
- },
- },
- },
- },
- },
- });
- return task;
- }
- /**
- * 获取用户的任务列表
- */
- async function getUserTasks(userId) {
- return models_1.prisma.learningPath.findMany({
- where: { userId },
- orderBy: { createdAt: 'desc' },
- take: 20,
- });
- }
- /**
- * 获取渐进模式的待确认状态
- */
- async function getPendingConfirmation(taskId) {
- const task = await models_1.prisma.learningPath.findUnique({
- where: { id: taskId },
- include: {
- subjects: {
- orderBy: { orderIndex: 'asc' },
- include: {
- chapters: {
- orderBy: { orderIndex: 'asc' },
- include: {
- sections: {
- orderBy: { orderIndex: 'asc' },
- },
- },
- },
- },
- },
- },
- });
- if (!task)
- return null;
- return {
- id: task.id,
- topic: task.topic,
- status: task.status,
- progress: task.progress,
- currentStep: task.currentStep,
- generationMode: task.generationMode,
- // 待确认的学科
- pendingSubjects: task.subjects
- .filter(s => s.confirmationStatus === 'pending')
- .map(s => ({ id: s.id, name: s.name, status: s.status })),
- // 待确认的章节
- pendingChapters: task.subjects.reduce((acc, subject) => {
- acc[subject.id] = subject.chapters
- .filter(c => c.confirmationStatus === 'pending')
- .map(c => ({ id: c.id, name: c.name, status: c.status }));
- return acc;
- }, {}),
- // 待确认的小节
- pendingSections: task.subjects.reduce((acc, subject) => {
- subject.chapters.forEach(chapter => {
- acc[chapter.id] = chapter.sections
- .filter(s => s.confirmationStatus === 'pending')
- .map(s => ({ id: s.id, name: s.name, status: s.status }));
- });
- return acc;
- }, {}),
- };
- }
- /**
- * 确认并继续生成
- * @param taskId 任务ID
- * @param step 当前步骤: subjects | chapters | sections
- * @param confirmedIds 确认的ID列表
- * @param modifiedItems 修改的项 [{id, name}]
- */
- async function confirmAndContinue(taskId, step, confirmedIds, modifiedItems = []) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- // 处理修改项
- for (const item of modifiedItems) {
- if (step === 'subjects') {
- await models_1.prisma.subject.update({ where: { id: item.id }, data: { name: item.name } });
- }
- else if (step === 'chapters') {
- await models_1.prisma.chapter.update({ where: { id: item.id }, data: { name: item.name } });
- }
- }
- // 标记确认的项
- if (step === 'subjects') {
- await models_1.prisma.subject.updateMany({
- where: { id: { in: confirmedIds }, learningPathId: taskId },
- data: { confirmationStatus: 'confirmed' },
- });
- // 更新任务步骤
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { currentStep: 'chapters' },
- });
- // 开始生成章节
- generateChaptersStep(taskId, confirmedIds).catch(console.error);
- return { currentStep: 'chapters' };
- }
- else if (step === 'chapters') {
- await models_1.prisma.chapter.updateMany({
- where: { id: { in: confirmedIds } },
- data: { confirmationStatus: 'confirmed' },
- });
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { currentStep: 'sections' },
- });
- // 开始生成小节
- generateSectionsStep(taskId, confirmedIds).catch(console.error);
- return { currentStep: 'sections' };
- }
- else if (step === 'sections') {
- await models_1.prisma.section.updateMany({
- where: { id: { in: confirmedIds } },
- data: { confirmationStatus: 'confirmed' },
- });
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { currentStep: 'content' },
- });
- // 开始生成详细内容
- generateContentStep(taskId, confirmedIds).catch(console.error);
- return { currentStep: 'content' };
- }
- return { currentStep: task.currentStep };
- }
- /**
- * 重新生成某个节点
- */
- async function regenerateNode(taskId, type, id, instruction) {
- if (type === 'chapter') {
- const chapter = await models_1.prisma.chapter.findUnique({ where: { id } });
- if (!chapter)
- throw new Error('章节不存在');
- await models_1.prisma.chapter.update({ where: { id }, data: { status: 'generating', confirmationStatus: 'regenerating' } });
- // 重新生成小节
- const subject = await models_1.prisma.subject.findUnique({ where: { id: chapter.subjectId } });
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- const sectionsPrompt = `你是课程规划专家。请为"${chapter.name}"这一章生成学习小节列表。
- 要求:
- 1. 生成4-6个小节
- 2. 每个小节应该讲解一个具体的知识点
- 3. 内容要循序渐进,由浅入深
- ${instruction ? `用户额外要求:${instruction}` : ''}
- 请以JSON数组格式返回,只返回纯JSON数组`;
- const sectionsResponse = await callLLM(sectionsPrompt);
- const sectionNames = parseJsonList(sectionsResponse);
- // 删除旧的小节
- await models_1.prisma.contentBlock.deleteMany({ where: { section: { chapterId: id } } });
- await models_1.prisma.section.deleteMany({ where: { chapterId: id } });
- // 创建新的小节
- await Promise.all(sectionNames.map((name, index) => models_1.prisma.section.create({
- data: {
- chapterId: id,
- name,
- orderIndex: index,
- status: 'pending',
- confirmationStatus: 'pending',
- aiResponse: sectionsResponse,
- },
- })));
- await models_1.prisma.chapter.update({ where: { id }, data: { status: 'completed', confirmationStatus: 'confirmed' } });
- return { success: true, newSections: sectionNames };
- }
- else if (type === 'section') {
- const section = await models_1.prisma.section.findUnique({
- where: { id },
- include: { chapter: { include: { subject: true } } },
- });
- if (!section)
- throw new Error('小节不存在');
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- await models_1.prisma.section.update({ where: { id }, data: { status: 'generating', confirmationStatus: 'regenerating' } });
- const contentPrompt = `你是专业的教学老师。请详细讲解以下知识点:
- 知识点:${section.name}
- 所属章节:${section.chapter.name}
- 所属学科:${section.chapter.subject.name}
- 学习主题:${task?.topic}
- ${instruction ? `用户额外要求:${instruction}` : ''}
- 要求:
- 1. 用通俗易懂的语言讲解这个知识点
- 2. 包含"是什么"、"为什么"、"怎么用"三个部分
- 3. 可以给出具体的例子、代码、公式等
- 4. 内容要详实、深入,不少于500字
- 5. 直接返回正文内容,不需要标题`;
- const contentResponse = await callLLM(contentPrompt);
- // 删除旧内容
- await models_1.prisma.contentBlock.deleteMany({ where: { sectionId: id } });
- // 创建新内容
- await models_1.prisma.contentBlock.create({
- data: {
- sectionId: id,
- content: contentResponse,
- orderIndex: 0,
- wordCount: contentResponse.length,
- },
- });
- await models_1.prisma.section.update({ where: { id }, data: { status: 'completed', confirmationStatus: 'confirmed' } });
- return { success: true };
- }
- return { success: false };
- }
- /**
- * 获取多Agent模式的状态
- */
- async function getAgentStatus(taskId) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- return null;
- const agentStatus = task.agentStatus ? JSON.parse(task.agentStatus) : null;
- return {
- mode: task.generationMode,
- status: task.status,
- progress: task.progress,
- agents: agentStatus,
- };
- }
- // ============ 渐进模式函数 ============
- /**
- * 渐进模式 Step 1: 生成学科列表
- */
- async function generateSubjectsStep(taskId) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- console.log(`📚 渐进模式 - 生成学科列表: ${task.topic}`);
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { status: 'generating', currentStep: 'subjects' },
- });
- const subjectsPrompt = `用户想要学习主题:"${task.topic}"
- 请作为一位专业的课程规划专家,为用户规划完整的学习路径。
- 要求:
- 1. 生成该主题下的主要学科/专业课程列表(6-10门核心学科)
- 2. 每门学科应该是构建该领域知识体系所必需的
- 3. 按照合理的学习顺序排列(从基础到进阶)
- 请以JSON数组格式返回学科列表,不要加标题不要加说明,只返回纯JSON数组,例如:
- ["计算机原理", "程序设计基础", "数据结构与算法", "操作系统", "计算机网络", "数据库原理", "软件工程"]`;
- const subjectsResponse = await callLLM(subjectsPrompt);
- const subjectNames = parseJsonList(subjectsResponse);
- console.log('📚 学科列表:', subjectNames);
- // 创建学科记录(带pending确认状态)
- await Promise.all(subjectNames.map((name, index) => models_1.prisma.subject.create({
- data: {
- learningPathId: taskId,
- name,
- orderIndex: index,
- status: 'completed',
- confirmationStatus: 'pending',
- aiResponse: subjectsResponse,
- },
- })));
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { progress: 10 },
- });
- console.log('📚 学科列表生成完成,等待用户确认');
- }
- /**
- * 渐进模式 Step 2: 生成章节 (完全并行)
- */
- async function generateChaptersStep(taskId, subjectIds) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- console.log(`📖 渐进模式 - 并行生成章节 for subjects: ${subjectIds}`);
- const subjects = await models_1.prisma.subject.findMany({
- where: { id: { in: subjectIds } },
- orderBy: { orderIndex: 'asc' },
- });
- // 并行生成所有学科的章节
- await Promise.all(subjects.map(async (subject, i) => {
- console.log(`📖 生成学科章节: ${subject.name}`);
- const chaptersPrompt = `你是课程规划专家。请为"${subject.name}"这门学科生成学习章节列表。
- 要求:
- 1. 生成6-10个核心章节
- 2. 章节应该覆盖该学科的主要知识领域
- 3. 按照合理的教学顺序排列
- 请以JSON数组格式返回,只返回纯JSON数组`;
- try {
- const chaptersResponse = await callLLM(chaptersPrompt);
- const chapterNames = parseJsonList(chaptersResponse);
- console.log(`📖 ${subject.name} - 章节:`, chapterNames);
- // 创建章节记录
- await Promise.all(chapterNames.map((name, index) => models_1.prisma.chapter.create({
- data: {
- subjectId: subject.id,
- name,
- orderIndex: index,
- status: 'completed',
- confirmationStatus: 'pending',
- aiResponse: chaptersResponse,
- },
- })));
- await models_1.prisma.subject.update({
- where: { id: subject.id },
- data: { status: 'completed' },
- });
- // 更新进度
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { progress: 10 + Math.floor(((i + 1) / subjects.length) * 20) },
- });
- }
- catch (error) {
- console.error(`❌ 生成章节失败 ${subject.name}:`, error);
- }
- }));
- console.log('📖 所有章节生成完成,等待用户确认');
- }
- /**
- * 渐进模式 Step 3: 生成小节 (完全并行)
- */
- async function generateSectionsStep(taskId, chapterIds) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- console.log(`📑 渐进模式 - 并行生成小节 for chapters: ${chapterIds}`);
- const chapters = await models_1.prisma.chapter.findMany({
- where: { id: { in: chapterIds } },
- orderBy: { orderIndex: 'asc' },
- include: { subject: true },
- });
- // 并行生成所有章节的小节
- await Promise.all(chapters.map(async (chapter, j) => {
- console.log(`📑 生成章节小节: ${chapter.name}`);
- const sectionsPrompt = `你是课程规划专家。请为"${chapter.name}"这一章生成学习小节列表。
- 要求:
- 1. 生成4-6个小节
- 2. 每个小节应该讲解一个具体的知识点
- 3. 内容要循序渐进,由浅入深
- 请以JSON数组格式返回,只返回纯JSON数组`;
- try {
- const sectionsResponse = await callLLM(sectionsPrompt);
- const sectionNames = parseJsonList(sectionsResponse);
- console.log(`📑 ${chapter.name} - 小节:`, sectionNames);
- // 创建小节记录
- await Promise.all(sectionNames.map((name, index) => models_1.prisma.section.create({
- data: {
- chapterId: chapter.id,
- name,
- orderIndex: index,
- status: 'completed',
- confirmationStatus: 'pending',
- aiResponse: sectionsResponse,
- },
- })));
- await models_1.prisma.chapter.update({
- where: { id: chapter.id },
- data: { status: 'completed' },
- });
- // 更新进度
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { progress: 30 + Math.floor(((j + 1) / chapters.length) * 20) },
- });
- }
- catch (error) {
- console.error(`❌ 生成小节失败 ${chapter.name}:`, error);
- }
- }));
- console.log('📑 所有小节生成完成,等待用户确认');
- }
- /**
- * 渐进模式 Step 4: 生成详细内容 (完全并行)
- */
- async function generateContentStep(taskId, sectionIds) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- console.log(`📝 渐进模式 - 并行生成详细内容 for sections: ${sectionIds}`);
- const sections = await models_1.prisma.section.findMany({
- where: { id: { in: sectionIds } },
- orderBy: { orderIndex: 'asc' },
- include: { chapter: { include: { subject: true } } },
- });
- const totalSections = sections.length;
- // 并行生成所有小节的详细内容
- await Promise.all(sections.map(async (section, k) => {
- console.log(`📝 生成详细内容: ${section.name}`);
- const contentPrompt = `你是专业的教学老师。请详细讲解以下知识点:
- 知识点:${section.name}
- 所属章节:${section.chapter.name}
- 所属学科:${section.chapter.subject.name}
- 学习主题:${task.topic}
- 要求:
- 1. 用通俗易懂的语言讲解这个知识点
- 2. 包含"是什么"、"为什么"、"怎么用"三个部分
- 3. 可以给出具体的例子、代码、公式等
- 4. 内容要详实、深入,不少于500字
- 5. 直接返回正文内容,不需要标题`;
- try {
- const contentResponse = await callLLM(contentPrompt);
- // 创建内容块
- await models_1.prisma.contentBlock.create({
- data: {
- sectionId: section.id,
- content: contentResponse,
- orderIndex: 0,
- wordCount: contentResponse.length,
- },
- });
- // 更新小节状态
- await models_1.prisma.section.update({
- where: { id: section.id },
- data: { status: 'completed', confirmationStatus: 'completed' },
- });
- // 更新进度 (动态计算已完成的小节数)
- const completedSections = k + 1;
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { progress: 50 + Math.floor((completedSections / totalSections) * 50) },
- });
- }
- catch (error) {
- console.error(`❌ 生成内容失败 ${section.name}:`, error);
- }
- }));
- // 统计并完成
- const totalBlocks = await models_1.prisma.contentBlock.count({
- where: {
- section: {
- chapter: {
- subject: { learningPathId: taskId }
- }
- }
- }
- });
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: {
- status: 'completed',
- progress: 100,
- currentStep: 'completed',
- totalCount: totalBlocks,
- completedCount: totalBlocks,
- },
- });
- console.log(`✅ 渐进模式生成完成: ${task.topic}`);
- }
- // ============ 多Agent模式函数 ============
- /**
- * 多Agent模式:全自动并行生成
- */
- async function generateMultiAgent(taskId) {
- const task = await models_1.prisma.learningPath.findUnique({ where: { id: taskId } });
- if (!task)
- throw new Error('任务不存在');
- console.log(`🚀 多Agent模式 - 开始生成学习路径: ${task.topic}`);
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: {
- status: 'generating',
- agentStatus: JSON.stringify([
- { name: '规划Agent', status: 'running', progress: 0 },
- ]),
- },
- });
- try {
- // Step 1: 生成学科列表(规划Agent)
- const subjectsPrompt = `用户想要学习主题:"${task.topic}"
- 请作为一位专业的课程规划专家,为用户规划完整的学习路径。
- 要求:
- 1. 生成该主题下的主要学科/专业课程列表(6-10门核心学科)
- 2. 每门学科应该是构建该领域知识体系所必需的
- 3. 按照合理的学习顺序排列(从基础到进阶)
- 请以JSON数组格式返回学科列表,不要加标题不要加说明,只返回纯JSON数组,例如:
- ["计算机原理", "程序设计基础", "数据结构与算法", "操作系统", "计算机网络", "数据库原理", "软件工程"]`;
- console.log('📚 规划Agent - 生成学科列表...');
- const subjectsResponse = await callLLM(subjectsPrompt);
- const subjectNames = parseJsonList(subjectsResponse);
- console.log('📚 学科列表:', subjectNames);
- // 创建学科记录
- const subjects = await Promise.all(subjectNames.map((name, index) => models_1.prisma.subject.create({
- data: {
- learningPathId: taskId,
- name,
- orderIndex: index,
- status: 'pending',
- aiResponse: subjectsResponse,
- },
- })));
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: {
- agentStatus: JSON.stringify([
- { name: '规划Agent', status: 'completed', progress: 100 },
- { name: '学科Agent群', status: 'running', progress: 0 },
- ]),
- progress: 10,
- },
- });
- // Step 2: 并行为每个学科生成章节(学科Agent群)
- await Promise.all(subjects.map(async (subject, i) => {
- console.log(`📖 学科Agent[${i}] - 生成章节: ${subject.name}`);
- const chaptersPrompt = `你是课程规划专家。请为"${subject.name}"这门学科生成学习章节列表。
- 要求:
- 1. 生成6-10个核心章节
- 2. 章节应该覆盖该学科的主要知识领域
- 3. 按照合理的教学顺序排列
- 请以JSON数组格式返回,只返回纯JSON数组`;
- const chaptersResponse = await callLLM(chaptersPrompt);
- const chapterNames = parseJsonList(chaptersResponse);
- const chapters = await Promise.all(chapterNames.map((name, index) => models_1.prisma.chapter.create({
- data: {
- subjectId: subject.id,
- name,
- orderIndex: index,
- status: 'pending',
- aiResponse: chaptersResponse,
- },
- })));
- await models_1.prisma.subject.update({
- where: { id: subject.id },
- data: { status: 'generating' },
- });
- // Step 3: 并行为每个章节生成小节
- await Promise.all(chapters.map(async (chapter) => {
- const sectionsPrompt = `你是课程规划专家。请为"${chapter.name}"这一章生成学习小节列表。
- 要求:
- 1. 生成4-6个小节
- 2. 每个小节应该讲解一个具体的知识点
- 3. 内容要循序渐进,由浅入深
- 请以JSON数组格式返回,只返回纯JSON数组`;
- const sectionsResponse = await callLLM(sectionsPrompt);
- const sectionNames = parseJsonList(sectionsResponse);
- const sections = await Promise.all(sectionNames.map((name, index) => models_1.prisma.section.create({
- data: {
- chapterId: chapter.id,
- name,
- orderIndex: index,
- status: 'pending',
- aiResponse: sectionsResponse,
- },
- })));
- await models_1.prisma.chapter.update({
- where: { id: chapter.id },
- data: { status: 'completed' },
- });
- // Step 4: 并行为每个小节生成详细内容
- await Promise.all(sections.map(async (section) => {
- const contentPrompt = `你是专业的教学老师。请详细讲解以下知识点:
- 知识点:${section.name}
- 所属章节:${chapter.name}
- 所属学科:${subject.name}
- 学习主题:${task.topic}
- 要求:
- 1. 用通俗易懂的语言讲解这个知识点
- 2. 包含"是什么"、"为什么"、"怎么用"三个部分
- 3. 可以给出具体的例子、代码、公式等
- 4. 内容要详实、深入,不少于500字
- 5. 直接返回正文内容,不需要标题`;
- try {
- const contentResponse = await callLLM(contentPrompt);
- await models_1.prisma.contentBlock.create({
- data: {
- sectionId: section.id,
- content: contentResponse,
- orderIndex: 0,
- wordCount: contentResponse.length,
- },
- });
- await models_1.prisma.section.update({
- where: { id: section.id },
- data: { status: 'completed' },
- });
- }
- catch (error) {
- console.error(`❌ 生成内容失败 ${section.name}:`, error);
- }
- }));
- }));
- await models_1.prisma.subject.update({
- where: { id: subject.id },
- data: { status: 'completed' },
- });
- // 更新学科Agent进度
- const subjectProgress = Math.floor(((i + 1) / subjects.length) * 40) + 10;
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: {
- progress: subjectProgress,
- agentStatus: JSON.stringify([
- { name: '规划Agent', status: 'completed', progress: 100 },
- { name: '学科Agent群', status: 'running', progress: subjectProgress },
- ]),
- },
- });
- }));
- // 统计并完成
- const totalBlocks = await models_1.prisma.contentBlock.count({
- where: {
- section: {
- chapter: {
- subject: { learningPathId: taskId }
- }
- }
- }
- });
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: {
- status: 'completed',
- progress: 100,
- totalCount: totalBlocks,
- completedCount: totalBlocks,
- agentStatus: JSON.stringify([
- { name: '规划Agent', status: 'completed', progress: 100 },
- { name: '学科Agent群', status: 'completed', progress: 100 },
- { name: '整合Agent', status: 'completed', progress: 100 },
- ]),
- },
- });
- console.log(`✅ 多Agent模式生成完成: ${task.topic}`);
- }
- catch (error) {
- console.error('❌ 多Agent生成失败:', error);
- await models_1.prisma.learningPath.update({
- where: { id: taskId },
- data: { status: 'failed', errorMsg: error.message },
- });
- throw error;
- }
- }
|