mirror of
https://github.com/BidingCC/BuildingAI.git
synced 2026-08-31 02:03:00 +08:00
ci: docker新增npm、pnpm镜像配置项
This commit is contained in:
@@ -48,6 +48,7 @@ VITE_APP_WEB_API_PREFIX=/api
|
||||
VITE_APP_CONSOLE_API_PREFIX=/consoleapi
|
||||
|
||||
# Docker
|
||||
NPM_REGISTRY_URL=https://registry.npmmirror.com
|
||||
QUICK_START_MODE=false
|
||||
DOCKER_CONTAINER_SUFFIX=
|
||||
DOCKER_MEMORY_LIMIT=3072M
|
||||
|
||||
@@ -48,6 +48,7 @@ VITE_APP_WEB_API_PREFIX=/api
|
||||
VITE_APP_CONSOLE_API_PREFIX=/consoleapi
|
||||
|
||||
# Docker
|
||||
NPM_REGISTRY_URL=https://registry.npmmirror.com
|
||||
QUICK_START_MODE=false
|
||||
DOCKER_CONTAINER_SUFFIX=
|
||||
DOCKER_MEMORY_LIMIT=3072M
|
||||
|
||||
Vendored
+3
@@ -27,5 +27,8 @@
|
||||
},
|
||||
"[plaintext]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[dockercompose]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,10 +311,26 @@ export class AiChatMessageController extends BaseController {
|
||||
const exists = await this.AiChatRecordService.findOneById(conversationId);
|
||||
|
||||
if (!exists.title) {
|
||||
const title = await this.aiGenerateTitle(
|
||||
model,
|
||||
dto.messages as Array<ChatCompletionMessageParam>,
|
||||
);
|
||||
let title: string;
|
||||
|
||||
// 检查是否有深度思考内容(从最终响应中检查)
|
||||
const hasReasoningContent = finalResponse?.choices?.[0]?.message?.reasoning_content;
|
||||
|
||||
if (hasReasoningContent) {
|
||||
// 如果有深度思考内容,说明是支持深度思考的模型,使用用户问题前20字符作为标题
|
||||
const userMessage = dto.messages.find((msg) => msg.role === "user");
|
||||
const userContent = userMessage?.content || "";
|
||||
title =
|
||||
typeof userContent === "string"
|
||||
? userContent.slice(0, 20) + (userContent.length > 20 ? "..." : "")
|
||||
: "新对话";
|
||||
} else {
|
||||
// 非深度思考模型,使用AI生成标题
|
||||
title = await this.aiGenerateTitle(
|
||||
model,
|
||||
dto.messages as Array<ChatCompletionMessageParam>,
|
||||
);
|
||||
}
|
||||
|
||||
await this.AiChatRecordService.updateConversation(conversationId, playground.id, {
|
||||
title,
|
||||
@@ -565,6 +581,7 @@ export class AiChatMessageController extends BaseController {
|
||||
let hasToolCalls = false;
|
||||
let reasoningContent = ""; // 收集深度思考内容
|
||||
let reasoningStartTime: number | null = null; // 深度思考开始时间
|
||||
let reasoningEndTime: number | null = null; // 深度思考结束时间
|
||||
|
||||
do {
|
||||
hasToolCalls = false;
|
||||
@@ -592,6 +609,8 @@ export class AiChatMessageController extends BaseController {
|
||||
if (!reasoningStartTime) {
|
||||
reasoningStartTime = Date.now();
|
||||
}
|
||||
// 每次收到 reasoning_content 都更新结束时间
|
||||
reasoningEndTime = Date.now();
|
||||
reasoningContent += chunk.choices[0].delta.reasoning_content;
|
||||
res.write(
|
||||
`data: ${JSON.stringify({
|
||||
@@ -800,13 +819,12 @@ export class AiChatMessageController extends BaseController {
|
||||
|
||||
// 准备 metadata,包含深度思考数据
|
||||
const metadata: Record<string, any> = {};
|
||||
if (reasoningContent && reasoningStartTime) {
|
||||
const endTime = Date.now();
|
||||
if (reasoningContent && reasoningStartTime && reasoningEndTime) {
|
||||
metadata.reasoning = {
|
||||
content: reasoningContent,
|
||||
startTime: reasoningStartTime,
|
||||
endTime: endTime,
|
||||
duration: endTime - reasoningStartTime,
|
||||
endTime: reasoningEndTime,
|
||||
duration: reasoningEndTime - reasoningStartTime,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -835,10 +853,23 @@ export class AiChatMessageController extends BaseController {
|
||||
const exists = await this.AiChatRecordService.findOneById(conversationId);
|
||||
|
||||
if (!exists.title) {
|
||||
const title = await this.aiGenerateTitle(
|
||||
model,
|
||||
dto.messages as Array<ChatCompletionMessageParam>,
|
||||
);
|
||||
let title: string;
|
||||
|
||||
// 如果有深度思考内容,说明是支持深度思考的模型,使用用户问题前20字符作为标题
|
||||
if (reasoningContent) {
|
||||
const userMessage = dto.messages.find((msg) => msg.role === "user");
|
||||
const userContent = userMessage?.content || "";
|
||||
title =
|
||||
typeof userContent === "string"
|
||||
? userContent.slice(0, 20) + (userContent.length > 20 ? "..." : "")
|
||||
: "新对话";
|
||||
} else {
|
||||
// 非深度思考模型,使用AI生成标题
|
||||
title = await this.aiGenerateTitle(
|
||||
model,
|
||||
dto.messages as Array<ChatCompletionMessageParam>,
|
||||
);
|
||||
}
|
||||
|
||||
await this.AiChatRecordService.updateConversation(conversationId, playground.id, {
|
||||
title,
|
||||
|
||||
+135
-129
@@ -1,137 +1,143 @@
|
||||
# 定义通用资源配置
|
||||
x-resource-config: &resource-config
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DOCKER_MEMORY_LIMIT:-3584M}
|
||||
cpus: '${DOCKER_CPU_LIMIT:-1.0}'
|
||||
reservations:
|
||||
memory: ${DOCKER_MEMORY_RESERVATION:-512M}
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DOCKER_MEMORY_LIMIT:-3584M}
|
||||
cpus: "${DOCKER_CPU_LIMIT:-1.0}"
|
||||
reservations:
|
||||
memory: ${DOCKER_MEMORY_RESERVATION:-512M}
|
||||
|
||||
services:
|
||||
# Redis 缓存服务
|
||||
redis:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/redis:8.2.0
|
||||
container_name: fastbuildai-redis${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
||||
QUICK_START_MODE: ${QUICK_START_MODE:-false}
|
||||
ports:
|
||||
- "${REDIS_EXTERNAL_PORT:-}${REDIS_EXTERNAL_PORT:+:}6379"
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli -a $$REDIS_PASSWORD ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
# Redis 缓存服务
|
||||
redis:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/redis:8.2.0
|
||||
container_name: fastbuildai-redis${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
||||
QUICK_START_MODE: ${QUICK_START_MODE:-false}
|
||||
ports:
|
||||
- "${REDIS_EXTERNAL_PORT:-}${REDIS_EXTERNAL_PORT:+:}6379"
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli -a $$REDIS_PASSWORD ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# PostgreSQL 数据库服务 (with pgvector)
|
||||
postgres:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/postgres:17.6
|
||||
container_name: fastbuildai-postgres${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: ${DB_USERNAME:-postgres}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
POSTGRES_DB: ${DB_DATABASE:-fastbuildai}
|
||||
ports:
|
||||
- "${POSTGRES_EXTERNAL_PORT:-}${POSTGRES_EXTERNAL_PORT:+:}5432"
|
||||
volumes:
|
||||
- ./data/postgres/postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME:-postgres}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
# PostgreSQL 数据库服务 (with pgvector)
|
||||
postgres:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/postgres:17.6
|
||||
container_name: fastbuildai-postgres${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: ${DB_USERNAME:-postgres}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
POSTGRES_DB: ${DB_DATABASE:-fastbuildai}
|
||||
ports:
|
||||
- "${POSTGRES_EXTERNAL_PORT:-}${POSTGRES_EXTERNAL_PORT:+:}5432"
|
||||
volumes:
|
||||
- ./data/postgres/postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME:-postgres}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Node.js 开发环境
|
||||
nodejs:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/node:22.18.0
|
||||
container_name: fastbuildai-nodejs${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: on-failure:3
|
||||
working_dir: /fastbuildai
|
||||
volumes:
|
||||
- ../:/fastbuildai
|
||||
ports:
|
||||
- "${SERVER_PORT:-4090}:${SERVER_PORT:-4090}"
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
SERVER_PORT: ${SERVER_PORT:-4090}
|
||||
QUICK_START_MODE: ${QUICK_START_MODE:-false}
|
||||
DB_USERNAME: ${DB_USERNAME:-postgres}
|
||||
DB_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
DB_DATABASE: ${DB_DATABASE:-fastbuildai}
|
||||
DB_HOST: postgres
|
||||
DB_PORT: 5432
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
||||
command: |
|
||||
sh -c '
|
||||
set -e
|
||||
echo "🚀 Starting FastbuildAI container..."
|
||||
|
||||
if [ -z "$$QUICK_START_MODE" ]; then
|
||||
QUICK_START_MODE="false"
|
||||
echo "⚠️ QUICK_START_MODE is empty, setting default value: false"
|
||||
fi
|
||||
|
||||
echo "🔍 Debug: QUICK_START_MODE = [$$QUICK_START_MODE]"
|
||||
|
||||
if ! command -v pnpm >/dev/null 2>&1; then
|
||||
echo "📦 Installing pnpm..."
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
npm install -g pnpm
|
||||
fi
|
||||
|
||||
echo "📦 Installing dependencies..."
|
||||
if [ -d "node_modules" ]; then
|
||||
echo "📁 node_modules exists, using force install..."
|
||||
yes | pnpm i
|
||||
else
|
||||
echo "📁 node_modules not found, installing..."
|
||||
pnpm i
|
||||
fi
|
||||
|
||||
if [ ! -f "/fastbuildai/public/index.html" ] || [ "$$QUICK_START_MODE" = "false" ]; then
|
||||
echo "🌐 Building web application..."
|
||||
pnpm --filter ./apps/web run generate
|
||||
fi
|
||||
|
||||
if [ ! -d "/fastbuildai/apps/server/dist" ] || [ "$$QUICK_START_MODE" = "false" ]; then
|
||||
echo "🔧 Building server application..."
|
||||
pnpm --filter ./apps/server run build
|
||||
fi
|
||||
|
||||
echo "🔍 Debug: QUICK_START_MODE = [$$QUICK_START_MODE]"
|
||||
echo "🎯 Starting production server..."
|
||||
exec pnpm --filter ./apps/server run start:prod
|
||||
'
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "ps aux | grep 'dist/main' | grep -v grep || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 180s
|
||||
# Node.js 开发环境
|
||||
nodejs:
|
||||
image: registry.ap-southeast-1.aliyuncs.com/fastbuildai/node:22.18.0
|
||||
container_name: fastbuildai-nodejs${DOCKER_CONTAINER_SUFFIX:-}
|
||||
restart: on-failure:3
|
||||
working_dir: /fastbuildai
|
||||
volumes:
|
||||
- ../:/fastbuildai
|
||||
ports:
|
||||
- "${SERVER_PORT:-4090}:${SERVER_PORT:-4090}"
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
SERVER_PORT: ${SERVER_PORT:-4090}
|
||||
QUICK_START_MODE: ${QUICK_START_MODE:-false}
|
||||
DB_USERNAME: ${DB_USERNAME:-postgres}
|
||||
DB_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
DB_DATABASE: ${DB_DATABASE:-fastbuildai}
|
||||
DB_HOST: postgres
|
||||
DB_PORT: 5432
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: 6379
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
||||
command: |
|
||||
sh -c '
|
||||
set -e
|
||||
echo "🚀 Starting FastbuildAI container..."
|
||||
|
||||
if [ -z "$$QUICK_START_MODE" ]; then
|
||||
QUICK_START_MODE="false"
|
||||
echo "⚠️ QUICK_START_MODE is empty, setting default value: false"
|
||||
fi
|
||||
|
||||
echo "🔍 Debug: QUICK_START_MODE = [$$QUICK_START_MODE]"
|
||||
|
||||
if ! command -v pnpm >/dev/null 2>&1; then
|
||||
echo "📦 Installing pnpm..."
|
||||
if [ -n "$$NPM_REGISTRY_URL" ]; then
|
||||
echo "🔧 Using custom registry: $$NPM_REGISTRY_URL"
|
||||
npm config set registry "$$NPM_REGISTRY_URL"
|
||||
fi
|
||||
npm install -g pnpm
|
||||
if [ -n "$$NPM_REGISTRY_URL" ]; then
|
||||
pnpm config set registry "$$NPM_REGISTRY_URL"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "📦 Installing dependencies..."
|
||||
if [ -d "node_modules" ]; then
|
||||
echo "📁 node_modules exists, using force install..."
|
||||
yes | pnpm i
|
||||
else
|
||||
echo "📁 node_modules not found, installing..."
|
||||
pnpm i
|
||||
fi
|
||||
|
||||
if [ ! -f "/fastbuildai/public/index.html" ] || [ "$$QUICK_START_MODE" = "false" ]; then
|
||||
echo "🌐 Building web application..."
|
||||
pnpm --filter ./apps/web run generate
|
||||
fi
|
||||
|
||||
if [ ! -d "/fastbuildai/apps/server/dist" ] || [ "$$QUICK_START_MODE" = "false" ]; then
|
||||
echo "🔧 Building server application..."
|
||||
pnpm --filter ./apps/server run build
|
||||
fi
|
||||
|
||||
echo "🔍 Debug: QUICK_START_MODE = [$$QUICK_START_MODE]"
|
||||
echo "🎯 Starting production server..."
|
||||
exec pnpm --filter ./apps/server run start:prod
|
||||
'
|
||||
networks:
|
||||
- fastbuildai-network
|
||||
<<: *resource-config
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "ps aux | grep 'dist/main' | grep -v grep || exit 1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 10
|
||||
start_period: 180s
|
||||
|
||||
networks:
|
||||
fastbuildai-network:
|
||||
driver: bridge
|
||||
fastbuildai-network:
|
||||
driver: bridge
|
||||
|
||||
Reference in New Issue
Block a user