xiongzhu 2 anni fa
parent
commit
89272146b4

+ 1 - 1
.env

@@ -62,7 +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
+OPENAI_BASE_URL=https://openai.c8c.top/v1
 
 
 WX_APP_ID=wx34f699b80d6f90e7

+ 5 - 1
src/paper/entities/paper-order.entity.ts

@@ -3,7 +3,7 @@ import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeor
 export enum PaperOrderStatus {
     Pending = 'pending',
     Generating = 'generating',
-    Complete = 'complete'
+    Complete = 'complete' 
 }
 
 @Entity()
@@ -20,6 +20,9 @@ export class PaperOrder {
     @Column()
     title: string
 
+    @Column()
+    major: string
+
     @Column({ type: 'text' })
     description: string
 
@@ -28,4 +31,5 @@ export class PaperOrder {
 
     @Column({ type: 'enum', enum: PaperOrderStatus, default: PaperOrderStatus.Pending })
     status: PaperOrderStatus
+
 }

+ 53 - 9
src/paper/paper-gen/index1.ts → src/paper/paper-gen/general.ts

@@ -9,8 +9,9 @@ import { createAbstract } from './abstract'
 import { createUseCase } from './useCase'
 import { genChapters } from './chapter'
 import { Logger } from '@nestjs/common'
+import { HumanMessage, SystemMessage } from 'langchain/schema'
 
-export async function genPaper(major: string, title: string, desc: string) {
+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
@@ -32,8 +33,7 @@ ${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
 
 现在我们来一步一步的编写这篇论文
 请严格按照markdown格式返回内容。
-请注意,你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字
-对于每个小节,你需要对该小节展开详细论述,不要过于笼统`)
+请注意,你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字`)
 
     for (let i = 0; i < chapters.length; i++) {
         let response
@@ -45,7 +45,9 @@ ${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}
                         chapters[i].chapterDesc
                     }
 我们分为多个小节编写:
-${chapters[i].sections.map((e) => `- ${e.sectionName}\n    ${e.sectionDesc}`).join('\n')}`
+${chapters[i].sections.map((e) => `- ${e.sectionName}\n    ${e.sectionDesc}`).join('\n')}
+
+对于每个小节,你需要用三段格式对该小节展开详细论述`
                 }
                 input += `\n现在我们开始编写第${j + 1}小节${chapters[i].sections[j].sectionName}的内容:`
 
@@ -76,8 +78,50 @@ ${chapters[i].sections.map((e) => `- ${e.sectionName}\n    ${e.sectionDesc}`).jo
     }
 }
 
-genPaper(
-    '国际经济与贸易',
-    '《中国新能源汽车进出口现状及前景分析》',
-    '讨论中国为何需要发展新能源汽车,通过对比分析最近几年中国新能源汽车的产量和产能等数据,找出中国新能源汽车发展的不足之处。对中国新能源汽车的发展前景和未来策略,以及对当前状况和未来前景的看法进行分析和展望'
-).then(console.log)
+export async function genGeneralPaper1(major: string, title: string, desc: string) {
+    const tools = createLLM('gpt-3.5-turbo')
+    const { llm, usage, conversation } = tools
+    const pRetry = (await eval("import('p-retry')")).default
+
+    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`)
+
+    for (let i = 0; i < chapters.length; i++) {
+        const sysPrompt = `你是一个擅长写${major}专业毕业论文的专家。
+你的任务是写一篇标题为"${title}"的论文。以下是本论文的大纲,请你根据大纲分章节帮我生成文章:
+${chapters.map((i) => `- ${i.chapterName}\n    ${i.chapterDesc}`).join('\n')}`
+        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
+每小节的主要论述内容应采用五段式结构进行论述,论述内容应尽量详细且逻辑清晰。
+语气应正式,内容应适合和吸引一般读者。
+请严格按照markdown格式返回内容。
+你只需要输出能够直接出现在论文中的内容,不需要输出你对该内容的总结或者介绍等其他文字,不需要出现介绍下一章或其他承上启下的文字。
+第${i + 1}章:${chapters[i].chapterName}:`
+        const { content } = await llm.call([new SystemMessage(sysPrompt), new HumanMessage(prompt)])
+        if (!content.includes(chapters[i].chapterName)) {
+            paper.write(`\n\n# ${chapters[i].chapterName}`)
+        }
+        paper.write('\n\n' + content)
+    }
+
+    const content = paper.getContentsAsString('utf8')
+    const duration = (Date.now() - startTime) / 1000
+    const fileUrl = await uploadDoc(title, content)
+    return {
+        content,
+        duration,
+        tokenUsage: usage,
+        fileUrl
+    }
+}

+ 7 - 7
src/paper/paper-gen/llm.ts

@@ -8,16 +8,16 @@ import { Logger } from '@nestjs/common'
 import { writeFile, mkdirSync, appendFileSync } from 'fs'
 import path = require('path')
 require('dotenv').config()
-export function createLLM() {
+export function createLLM(model = 'gpt-3.5-turbo-16k') {
     const usage = { completionTokens: 0, promptTokens: 0, totalTokens: 0 }
     const llm = new ChatOpenAI({
-        // openAIApiKey: process.env.OPENAI_API_KEY,
-        // modelName: 'gpt-3.5-turbo-1106',
+        openAIApiKey: process.env.OPENAI_API_KEY,
+        modelName: model,
 
-        azureOpenAIApiKey: process.env.AZURE_OPENAI_KEY,
-        azureOpenAIApiVersion: process.env.AZURE_OPENAI_VERSION,
-        azureOpenAIApiInstanceName: process.env.AZURE_OPENAI_INSTANCE,
-        azureOpenAIApiDeploymentName: process.env.AZURE_OPENAI_DEPLOYMENT,
+        // 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: {

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

@@ -7,8 +7,9 @@ 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'
 
-@Injectable() 
+@Injectable()
 export class PaperService implements OnModuleInit {
     constructor(
         @InjectRepository(PaperOrder)
@@ -68,7 +69,16 @@ export class PaperService implements OnModuleInit {
 
     async genPaper(order: PaperOrder) {
         try {
-            const { content, duration, tokenUsage, fileUrl } = await genPaper(order.title, order.description)
+            let content, duration, tokenUsage, fileUrl
+            if (/计算机/.test(order.major)) {
+                ;({ content, duration, tokenUsage, fileUrl } = await genPaper(order.title, order.description))
+            } else {
+                ;({ content, duration, tokenUsage, fileUrl } = await genGeneralPaper1(
+                    order.major,
+                    order.title,
+                    order.description
+                ))
+            }
             await this.paperGenResultRepository.save({
                 orderId: order.id,
                 content,