Commit 805da8c5 by hometown

feat: done

parent 39a13350
# 系统配置
PORT=3333
PREFIX=chh-api
# 丝袜哥
SWAGGER_VERSION='v1'
# 百度千帆配置
ERNIE_BOT_AK=mXQIDW260qBbNgQRF0p1YFgn
ERNIE_BOT_SK=hzriOtzGiDkd1S0wFwiyr7WlarfufTdi
ERNIE_BOT_KNOWLEDGE_PLUGIN_URL=https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/plugin/8yrkkifr8gccsvck/
ERNIE_BOT_ACCESS_TOKEN_URL=https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials
# 系统配置
PORT=3333
PREFIX=chh-api
# 丝袜哥
SWAGGER_VERSION='v1'
# 百度千帆配置
ERNIE_BOT_AK=mXQIDW260qBbNgQRF0p1YFgn
ERNIE_BOT_SK=hzriOtzGiDkd1S0wFwiyr7WlarfufTdi
ERNIE_BOT_KNOWLEDGE_PLUGIN_URL=https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/plugin/8yrkkifr8gccsvck/
ERNIE_BOT_ACCESS_TOKEN_URL=https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials
module.exports = {presets: ['@babel/preset-env']}
......@@ -55,6 +55,7 @@
},
"devDependencies": {
"@nestjs/cli": "^7.5.3",
"@nestjs/config": "^3.1.1",
"@nestjs/schematics": "^7.2.5",
"@nestjs/testing": "^7.5.5",
"@types/express": "^4.17.9",
......@@ -85,6 +86,9 @@
"json",
"ts"
],
"moduleNameMapper": {
"^axios$": "axios/dist/node/axios.cjs"
},
"rootDir": "src",
"testRegex": ".spec.ts$",
"transform": {
......
......@@ -103,6 +103,9 @@ devDependencies:
'@nestjs/cli':
specifier: ^7.5.3
version: 7.6.0(eslint@7.32.0)
'@nestjs/config':
specifier: ^3.1.1
version: 3.1.1(@nestjs/common@7.6.18)(reflect-metadata@0.1.14)
'@nestjs/schematics':
specifier: ^7.2.5
version: 7.3.1(typescript@5.3.3)
......@@ -762,7 +765,7 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.12.13
'@babel/types': 7.23.6
dev: false
/@babel/parser@7.23.6:
......@@ -1169,8 +1172,8 @@ packages:
'@babel/generator': 7.23.6
'@babel/helper-function-name': 7.23.0
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.12.16
'@babel/types': 7.12.13
'@babel/parser': 7.23.6
'@babel/types': 7.23.6
debug: 4.3.4
globals: 11.12.0
lodash: 4.17.21
......@@ -1888,6 +1891,7 @@ packages:
/@jest/types@26.6.2:
resolution: {integrity: sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==}
engines: {node: '>= 10.14.2'}
requiresBuild: true
dependencies:
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
......@@ -2029,6 +2033,20 @@ packages:
transitivePeerDependencies:
- debug
/@nestjs/config@3.1.1(@nestjs/common@7.6.18)(reflect-metadata@0.1.14):
resolution: {integrity: sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==}
peerDependencies:
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
reflect-metadata: ^0.1.13
dependencies:
'@nestjs/common': 7.6.18(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.14)(rxjs@6.6.7)
dotenv: 16.3.1
dotenv-expand: 10.0.0
lodash: 4.17.21
reflect-metadata: 0.1.14
uuid: 9.0.0
dev: true
/@nestjs/core@7.6.18(@nestjs/common@7.6.18)(@nestjs/platform-express@7.6.18)(reflect-metadata@0.1.14)(rxjs@6.6.7):
resolution: {integrity: sha512-CGu20OjIxgFDY7RJT5t1TDGL8wSlTSlbZEkn8U5OlICZEB3WIpi98G7ajJpnRWmEgW8S4aDJmRKGjT+Ntj5U4A==}
requiresBuild: true
......@@ -2504,14 +2522,17 @@ packages:
/@types/istanbul-lib-coverage@2.0.6:
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
requiresBuild: true
/@types/istanbul-lib-report@3.0.3:
resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
requiresBuild: true
dependencies:
'@types/istanbul-lib-coverage': 2.0.6
/@types/istanbul-reports@3.0.4:
resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
requiresBuild: true
dependencies:
'@types/istanbul-lib-report': 3.0.3
......@@ -2689,9 +2710,11 @@ packages:
/@types/yargs-parser@21.0.3:
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
requiresBuild: true
/@types/yargs@15.0.19:
resolution: {integrity: sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==}
requiresBuild: true
dependencies:
'@types/yargs-parser': 21.0.3
......@@ -4190,7 +4213,7 @@ packages:
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
dependencies:
pascal-case: 3.1.2
tslib: 2.3.0
tslib: 2.6.2
dev: false
/camelcase@5.3.1:
......@@ -4854,11 +4877,21 @@ packages:
webidl-conversions: 5.0.0
dev: true
/dotenv-expand@10.0.0:
resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==}
engines: {node: '>=12'}
dev: true
/dotenv@10.0.0:
resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==}
engines: {node: '>=10'}
dev: false
/dotenv@16.3.1:
resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
engines: {node: '>=12'}
dev: true
/dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
engines: {node: '>=10'}
......@@ -5697,6 +5730,7 @@ packages:
/form-data@3.0.1:
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
engines: {node: '>= 6'}
requiresBuild: true
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
......@@ -6197,6 +6231,7 @@ packages:
/http-proxy-agent@4.0.1:
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
engines: {node: '>= 6'}
requiresBuild: true
dependencies:
'@tootallnate/once': 1.1.2
agent-base: 6.0.2
......@@ -7523,7 +7558,7 @@ packages:
/lower-case@2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
dependencies:
tslib: 2.3.0
tslib: 2.6.2
dev: false
/lru-cache@5.1.1:
......@@ -7919,7 +7954,7 @@ packages:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
dependencies:
lower-case: 2.0.2
tslib: 2.3.0
tslib: 2.6.2
dev: false
/node-abort-controller@3.1.1:
......@@ -8302,7 +8337,7 @@ packages:
resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
dependencies:
no-case: 3.0.4
tslib: 2.3.0
tslib: 2.6.2
dev: false
/pascalcase@0.1.1:
......@@ -8422,6 +8457,7 @@ packages:
/pretty-format@26.6.2:
resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==}
engines: {node: '>= 10'}
requiresBuild: true
dependencies:
'@jest/types': 26.6.2
ansi-regex: 5.0.1
......@@ -8579,6 +8615,7 @@ packages:
/react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
requiresBuild: true
/read-pkg-up@7.0.1:
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
......@@ -9218,11 +9255,6 @@ packages:
engines: {node: '>= 8'}
dev: true
/source-map@0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
dev: true
/sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
deprecated: Please use @jridgewell/sourcemap-codec instead
......@@ -9753,7 +9785,7 @@ packages:
engines: {node: '>=8'}
requiresBuild: true
dependencies:
tslib: 2.2.0
tslib: 2.6.2
dev: false
/ts-jest@26.4.4(jest@26.6.3)(typescript@5.3.3):
......@@ -10183,6 +10215,11 @@ packages:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
hasBin: true
/uuid@9.0.0:
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
hasBin: true
dev: true
/uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
......@@ -10200,7 +10237,7 @@ packages:
dependencies:
'@types/istanbul-lib-coverage': 2.0.6
convert-source-map: 1.9.0
source-map: 0.7.4
source-map: 0.7.3
dev: true
/valid-url@1.0.9:
......
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ChatController } from './modules/chat/chat.controller';
import { ChatService } from './modules/chat/chat.service';
import { ChatModule } from './modules/chat/chat.module';
import envConfig from './config/env';
@Module({
imports: [ChatModule],
imports: [ChatModule, ConfigModule.forRoot({
isGlobal: true,
envFilePath: [envConfig.path],
})],
controllers: [AppController, ChatController],
providers: [AppService, ChatService],
})
......
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
console.log(process.env.ERNIE_BOT_AK)
return 'Hello World!';
}
}
import * as fs from 'fs';
import * as path from 'path';
const isProd = process.env.NODE_ENV === 'production';
function parseEnv() {
const localEnv = path.resolve('.env.development');
const prodEnv = path.resolve('.env.prod');
if (!fs.existsSync(localEnv) && !fs.existsSync(prodEnv)) {
throw new Error('缺少环境配置文件');
}
const filePath = isProd && fs.existsSync(prodEnv) ? prodEnv : localEnv;
return { path:filePath };
}
export default parseEnv();
......@@ -13,23 +13,22 @@ import { TransformReturnInterceptor } from './common/transform.return';
const bodyParser = require('body-parser');
require('body-parser-xml')(bodyParser);
const PORT = 3333;
const PREFIX = 'chh-api'
const SWAGGER_V1 = `${PREFIX}/v1/swagger`
const PORT = process.env.PORT || 3333;
const PREFIX = process.env.PREFIX || 'chh-api'
const SWAGGER = `${PREFIX}/${process.env.SWAGGER_VERSION}/swagger`
async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.setGlobalPrefix(PREFIX);
const options = new DocumentBuilder() // 创建并配置文档信息
.setTitle('标题')
.setDescription('描述信息')
const options = new DocumentBuilder()
.setTitle('宠哈哈在线问诊接口文档')
.setDescription('宠哈哈在线问诊接口文档')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, options);
// 会自动将所有路由显示出来
SwaggerModule.setup(SWAGGER_V1, app, document); // api/swagger = API文档的路径,访问:http://localhost:3000/api/swagger
SwaggerModule.setup(SWAGGER, app, document);
// 跨域资源共享
app.enableCors()
......@@ -69,7 +68,7 @@ async function bootstrap() {
app.useGlobalPipes(new ValidationPipe());
await app.listen(PORT, () => {
Logger.log(`已启动,接口: http://localhost:${PORT}/${PREFIX} , API文档:http://localhost:${PORT}/${SWAGGER_V1}`);
Logger.log(`已启动,接口: http://localhost:${PORT}/${PREFIX} , API文档:http://localhost:${PORT}/${SWAGGER}`);
});
}
bootstrap().catch(err => Logger.error('启动错误:', err));
......@@ -13,6 +13,7 @@ describe('ChatController', () => {
});
it('should be defined', () => {
console.log(controller,'controller')
expect(controller).toBeDefined();
});
});
import { ChatService } from './chat.service';
import { Body, Controller, HttpException, HttpStatus, Post, Req } from '@nestjs/common';
import { Body, Controller, Get, HttpException, HttpStatus, Post, Req } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ChatQueryDto } from './dto/chatQuery.dto';
......
......@@ -8,4 +8,4 @@ import { ChatService } from './chat.service';;
controllers: [ChatController],
providers: [ChatService],
})
export class ChatModule { }
export class ChatModule {}
import { Injectable, Logger } from '@nestjs/common';
import axios from 'axios';
import retry from 'axios-retry'
import { Injectable } from '@nestjs/common';
import type { ErnieBotAccessToken, ErnieBotChatResponse } from './types';
import { ChatQueryDto } from './dto/chatQuery.dto';
const axiosTimeOut = 1000 * 60 * 5
import axios from 'axios';
import retry from 'axios-retry'
retry(axios, {
retries: 3,
......@@ -13,28 +11,52 @@ retry(axios, {
@Injectable()
export class ChatService {
private static readonly AXIOS_TIME_OUT = 1000 * 60 * 5
/**
* 查询问题
* @param body ChatQueryDto
* @returns
*/
async query(body: ChatQueryDto) {
return await this.chat(body)
}
/**
* 问题是否缺失
* @param query 问题
*/
private queryIsMissed(query: string) {
}
/**
* 向千帆大模型提交问题
* @param param ChatQueryDto
* @returns
*/
private async chat({query, history}: ChatQueryDto) {
const url = `https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/plugin/8yrkkifr8gccsvck/?access_token=${await this.getAccessToken()}`
const url = `${process.env.ERNIE_BOT_KNOWLEDGE_PLUGIN_URL}?access_token=${await this.getAccessToken()}`
const data = JSON.stringify({
query,
plugins: ['uuid-zhishiku'],
verbose: true,
history,
})
const res = await axios<ErnieBotChatResponse>(url, { method: 'post', timeout: axiosTimeOut, headers: { 'Content-Type': 'application/json' }, data })
const res = await axios<ErnieBotChatResponse>(url, { method: 'post', timeout: ChatService.AXIOS_TIME_OUT, headers: { 'Content-Type': 'application/json' }, data })
return res.data.result || res.data.error_msg
}
/**
* 获取百度access_token
* @returns 获取百度token
*/
private async getAccessToken() {
const AK = 'mXQIDW260qBbNgQRF0p1YFgn'
const SK = 'hzriOtzGiDkd1S0wFwiyr7WlarfufTdi'
const res = await axios<ErnieBotAccessToken>(`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${AK}&client_secret=${SK}`, {
const AK = process.env.ERNIE_BOT_AK
const SK = process.env.ERNIE_BOT_SK
const res = await axios<ErnieBotAccessToken>(`${process.env.ERNIE_BOT_ACCESS_TOKEN_URL}&client_id=${AK}&client_secret=${SK}`, {
method: 'post',
timeout: axiosTimeOut
timeout: ChatService.AXIOS_TIME_OUT
})
return res.data.access_token
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment