xiongzhu 2 anos atrás
pai
commit
4fe1903174

+ 6 - 0
1.md

@@ -1,3 +1,9 @@
+- laskdjfklasdf
+    - lksdjfksdf
+    - lksjdkf
+        - lksdflksdf
+            - lkajsdlkfjsdf
+
 我的毕业设计项目是基于Java的电器销售系统
 这个项目包含以下功能:本管理系统采用的集成开发环境为Eclipse,使用Java等语言及 SSM框架进行开发:
 用户:注册登录,个人中心,公告消息、电器资讯、电器商城、留言反馈。

+ 1 - 0
package.json

@@ -46,6 +46,7 @@
     "@nestjs/throttler": "^4.0.0",
     "@nestjs/typeorm": "^9.0.1",
     "@opensearch-project/opensearch": "^2.3.1",
+    "@siakhooi/number-to-chinese-words": "^1.12.4",
     "ali-oss": "^6.17.1",
     "axios": "^1.3.6",
     "azure-openai": "^0.9.4",

+ 4 - 4
src/paper/paper-gen/abstract.ts

@@ -18,10 +18,10 @@ ${desc}
 
     const abstract = content.replace(/^摘要[::][\s\n]+/, '')
     const { content: translated } = await llm.call([
-        new SystemMessage(
-            '我希望你能担任英语翻译、拼写校对和修辞改进的角色。请将我给你的内容,用更为优美和精炼的英语翻译给我。请确保意思不变,但使其更具文学性。'
-        ),
-        new HumanMessage(abstract)
+        new SystemMessage('You are a translator, translate directly without explanation'),
+        new HumanMessage(`Translate the following text from Chinese to English without the style of machine translation.
+------
+${abstract}`)
     ])
 
     return `# 摘要\n\n${abstract}\n\n# Abstract\n\n${translated}`

+ 23 - 5
src/paper/paper-gen/chapter.ts

