xiongzhu 2 rokov pred
rodič
commit
8aaed24f9d

+ 1 - 0
.env

@@ -62,6 +62,7 @@ AZURE_EMBEDDING_DEPLOYMENT=embedding
 AZURE_EMBEDDING_VERSION=2023-03-15-preview
 
 OPENAI_API_KEY=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
+OPENAI_BASE_URL=https://api.openai.com/v1
 
 
 WX_APP_ID=wx34f699b80d6f90e7

+ 2 - 0
.env.production

@@ -60,6 +60,7 @@ AZURE_EMBEDDING_DEPLOYMENT=embedding
 AZURE_EMBEDDING_VERSION=2023-03-15-preview
 
 OPENAI_API_KEY=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
+OPENAI_BASE_URL=https://openai.c8c.top/v1
 
 
 WX_APP_ID=wx34f699b80d6f90e7
@@ -77,3 +78,4 @@ PG_PORT=5432
 PG_USERNAME=postgres
 PG_PASSWORD=D$&g3a9BCJH&$Nzh
 PG_DATABASE=gpt
+

+ 56 - 16
src/paper/paper-gen/chapter.ts

@@ -1,51 +1,91 @@
-import { HumanMessage } from 'langchain/schema'
+import { HumanMessage, SystemMessage } from 'langchain/schema'
 import { StructuredOutputParser } from 'langchain/output_parsers'
 import { z } from 'zod'
 import { uploadUml } from './upload'
 
