chore: 删除原 node 服务器
This commit is contained in:
parent
192013bd65
commit
c32b50584d
|
|
@ -1,6 +0,0 @@
|
||||||
# 阿里云百炼 API Key
|
|
||||||
# 请在百炼控制台申请并填入此处
|
|
||||||
ALIYUN_API_KEY=your_api_key_here
|
|
||||||
|
|
||||||
# 本地中转服务器运行端口
|
|
||||||
PORT=3000
|
|
||||||
|
|
@ -22,17 +22,20 @@
|
||||||
1. **克隆或复制代码**
|
1. **克隆或复制代码**
|
||||||
|
|
||||||
2. **安装Python依赖**:
|
2. **安装Python依赖**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd server_python
|
cd server
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **配置环境变量**:
|
3. **配置环境变量**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
|
|
||||||
编辑`.env`文件,填入您的阿里云百炼API密钥:
|
编辑`.env`文件,填入您的阿里云百炼API密钥:
|
||||||
|
|
||||||
```
|
```
|
||||||
ALIYUN_API_KEY=your_actual_api_key_here
|
ALIYUN_API_KEY=your_actual_api_key_here
|
||||||
```
|
```
|
||||||
|
|
@ -40,11 +43,13 @@
|
||||||
## 启动服务器
|
## 启动服务器
|
||||||
|
|
||||||
### 方法一:直接运行
|
### 方法一:直接运行
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python run_server.py
|
python run_server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### 方法二:使用uvicorn
|
### 方法二:使用uvicorn
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uvicorn app:app --host 0.0.0.0 --port 8000 --reload
|
uvicorn app:app --host 0.0.0.0 --port 8000 --reload
|
||||||
```
|
```
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
# 日志系统文档
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
本项目实现了统一的后端日志系统,为所有接口提供了详细的日志记录功能,包括请求、响应、错误等状态。
|
|
||||||
|
|
||||||
## 日志系统结构
|
|
||||||
|
|
||||||
### 1. logger.js
|
|
||||||
- 统一日志管理模块
|
|
||||||
- 支持多种日志级别:ERROR, WARN, INFO, DEBUG
|
|
||||||
- 支持控制台和文件双重输出
|
|
||||||
- 包含HTTP请求专用日志方法
|
|
||||||
|
|
||||||
### 2. 日志文件位置
|
|
||||||
- 存储在 `server/logs/` 目录
|
|
||||||
- 按日期命名:`server-YYYY-MM-DD.log`
|
|
||||||
- JSON格式便于查询和分析
|
|
||||||
|
|
||||||
## 日志级别
|
|
||||||
|
|
||||||
- `ERROR`: 错误和异常情况
|
|
||||||
- `WARN`: 警告和潜在问题
|
|
||||||
- `INFO`: 重要操作和状态信息
|
|
||||||
- `DEBUG`: 详细调试信息
|
|
||||||
|
|
||||||
## 接口日志详情
|
|
||||||
|
|
||||||
### 1. 对话接口 (`/api/chat-ui/chat`)
|
|
||||||
- 记录请求代理开始和结束
|
|
||||||
- 记录目标API响应状态
|
|
||||||
- 记录代理错误
|
|
||||||
|
|
||||||
### 2. 模型列表接口 (`/api/chat-ui/models`)
|
|
||||||
- 记录请求基本信息
|
|
||||||
- 记录返回的模型数量
|
|
||||||
|
|
||||||
### 3. 对话管理接口 (`/api/chat-ui/conversations/*`)
|
|
||||||
- 记录操作类型(获取/创建/删除)
|
|
||||||
- 记录对话ID
|
|
||||||
- 记录操作结果
|
|
||||||
|
|
||||||
### 4. 文件上传接口 (`/api/chat-ui/upload`)
|
|
||||||
- 记录上传文件信息(名称、大小、类型)
|
|
||||||
- 记录上传结果和生成的URL
|
|
||||||
|
|
||||||
### 5. 停止生成接口 (`/api/chat-ui/stop/*`)
|
|
||||||
- 记录停止请求的ID
|
|
||||||
- 记录操作结果
|
|
||||||
|
|
||||||
### 6. HTTP通用日志
|
|
||||||
- 记录所有请求的方法、URL、状态码
|
|
||||||
- 记录请求耗时
|
|
||||||
- 记录客户端IP和User-Agent
|
|
||||||
- 根据状态码自动分类日志级别
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 环境变量
|
|
||||||
```bash
|
|
||||||
LOG_LEVEL=DEBUG # 设置日志级别,默认为INFO
|
|
||||||
```
|
|
||||||
|
|
||||||
### 在代码中使用
|
|
||||||
```javascript
|
|
||||||
const { logger } = require('./logger');
|
|
||||||
|
|
||||||
logger.info('Some info message', { additional: 'data' });
|
|
||||||
logger.error('Error occurred', { error: error.message });
|
|
||||||
logger.debug('Debug info', { variable: value });
|
|
||||||
```
|
|
||||||
|
|
||||||
## 日志示例
|
|
||||||
|
|
||||||
### HTTP请求日志
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"timestamp": "2026-03-03T03:26:58.631Z",
|
|
||||||
"level": "INFO",
|
|
||||||
"message": "HTTP GET /api/chat-ui/models 200 15ms",
|
|
||||||
"method": "GET",
|
|
||||||
"url": "/api/chat-ui/models",
|
|
||||||
"statusCode": 200,
|
|
||||||
"duration": "15ms",
|
|
||||||
"userAgent": "Mozilla/5.0...",
|
|
||||||
"ip": "::1"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 特定接口日志
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"timestamp": "2026-03-03T03:27:12.123Z",
|
|
||||||
"level": "INFO",
|
|
||||||
"message": "Successfully uploaded file",
|
|
||||||
"filename": "1642342342-file.jpg",
|
|
||||||
"originalName": "file.jpg",
|
|
||||||
"url": "http://localhost:3000/uploads/1642342342-file.jpg",
|
|
||||||
"size": 123456
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// 日志级别枚举
|
|
||||||
const LOG_LEVELS = {
|
|
||||||
ERROR: 0,
|
|
||||||
WARN: 1,
|
|
||||||
INFO: 2,
|
|
||||||
DEBUG: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 创建logs目录
|
|
||||||
const logsDir = path.join(__dirname, 'logs');
|
|
||||||
if (!fs.existsSync(logsDir)) {
|
|
||||||
fs.mkdirSync(logsDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 日志记录器类
|
|
||||||
class Logger {
|
|
||||||
constructor(level = 'INFO') {
|
|
||||||
this.level = LOG_LEVELS[level.toUpperCase()] || LOG_LEVELS.INFO;
|
|
||||||
this.logFilePath = path.join(logsDir, `server-${new Date().toISOString().split('T')[0]}.log`);
|
|
||||||
}
|
|
||||||
|
|
||||||
_shouldLog(level) {
|
|
||||||
return LOG_LEVELS[level.toUpperCase()] <= this.level;
|
|
||||||
}
|
|
||||||
|
|
||||||
_writeLog(level, message, meta = {}) {
|
|
||||||
if (!this._shouldLog(level)) return;
|
|
||||||
|
|
||||||
const timestamp = new Date().toISOString();
|
|
||||||
const logEntry = {
|
|
||||||
timestamp,
|
|
||||||
level,
|
|
||||||
message,
|
|
||||||
...meta,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 控制台输出
|
|
||||||
console.log(`[${timestamp}] [${level}] ${message}`, meta);
|
|
||||||
|
|
||||||
// 文件输出
|
|
||||||
try {
|
|
||||||
const logLine = JSON.stringify(logEntry) + '\n';
|
|
||||||
fs.appendFileSync(this.logFilePath, logLine);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to write to log file:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error(message, meta = {}) {
|
|
||||||
this._writeLog('ERROR', message, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
warn(message, meta = {}) {
|
|
||||||
this._writeLog('WARN', message, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
info(message, meta = {}) {
|
|
||||||
this._writeLog('INFO', message, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(message, meta = {}) {
|
|
||||||
this._writeLog('DEBUG', message, meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP请求日志专用方法
|
|
||||||
http(req, res, startTime, error = null) {
|
|
||||||
const duration = Date.now() - startTime;
|
|
||||||
const logMeta = {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
statusCode: res.statusCode,
|
|
||||||
duration: `${duration}ms`,
|
|
||||||
userAgent: req.headers['user-agent'],
|
|
||||||
ip: req.ip || req.connection.remoteAddress,
|
|
||||||
...(error ? { error: error.message || error } : {})
|
|
||||||
};
|
|
||||||
|
|
||||||
const statusCategory = Math.floor(res.statusCode / 100);
|
|
||||||
let level = 'INFO';
|
|
||||||
if (error || statusCategory >= 5) {
|
|
||||||
level = 'ERROR';
|
|
||||||
} else if (statusCategory >= 4) {
|
|
||||||
level = 'WARN';
|
|
||||||
}
|
|
||||||
|
|
||||||
this._writeLog(level, `HTTP ${req.method} ${req.url} ${res.statusCode} ${duration}ms`, logMeta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建全局日志实例
|
|
||||||
const logger = new Logger(process.env.LOG_LEVEL || 'INFO');
|
|
||||||
|
|
||||||
module.exports = { logger, LOG_LEVELS };
|
|
||||||
|
|
@ -13,7 +13,7 @@ from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
# 导入模块
|
# 导入模块
|
||||||
import sys
|
import sys
|
||||||
sys.path.append('/home/mt/project/ai-chat-ui/server_python')
|
sys.path.append('/home/mt/project/ai-chat-ui/server')
|
||||||
|
|
||||||
from api.chat_routes import (
|
from api.chat_routes import (
|
||||||
chat_endpoint_handler,
|
chat_endpoint_handler,
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"name": "server",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "node server.js",
|
|
||||||
"dev": "nodemon server.js"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"type": "commonjs",
|
|
||||||
"dependencies": {
|
|
||||||
"cors": "^2.8.6",
|
|
||||||
"dotenv": "^17.3.1",
|
|
||||||
"express": "^5.2.1",
|
|
||||||
"http-proxy-middleware": "^3.0.5",
|
|
||||||
"morgan": "^1.10.1",
|
|
||||||
"multer": "^2.1.0",
|
|
||||||
"uuid": "^13.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
351
server/server.js
351
server/server.js
|
|
@ -1,351 +0,0 @@
|
||||||
const express = require('express');
|
|
||||||
const cors = require('cors');
|
|
||||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
||||||
const multer = require('multer');
|
|
||||||
const { v4: uuidv4 } = require('uuid');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
const morgan = require('morgan');
|
|
||||||
require('dotenv').config();
|
|
||||||
|
|
||||||
// 引入自定义日志系统
|
|
||||||
const { logger } = require('./logger');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const PORT = process.env.PORT || 3000;
|
|
||||||
|
|
||||||
// 配置全局请求日志中间件
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
const startTime = Date.now();
|
|
||||||
|
|
||||||
// 保存原始的res.end方法
|
|
||||||
const originalEnd = res.end;
|
|
||||||
res.end = function(chunk, encoding) {
|
|
||||||
// 调用自定义日志记录
|
|
||||||
logger.http(req, res, startTime);
|
|
||||||
|
|
||||||
// 调用原始的res.end
|
|
||||||
originalEnd.call(this, chunk, encoding);
|
|
||||||
};
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 配置 CORS,允许前端项目的跨域请求
|
|
||||||
app.use(cors());
|
|
||||||
|
|
||||||
// --- 1. 流式对话请求代理配置 ---
|
|
||||||
app.use('/api/chat-ui/chat', (req, res, next) => {
|
|
||||||
logger.info('Received chat request', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
headers: {
|
|
||||||
'content-type': req.headers['content-type'],
|
|
||||||
'content-length': req.headers['content-length']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const apiKey = process.env.ALIYUN_API_KEY;
|
|
||||||
if (!apiKey) {
|
|
||||||
logger.error("【错误】发送代理请求前未配置 ALIYUN_API_KEY !");
|
|
||||||
} else {
|
|
||||||
req.headers['authorization'] = `Bearer ${apiKey}`;
|
|
||||||
logger.debug('Added authorization header for chat request');
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注意:代理中间件需要在 body-parser (express.json) 之前,不然代理会导致请求体丢失
|
|
||||||
app.use(
|
|
||||||
'/api/chat-ui/chat',
|
|
||||||
createProxyMiddleware({
|
|
||||||
// 阿里云百炼由于兼容 OpenAI 格式,所以代理到此接口
|
|
||||||
target: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
|
|
||||||
changeOrigin: true,
|
|
||||||
// 去除路径前缀,确保发往阿里云的路径是纯正的 completions 路径
|
|
||||||
pathRewrite: {
|
|
||||||
'^/api/chat-ui/chat': '',
|
|
||||||
},
|
|
||||||
// 代理日志
|
|
||||||
onProxyReq: (proxyReq, req, res) => {
|
|
||||||
logger.info('Proxying chat request to DashScope API', {
|
|
||||||
target: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
|
|
||||||
method: req.method,
|
|
||||||
url: req.url
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onProxyRes: (proxyRes, req, res) => {
|
|
||||||
logger.info('Received response from DashScope API', {
|
|
||||||
statusCode: proxyRes.statusCode,
|
|
||||||
headers: proxyRes.headers
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onError: (err, req, res) => {
|
|
||||||
logger.error('Error occurred during proxying chat request', {
|
|
||||||
error: err.message,
|
|
||||||
method: req.method,
|
|
||||||
url: req.url
|
|
||||||
});
|
|
||||||
res.status(500).json({ error: 'Proxy error: ' + err.message });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- 下面的路由专门走 Node.js 业务逻辑,因此需要解析 JSON Body ---
|
|
||||||
app.use(express.json());
|
|
||||||
|
|
||||||
// 内存中暂时存放对话数据用于 Mock
|
|
||||||
const conversationsDB = {};
|
|
||||||
|
|
||||||
// --- 2. 获取模型列表 ---
|
|
||||||
app.get('/api/chat-ui/models', (req, res) => {
|
|
||||||
logger.info('Getting models list', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const models = [
|
|
||||||
{
|
|
||||||
id: "qwen-max",
|
|
||||||
name: "通义千问 Max",
|
|
||||||
description: "最强大的模型",
|
|
||||||
maxTokens: 8192,
|
|
||||||
provider: "Aliyun"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "qwen-plus",
|
|
||||||
name: "通义千问 Plus",
|
|
||||||
description: "能力均衡",
|
|
||||||
maxTokens: 8192,
|
|
||||||
provider: "Aliyun"
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
res.json(models);
|
|
||||||
logger.info('Successfully returned models list', { count: models.length });
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error getting models list', { error: error.message });
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- 3. 获取所有对话历史 ---
|
|
||||||
app.get('/api/chat-ui/conversations', (req, res) => {
|
|
||||||
logger.info('Getting all conversations', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const conversations = Object.values(conversationsDB);
|
|
||||||
res.json(conversations);
|
|
||||||
logger.info('Successfully returned conversations', { count: conversations.length });
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error getting conversations', { error: error.message });
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- 4. 获取单个对话 ---
|
|
||||||
app.get('/api/chat-ui/conversations/:id', (req, res) => {
|
|
||||||
const { id } = req.params;
|
|
||||||
logger.info('Getting conversation by ID', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
conversationId: id,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const conversation = conversationsDB[id];
|
|
||||||
if (conversation) {
|
|
||||||
res.json(conversation);
|
|
||||||
logger.info('Successfully returned conversation', { conversationId: id });
|
|
||||||
} else {
|
|
||||||
res.status(404).json({ error: '对话不存在' });
|
|
||||||
logger.warn('Conversation not found', { conversationId: id });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error getting conversation by ID', {
|
|
||||||
conversationId: id,
|
|
||||||
error: error.message
|
|
||||||
});
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- 5. 保存或更新对话 ---
|
|
||||||
app.post('/api/chat-ui/conversations', (req, res) => {
|
|
||||||
logger.info('Creating or updating conversation', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
body: {
|
|
||||||
hasId: !!req.body.id,
|
|
||||||
title: req.body.title
|
|
||||||
},
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = req.body;
|
|
||||||
if(!data.id) {
|
|
||||||
data.id = uuidv4();
|
|
||||||
logger.debug('Generated new conversation ID', { conversationId: data.id });
|
|
||||||
}
|
|
||||||
|
|
||||||
conversationsDB[data.id] = data;
|
|
||||||
res.json(data);
|
|
||||||
logger.info('Successfully saved conversation', { conversationId: data.id });
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error saving conversation', { error: error.message });
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- 6. 删除对话 ---
|
|
||||||
app.delete('/api/chat-ui/conversations/:id', (req, res) => {
|
|
||||||
const { id } = req.params;
|
|
||||||
logger.info('Deleting conversation', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
conversationId: id,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (conversationsDB[id]) {
|
|
||||||
delete conversationsDB[id];
|
|
||||||
res.json({ success: true, message: "删除成功" });
|
|
||||||
logger.info('Successfully deleted conversation', { conversationId: id });
|
|
||||||
} else {
|
|
||||||
res.status(404).json({ error: '对话不存在' });
|
|
||||||
logger.warn('Attempted to delete non-existent conversation', { conversationId: id });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error deleting conversation', {
|
|
||||||
conversationId: id,
|
|
||||||
error: error.message
|
|
||||||
});
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 为了存储上传文件而建立临时目录
|
|
||||||
const uploadDir = path.join(__dirname, 'uploads');
|
|
||||||
if (!fs.existsSync(uploadDir)) {
|
|
||||||
fs.mkdirSync(uploadDir);
|
|
||||||
logger.info('Created uploads directory', { path: uploadDir });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 配置文件上传
|
|
||||||
const storage = multer.diskStorage({
|
|
||||||
destination: function (req, file, cb) {
|
|
||||||
cb(null, uploadDir);
|
|
||||||
},
|
|
||||||
filename: function (req, file, cb) {
|
|
||||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
|
||||||
cb(null, uniqueSuffix + '-' + file.originalname);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const upload = multer({ storage: storage });
|
|
||||||
|
|
||||||
// 提供静态文件访问支持
|
|
||||||
app.use('/uploads', express.static(uploadDir));
|
|
||||||
|
|
||||||
// --- 7. 上传文件 ---
|
|
||||||
app.post('/api/chat-ui/upload', upload.single('file'), (req, res) => {
|
|
||||||
logger.info('Processing file upload', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
originalFilename: req.file ? req.file.originalname : 'none',
|
|
||||||
mimetype: req.file ? req.file.mimetype : 'none',
|
|
||||||
size: req.file ? req.file.size : 'none',
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!req.file) {
|
|
||||||
const errorMsg = '没有文件上传';
|
|
||||||
logger.warn(errorMsg, {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url
|
|
||||||
});
|
|
||||||
return res.status(400).json({ error: errorMsg });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 返回供前端使用和访问的 URL
|
|
||||||
const response = {
|
|
||||||
url: `http://localhost:${PORT}/uploads/${req.file.filename}`,
|
|
||||||
name: req.file.originalname,
|
|
||||||
size: req.file.size,
|
|
||||||
mimeType: req.file.mimetype
|
|
||||||
};
|
|
||||||
|
|
||||||
res.json(response);
|
|
||||||
logger.info('Successfully uploaded file', {
|
|
||||||
filename: req.file.filename,
|
|
||||||
originalName: req.file.originalname,
|
|
||||||
url: response.url,
|
|
||||||
size: req.file.size
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error processing file upload', {
|
|
||||||
originalFilename: req.file.originalname,
|
|
||||||
error: error.message
|
|
||||||
});
|
|
||||||
res.status(500).json({ error: 'File upload processing failed' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- 8. 停止生成 ---
|
|
||||||
app.post(['/api/chat-ui/stop', '/api/chat-ui/stop/:id'], (req, res) => {
|
|
||||||
const id = req.params.id;
|
|
||||||
logger.info('Stop generation request received', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
messageId: id,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
res.json({ success: true, message: "已发出停止指令" });
|
|
||||||
logger.info('Stop generation request processed', { messageId: id });
|
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error processing stop generation request', {
|
|
||||||
messageId: id,
|
|
||||||
error: error.message
|
|
||||||
});
|
|
||||||
res.status(500).json({ error: 'Internal server error' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 其他所有路由返回404
|
|
||||||
app.use((req, res) => {
|
|
||||||
logger.warn('Route not found', {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url,
|
|
||||||
ip: req.ip || req.connection.remoteAddress
|
|
||||||
});
|
|
||||||
res.status(404).json({ error: 'Endpoint not found' });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
|
||||||
logger.info('Server started successfully', {
|
|
||||||
port: PORT,
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('====================================');
|
|
||||||
console.log(`本地代理服务器已启动,监听端口: ${PORT}`);
|
|
||||||
console.log('====================================');
|
|
||||||
if (!process.env.ALIYUN_API_KEY) {
|
|
||||||
console.log('⚠️ 警告: 未在 .env 文件中检测到 ALIYUN_API_KEY!');
|
|
||||||
console.log('请在 server/.env 中添加您的百炼 API Key。');
|
|
||||||
} else {
|
|
||||||
console.log('✅ 检测到了 API Key。');
|
|
||||||
logger.info('API Key detected in environment');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -10,7 +10,7 @@ if lsof -Pi :8000 -sTCP:LISTEN -t >/dev/null; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 切换到服务器目录
|
# 切换到服务器目录
|
||||||
cd /home/mt/project/ai-chat-ui/server_python
|
cd /home/mt/project/ai-chat-ui/server
|
||||||
|
|
||||||
# 检查虚拟环境是否存在
|
# 检查虚拟环境是否存在
|
||||||
if [ ! -d ".venv" ]; then
|
if [ ! -d ".venv" ]; then
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue