perf: 优化部份判断

This commit is contained in:
ChenZhaoYu 2023-03-17 08:57:27 +08:00
parent b3cfe7a976
commit 2ad7567548
5 changed files with 63 additions and 45 deletions

View File

@ -6,6 +6,7 @@ import { SocksProxyAgent } from 'socks-proxy-agent'
import { HttpsProxyAgent } from 'https-proxy-agent' import { HttpsProxyAgent } from 'https-proxy-agent'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { sendResponse } from '../utils' import { sendResponse } from '../utils'
import { isNotEmptyString } from '../utils/is'
import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types' import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types'
const ErrorCodeMessage: Record<string, string> = { const ErrorCodeMessage: Record<string, string> = {
@ -27,42 +28,21 @@ if (!process.env.OPENAI_API_KEY && !process.env.OPENAI_ACCESS_TOKEN)
throw new Error('Missing OPENAI_API_KEY or OPENAI_ACCESS_TOKEN environment variable') throw new Error('Missing OPENAI_API_KEY or OPENAI_ACCESS_TOKEN environment variable')
let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI
function setupProxy(options) {
if (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) {
const agent = new SocksProxyAgent({
hostname: process.env.SOCKS_PROXY_HOST,
port: process.env.SOCKS_PROXY_PORT,
})
options.fetch = (url, options) => {
return fetch(url, { agent, ...options })
}
}
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy
if (httpsProxy) {
const agent = new HttpsProxyAgent(httpsProxy)
options.fetch = (url, options) => {
return fetch(url, { agent, ...options })
}
}
}
(async () => { (async () => {
// More Info: https://github.com/transitive-bullshit/chatgpt-api // More Info: https://github.com/transitive-bullshit/chatgpt-api
if (process.env.OPENAI_API_KEY) { if (process.env.OPENAI_API_KEY) {
const OPENAI_API_MODEL = process.env.OPENAI_API_MODEL const OPENAI_API_MODEL = process.env.OPENAI_API_MODEL
const model = (typeof OPENAI_API_MODEL === 'string' && OPENAI_API_MODEL.length > 0) const model = isNotEmptyString(OPENAI_API_MODEL) ? OPENAI_API_MODEL : 'gpt-3.5-turbo'
? OPENAI_API_MODEL
: 'gpt-3.5-turbo'
const options: ChatGPTAPIOptions = { const options: ChatGPTAPIOptions = {
apiKey: process.env.OPENAI_API_KEY, apiKey: process.env.OPENAI_API_KEY,
completionParams: { model }, completionParams: { model },
debug: false, debug: true,
} }
if (process.env.OPENAI_API_BASE_URL && process.env.OPENAI_API_BASE_URL.trim().length > 0) if (isNotEmptyString(process.env.OPENAI_API_BASE_URL))
options.apiBaseUrl = process.env.OPENAI_API_BASE_URL options.apiBaseUrl = process.env.OPENAI_API_BASE_URL
setupProxy(options) setupProxy(options)
@ -73,14 +53,14 @@ function setupProxy(options) {
else { else {
const options: ChatGPTUnofficialProxyAPIOptions = { const options: ChatGPTUnofficialProxyAPIOptions = {
accessToken: process.env.OPENAI_ACCESS_TOKEN, accessToken: process.env.OPENAI_ACCESS_TOKEN,
debug: false, debug: true,
} }
setupProxy(options) if (isNotEmptyString(process.env.API_REVERSE_PROXY))
if (process.env.API_REVERSE_PROXY)
options.apiReverseProxyUrl = process.env.API_REVERSE_PROXY options.apiReverseProxyUrl = process.env.API_REVERSE_PROXY
setupProxy(options)
api = new ChatGPTUnofficialProxyAPI({ ...options }) api = new ChatGPTUnofficialProxyAPI({ ...options })
apiModel = 'ChatGPTUnofficialProxyAPI' apiModel = 'ChatGPTUnofficialProxyAPI'
} }
@ -91,9 +71,6 @@ async function chatReplyProcess(
lastContext?: { conversationId?: string; parentMessageId?: string }, lastContext?: { conversationId?: string; parentMessageId?: string },
process?: (chat: ChatMessage) => void, process?: (chat: ChatMessage) => void,
) { ) {
// if (!message)
// return sendResponse({ type: 'Fail', message: 'Message is empty' })
try { try {
let options: SendMessageOptions = { timeoutMs } let options: SendMessageOptions = { timeoutMs }
@ -123,20 +100,39 @@ async function chatReplyProcess(
} }
async function chatConfig() { async function chatConfig() {
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.ALL_PROXY || process.env.all_proxy const reverseProxy = process.env.API_REVERSE_PROXY ?? '-'
const socksProxy = (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) ? (`${process.env.SOCKS_PROXY_HOST}:${process.env.SOCKS_PROXY_PORT}`) : '-'
const httpsProxy = (process.env.HTTPS_PROXY || process.env.ALL_PROXY) ?? '-'
return sendResponse({ return sendResponse<ModelConfig>({
type: 'Success', type: 'Success',
data: { data: { apiModel, reverseProxy, timeoutMs, socksProxy, httpsProxy },
apiModel,
reverseProxy: process.env.API_REVERSE_PROXY,
timeoutMs,
socksProxy: (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) ? (`${process.env.SOCKS_PROXY_HOST}:${process.env.SOCKS_PROXY_PORT}`) : '-',
httpsProxy,
} as ModelConfig,
}) })
} }
function setupProxy(options: ChatGPTAPIOptions | ChatGPTUnofficialProxyAPIOptions) {
if (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) {
const agent = new SocksProxyAgent({
hostname: process.env.SOCKS_PROXY_HOST,
port: process.env.SOCKS_PROXY_PORT,
})
options.fetch = (url, options) => {
return fetch(url, { agent, ...options })
}
}
else {
if (process.env.HTTPS_PROXY || process.env.ALL_PROXY) {
const httpsProxy = process.env.HTTPS_PROXY || process.env.ALL_PROXY
if (httpsProxy) {
const agent = new HttpsProxyAgent(httpsProxy)
options.fetch = (url, options) => {
return fetch(url, { agent, ...options })
}
}
}
}
}
export type { ChatContext, ChatMessage } export type { ChatContext, ChatMessage }
export { chatReplyProcess, chatConfig } export { chatReplyProcess, chatConfig }

View File

@ -2,6 +2,7 @@ import express from 'express'
import type { ChatContext, ChatMessage } from './chatgpt' import type { ChatContext, ChatMessage } from './chatgpt'
import { chatConfig, chatReplyProcess } from './chatgpt' import { chatConfig, chatReplyProcess } from './chatgpt'
import { auth } from './middleware/auth' import { auth } from './middleware/auth'
import { isNotEmptyString } from './utils/is'
const app = express() const app = express()
const router = express.Router() const router = express.Router()
@ -48,7 +49,7 @@ router.post('/config', async (req, res) => {
router.post('/session', async (req, res) => { router.post('/session', async (req, res) => {
try { try {
const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY
const hasAuth = typeof AUTH_SECRET_KEY === 'string' && AUTH_SECRET_KEY.length > 0 const hasAuth = isNotEmptyString(AUTH_SECRET_KEY)
res.send({ status: 'Success', message: '', data: { auth: hasAuth } }) res.send({ status: 'Success', message: '', data: { auth: hasAuth } })
} }
catch (error) { catch (error) {

View File

@ -1,6 +1,8 @@
import { isNotEmptyString } from '../utils/is'
const auth = async (req, res, next) => { const auth = async (req, res, next) => {
const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY const AUTH_SECRET_KEY = process.env.AUTH_SECRET_KEY
if (typeof AUTH_SECRET_KEY === 'string' && AUTH_SECRET_KEY.length > 0) { if (isNotEmptyString(AUTH_SECRET_KEY)) {
try { try {
const Authorization = req.header('Authorization') const Authorization = req.header('Authorization')
if (!Authorization || Authorization.replace('Bearer ', '').trim() !== AUTH_SECRET_KEY.trim()) if (!Authorization || Authorization.replace('Bearer ', '').trim() !== AUTH_SECRET_KEY.trim())

View File

@ -1,10 +1,10 @@
interface SendResponseOptions { interface SendResponseOptions<T = any> {
type: 'Success' | 'Fail' type: 'Success' | 'Fail'
message?: string message?: string
data?: any data?: T
} }
export function sendResponse(options: SendResponseOptions) { export function sendResponse<T>(options: SendResponseOptions<T>) {
if (options.type === 'Success') { if (options.type === 'Success') {
return Promise.resolve({ return Promise.resolve({
message: options.message ?? null, message: options.message ?? null,

19
service/src/utils/is.ts Normal file
View File

@ -0,0 +1,19 @@
export function isNumber<T extends number>(value: T | unknown): value is number {
return Object.prototype.toString.call(value) === '[object Number]'
}
export function isString<T extends string>(value: T | unknown): value is string {
return Object.prototype.toString.call(value) === '[object String]'
}
export function isNotEmptyString(value: any): boolean {
return typeof value === 'string' && value.length > 0
}
export function isBoolean<T extends boolean>(value: T | unknown): value is boolean {
return Object.prototype.toString.call(value) === '[object Boolean]'
}
export function isFunction<T extends (...args: any[]) => any | void | never>(value: T | unknown): value is T {
return Object.prototype.toString.call(value) === '[object Function]'
}