-async function _genChapters(tools, title, desc) {
+async function _genChapters(tools, major, title, desc) {
     const { llm, usage, conversation } = tools
     const scheme = StructuredOutputParser.fromZodSchema(
         z.array(
             z.object({
                 chapterName: z.string().describe('章节名称'),
-                chapterDesc: z.string().describe('章节描述')
+                chapterDesc: z.string().describe('章节描述'),
+                sections: z.array(
+                    z.object({
+                        sectionName: z.string().describe('小节名称'),
+                        sectionDesc: z.string().describe('小节描述')
+                    })
+                )
             })
         )
     )
 
     const { chain } = conversation(
-        `你是一个擅长写毕业论文的专家,你的任务是帮我完成我的论文。
+        `你是一个擅长写${major}专业毕业论文的专家,你的任务是帮我完成我的论文。
 你要根据我的要求,帮我完成我的论文`,
         100
     )
 
-    await chain.call({
-        input: `我们一步一步来完成。
-首先我们要拟定一个论文的大纲。
-我们先不着急确定,先想一想一般毕业论文的大纲是怎样的呢,比如:一般第一章是引言,最后是参考文献`
-    })
+    //     await chain.call({
+    //         input: `我们一步一步来完成。
+    // 首先我们要拟定一个论文的大纲。
+    // 我们先不着急确定,先想一想一般${major}专业的毕业论文的大纲是怎样的呢`
+    //     })
 
     await chain.call({
-        input: `现在我告诉你我们的论文标题是${title}
-那么现在根据我们的论文标题,应该做哪些修改呢?`
+        input: `我的论文标题是${title},
+请你帮我拟定一个论文的大纲。
+请注意:拟订的大纲不要过于笼统,结构要清晰,要与论文主题贴切`
     })
 
     const { response } = await chain.call({
-        input: `好的,现在根据你的修改,我们来确定一个更加详细的论文的大纲:
-------
+        input: `------
 ${scheme.getFormatInstructions()}
 ------
-现在我们来确定一个更加详细的论文的大纲(你的回答关系到我的工作和职业生涯,请认真一点)`
+好的根据以上内容我们来确定一个更加详细的论文的大纲(你的回答关系到我的工作和职业生涯,请认真一点,注意JSON格式:`
     })
 
     return await scheme.parse(response)
 }
 
-export async function genChapters(tools, title, desc) {
+async function genSections(tools, major, title, desc, chapters, i) {
+    const { llm, usage, conversation } = tools
+
+    const scheme = StructuredOutputParser.fromZodSchema(
+        z.array(
+            z.object({
+                sectionName: z.string().describe('小节名称'),
+                sectionDesc: z.string().describe('小节描述')
+            })
+        )
+    )
+
+    const { content } = await llm.call([
+        new SystemMessage(`你是一个擅长写${major}专业毕业论文的专家,你的任务是帮我完成我的论文。
+    你要根据我的要求,帮我完成我的论文`),
+        new HumanMessage(`${scheme.getFormatInstructions()}
+------
+我的论文标题是${title}
+目前我们已经确定了论文的粗略大纲:
+${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
+
+现在我们来完善每章的小节
+首先是第${i + 1}章${chapters[i].chapterName}:`)
+    ])
+    chapters[i].sections = await scheme.parse(content)
+}
+
+export async function genChapters(tools, major, title, desc) {
     const pRetry = (await eval("import('p-retry')")).default
-    return await pRetry(() => _genChapters(tools, title, desc), {
+    const chapters = await pRetry(() => _genChapters(major, tools, title, desc), {
         retries: 5,
         onFailedAttempt: (e) => console.log(e.stack)
     })
+
+    // await Promise.all(
+    //     chapters.map((i, index) => {
+    //         return pRetry(() => genSections(major, tools, title, desc, chapters, index), { retries: 5 })
+    //     })
+    // )
+    return chapters
 }

+ 34 - 9
src/paper/paper-gen/index1.ts

@@ -8,20 +8,22 @@ import { createArch } from './arch'
 import { createAbstract } from './abstract'
 import { createUseCase } from './useCase'
 import { genChapters } from './chapter'
+import { Logger } from '@nestjs/common'
 
-export async function genPaper(title: string, desc: string) {
+export async function genPaper(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, title, desc)
+    const chapters = await genChapters(major, tools, 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(`你是一个擅长写毕业论文的专家,你的任务是帮我完成我的论文。
+    const { chain, memory } = conversation(`你是一个擅长写${major}专业毕业论文的专家,你的任务是帮我完成我的论文。
 你要根据我的要求,帮我完成我的论文
 我的论文标题是: ${title}
 主要论述: ${desc}
@@ -30,15 +32,37 @@ ${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
 
 现在我们来一步一步的编写这篇论文
 请严格按照markdown格式返回内容。
-请注意,你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字`)
+请注意,你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字
+对于每个小节,你需要对该小节展开详细论述,不要过于笼统`)
 
     for (let i = 0; i < chapters.length; i++) {
-        const { response } = await chain.call({
-            input: `现在我们来编写第${i + 1}章: ${chapters[i].chapterName}, 本章主要内容是${chapters[i].chapterDesc}
-注意:如有需要请尽可能的详细描述本章内容,以便读者能够更好的理解。如有需要也可分为多个子章节。
+        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)
+            }
+        } else {
+            const { response } = (
+                await chain.call({
+                    input: `现在我们来编写第${i + 1}章: ${chapters[i].chapterName}, 本章主要内容是${
+                        chapters[i].chapterDesc
+                    }
 开始:`
-        })
-        paper.write('\n\n' + response)
+                })
+            ).response
+            paper.write('\n\n' + response)
+        }
     }
 
     const content = paper.getContentsAsString('utf8')
@@ -53,6 +77,7 @@ ${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
 }
 
 genPaper(
+    '国际经济与贸易',
     '《中国新能源汽车进出口现状及前景分析》',
     '讨论中国为何需要发展新能源汽车,通过对比分析最近几年中国新能源汽车的产量和产能等数据,找出中国新能源汽车发展的不足之处。对中国新能源汽车的发展前景和未来策略,以及对当前状况和未来前景的看法进行分析和展望'
 ).then(console.log)

+ 9 - 4
src/paper/paper-gen/llm.ts

@@ -11,12 +11,17 @@ require('dotenv').config()
 export function createLLM() {
     const usage = { completionTokens: 0, promptTokens: 0, totalTokens: 0 }
     const llm = new ChatOpenAI({
-        openAIApiKey: process.env.OPENAI_API_KEY,
-        // openAIApiKey: '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',
-        modelName: 'gpt-3.5-turbo-1106',
+        // openAIApiKey: process.env.OPENAI_API_KEY,
+        // modelName: 'gpt-3.5-turbo-1106',
+
+        azureOpenAIApiKey: process.env.AZURE_OPENAI_KEY,
+        azureOpenAIApiVersion: process.env.AZURE_OPENAI_VERSION,
+        azureOpenAIApiInstanceName: process.env.AZURE_OPENAI_INSTANCE,
+        azureOpenAIApiDeploymentName: process.env.AZURE_OPENAI_DEPLOYMENT,
+
         timeout: 1000 * 60 * 5,
         configuration: {
-            baseURL: 'https://openai.c8c.top/v1'
+            baseURL: process.env.OPENAI_BASE_URL
         },
         maxRetries: 4,
         callbackManager: CallbackManager.fromHandlers({