@@ -10,11 +10,9 @@ async function _genChapters(tools: LLMTools, major: string, title: string, desc:
         z.array(
             z.object({
                 chapterName: z.string().describe('章节名称'),
-                chapterDesc: z.string().describe('章节描述'),
                 sections: z.array(
                     z.object({
-                        sectionName: z.string().describe('小节名称'),
-                        sectionDesc: z.string().describe('小节描述')
+                        sectionName: z.string().describe('小节名称')
                     })
                 )
             })
@@ -48,7 +46,27 @@ ${scheme.getFormatInstructions()}
 
     return await scheme.parse(response)
 }
-
+function formatChapters(chapters: any[]) {
+    chapters.forEach((item: any) => {
+        if (item.chapterName) {
+            item.title = item.chapterName
+        } else {
+            item.title = item.sectionName
+        }
+        if (item.sections) {
+            item.children = item.sections
+        }
+        delete item.sections
+        delete item.chapterName
+        delete item.chapterDesc
+        delete item.sectionName
+        delete item.sectionDesc
+        if (item.children) {
+            formatChapters(item.children)
+        }
+    })
+    return chapters
+}
 export async function genChapters(tools: LLMTools, major, title, desc) {
     const pRetry = (await eval("import('p-retry')")).default
     const chapters = await pRetry(() => _genChapters(tools, major, title, desc), {
@@ -61,5 +79,5 @@ export async function genChapters(tools: LLMTools, major, title, desc) {
     //         return pRetry(() => genSections(major, tools, title, desc, chapters, index), { retries: 5 })
     //     })
     // )
-    return chapters
+    return formatChapters(chapters)
 }

+ 70 - 87
src/paper/paper-gen/general.ts

@@ -1,89 +1,50 @@
 import { WritableStreamBuffer } from 'stream-buffers'
 import { createLLM } from './llm'
-import { createFlow } from './flow'
-import { createER } from './er'
-import { createTable } from './table'
 import { uploadDoc } from './upload'
-import { createArch } from './arch'
-import { createAbstract } from './abstract'
-import { createUseCase } from './useCase'
 import { genChapters } from './chapter'
 import { Logger } from '@nestjs/common'
 import { HumanMessage, SystemMessage } from 'langchain/schema'
+import * as NumberToChinese from '@siakhooi/number-to-chinese-words'
+import { createAbstract } from './abstract'
 
-export async function genGeneralPaper(major: string, title: string, desc: string) {
-    const tools = createLLM()
-    const { llm, usage, conversation } = tools
-    const pRetry = (await eval("import('p-retry')")).default
-
-    const chapters = await genChapters(tools, major, title, desc)
-    Logger.log(JSON.stringify(chapters, null, 4))
-
-    let paper = new WritableStreamBuffer()
-    const startTime = Date.now()
-
-    paper.write(`${await createAbstract(tools, title, desc)}\n\n`)
-
-    const { chain, memory } = conversation(`你是一个擅长写${major}专业毕业论文的专家,你的任务是帮我完成我的论文。
-你要根据我的要求,帮我完成我的论文
-我的论文标题是: ${title}
-主要论述: ${desc}
-现在我们已经为论文拟好了一个大纲:
-${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
-
-现在我们来一步一步的编写这篇论文
-请严格按照markdown格式返回内容。
-请注意,你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字`)
-
-    for (let i = 0; i < chapters.length; i++) {
-        let response
-        if (chapters[i].sections && chapters[i].sections.length) {
-            for (let j = 0; j < chapters[i].sections.length; j++) {
-                let input = ''
-                if (j == 0) {
-                    input = `现在我们来编写第${i + 1}章: ${chapters[i].chapterName}, 本章主要内容是${
-                        chapters[i].chapterDesc
-                    }
-我们分为多个小节编写:
-${chapters[i].sections.map((e) => `- ${e.sectionName}\n    ${e.sectionDesc}`).join('\n')}
-
-对于每个小节,你需要用三段格式对该小节展开详细论述`
-                }
-                input += `\n现在我们开始编写第${j + 1}小节${chapters[i].sections[j].sectionName}的内容:`
-
-                const { response } = await chain.call({ input })
-                paper.write('\n\n' + response)
-            }
+function chapters2md(chapters, sub = []) {
+    let md = ''
+    const list: any[] = []
+    function _update(_data: any, level: number) {
+        _data.forEach((e: any) => {
+            list.push({
+                title: e.title,
+                level
+            })
+            if (e.children) _update(e.children, level + 1)
+        })
+    }
+    _update(chapters, 0)
+    const levels = [0, 0, 0, 0]
+    for (const child of list) {
+        const level = child.level
+        levels[level] = levels[level] + 1
+        for (let i = level + 1; i < levels.length; i++) {
+            levels[i] = 0
+        }
+        let title
+        if (level === 0 && !sub.length) {
+            title = ''
         } else {
-            const { response } = (
-                await chain.call({
-                    input: `现在我们来编写第${i + 1}章: ${chapters[i].chapterName}, 本章主要内容是${
-                        chapters[i].chapterDesc
-                    }
-开始:`
-                })
-            ).response
-            paper.write('\n\n' + response)
+            title = levels.slice(0, level + 1).join('.') + ' '
         }
-    }
 
-    const content = paper.getContentsAsString('utf8')
-    const duration = (Date.now() - startTime) / 1000
-    const fileUrl = await uploadDoc(title, content)
-    return {
-        content,
-        duration,
-        tokenUsage: usage,
-        fileUrl
+        md += `${'    '.repeat(level)}- ${title}${child.title}\n`
     }
+    return md
 }
 
-export async function genGeneralPaper1(major: string, title: string, desc: string) {
+export async function genGeneralPaper1(major: string, title: string, desc: string, chapters) {
     const tools = createLLM('gpt-3.5-turbo')
     const { llm, usage, conversation } = tools
     const pRetry = (await eval("import('p-retry')")).default
 
-    const chapters = await genChapters(tools, major, title, desc)
+    chapters = chapters || (await genChapters(tools, major, title, desc))
     Logger.log(JSON.stringify(chapters, null, 4))
 
     let paper = new WritableStreamBuffer()
@@ -92,30 +53,52 @@ export async function genGeneralPaper1(major: string, title: string, desc: strin
     paper.write(`${await createAbstract(tools, title, desc)}\n\n`)
 
     for (let i = 0; i < chapters.length; i++) {
+        const chapter = chapters[i]
         const sysPrompt = `你是一个擅长写${major}专业毕业论文的专家。
 你的任务是写一篇标题为"${title}"的论文。
-以下是论文的大纲
-${chapters.map((i, index) => `${index + 1}. ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
+全文按照以下章节组织
+${chapters2md(chapters)}
 
-你要根据大纲分章节帮我生成文章。
 你的语气应正式,内容应适合和吸引一般读者。
 你要严格按照markdown格式返回内容。
-你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字,不需要出现介绍下一章或其他承上启下的文字。`
-        let prompt = `第${i + 1}章是:${chapters[i].chapterName},本章主要内容是${chapters[i].chapterDesc}`
-        if (chapters[i].sections && chapters[i].sections.length) {
-            prompt += `\n本章分为多个小节,每小节的主要论述内容应采用五段式结构进行论述,论述内容应尽量详细且逻辑清晰。
-以下是各小节的简介:
-${chapters[i].sections.map((e) => `- ${e.sectionName}\n    ${e.sectionDesc}`).join('\n')}
-
-请按照此结构一次性完成本章内容`
-        }
-        prompt += `\n
-第${i + 1}章:# ${chapters[i].chapterName}:`
-        const { content } = await llm.call([new SystemMessage(sysPrompt), new HumanMessage(prompt)])
-        if (!content.trim().split('\n')[0].includes(chapters[i].chapterName)) {
-            paper.write(`\n\n# ${chapters[i].chapterName}`)
+不要擅作主张输出你对该内容的总结或者介绍等其他文字,不需要出现介绍下一章或其他承上启下的文字。
+你要严格遵守我的指令,按照我的指定的章节和小节完成论文的写作。
+请直接开始写作,不要对内容作任何解释。`
+        paper.write('\n\n# ' + chapter.title)
+        if (chapter.children && chapter.children.length) {
+            // for (let j = 0; j < chapter.children.length; j++) {
+            //     const section = chapter.children[j]
+            //     paper.write(`\n\n## ${i + 1}.${j + 1} ${section.title}`)
+            //     let prompt = `第${i + 1}章: # ${chapter.title}`
+            //     prompt += `\n## ${i + 1}.${j + 1} ${section.title} (请注意只需要编写这一小节的内容):`
+            //     const { content } = await llm.call([new SystemMessage(sysPrompt), new HumanMessage(prompt)])
+            //     paper.write('\n\n' + content)
+            // }
+
+            paper.write(
+                '\n\n' +
+                    (
+                        await Promise.all(
+                            chapter.children.map(async (section, j) => {
+                                let prompt = `第${i + 1}章: # ${chapter.title}`
+                                prompt += `\n## ${i + 1}.${j + 1} ${section.title} (请注意只需要编写这一小节的内容):`
+                                const { content } = await llm.call([
+                                    new SystemMessage(sysPrompt),
+                                    new HumanMessage(prompt)
+                                ])
+                                return `## ${i + 1}.${j + 1} ${section.title}\n\n` + content
+                            })
+                        )
+                    ).join('\n\n')
+            )
+        } else {
+            let prompt = `第${i + 1}章: # ${chapter.title}`
+            const { content } = await llm.call([new SystemMessage(sysPrompt), new HumanMessage(prompt)])
+            // if (!content.trim().split('\n')[0].includes(chapter.title)) {
+            //     paper.write(`\n\n# ${chapter.title}`)
+            // }
+            paper.write('\n\n' + content)
         }
-        paper.write('\n\n' + content)
     }
 
     let content = paper.getContentsAsString('utf8').split('\n')

+ 3 - 2
src/paper/paper.service.ts

@@ -7,7 +7,7 @@ import { Pagination, paginate } from 'nestjs-typeorm-paginate'
 import { PageRequest } from 'src/common/dto/page-request'
 import { CreatePaperOrderDto } from './dto/create-order.dto'
 import { genPaper } from './paper-gen'
-import { genGeneralPaper, genGeneralPaper1 } from './paper-gen/general'
+import { genGeneralPaper1 } from './paper-gen/general'
 import { createLLM } from './paper-gen/llm'
 import { genChapters } from './paper-gen/chapter'
 
@@ -84,7 +84,8 @@ export class PaperService implements OnModuleInit {
                 ;({ content, duration, tokenUsage, fileUrl } = await genGeneralPaper1(
                     order.major,
                     order.title,
-                    order.description
+                    order.description,
+                    order.chapters
                 ))
             }
             await this.paperGenResultRepository.save({

+ 7 - 0
yarn.lock

@@ -1780,6 +1780,13 @@
   resolved "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
   integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
 
+"@siakhooi/number-to-chinese-words@^1.12.4":
+  version "1.12.4"
+  resolved "https://registry.npmmirror.com/@siakhooi/number-to-chinese-words/-/number-to-chinese-words-1.12.4.tgz#5cfc758427281f8c2197551aaa1707516f655da4"
+  integrity sha512-/94LlVgPqm3tlMmdGGchmJ9cD7FrZ/maKbpzBeoXv4TyasCDFu1wnA5uO/uDTzeGxJrrkvWmSiR53S7w+cRZ5w==
+  dependencies:
+    ts-node "^10.9.1"
+
 "@sinclair/typebox@^0.27.8":
   version "0.27.8"
   resolved "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"