feat(dc/tool-c): 完成AI代码生成服务(Day 3 MVP)
核心功能: - 新增AICodeService(550行):AI代码生成核心服务 - 新增AIController(257行):4个API端点 - 新增dc_tool_c_ai_history表:存储对话历史 - 实现自我修正机制:最多3次智能重试 - 集成LLMFactory:复用通用能力层 - 10个Few-shot示例:覆盖Level 1-4场景 技术优化: - 修复NaN序列化问题(Python端转None) - 修复数据传递问题(从Session获取真实数据) - 优化System Prompt(明确环境信息) - 调整Few-shot示例(移除import语句) 测试结果: - 通过率:9/11(81.8%) 达到MVP标准 - 成功场景:缺失值处理、编码、分箱、BMI、筛选、填补、统计、分类 - 待优化:数值清洗、智能去重(已记录技术债务TD-C-006) API端点: - POST /api/v1/dc/tool-c/ai/generate(生成代码) - POST /api/v1/dc/tool-c/ai/execute(执行代码) - POST /api/v1/dc/tool-c/ai/process(生成并执行,一步到位) - GET /api/v1/dc/tool-c/ai/history/:sessionId(对话历史) 文档更新: - 新增Day 3开发完成总结(770行) - 新增复杂场景优化技术债务(TD-C-006) - 更新工具C当前状态文档 - 更新技术债务清单 影响范围: - backend/src/modules/dc/tool-c/*(新增2个文件,更新1个文件) - backend/scripts/create-tool-c-ai-history-table.mjs(新增) - backend/prisma/schema.prisma(新增DcToolCAiHistory模型) - extraction_service/services/dc_executor.py(NaN序列化修复) - docs/03-业务模块/DC-数据清洗整理/*(5份文档更新) Breaking Changes: 无 总代码行数:+950行 Refs: #Tool-C-Day3
This commit is contained in:
@@ -199,3 +199,5 @@ checkDCTables();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
155
backend/scripts/create-tool-c-ai-history-table.mjs
Normal file
155
backend/scripts/create-tool-c-ai-history-table.mjs
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 创建 Tool C AI对话历史表
|
||||
*
|
||||
* 执行方式:node scripts/create-tool-c-ai-history-table.mjs
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function createAiHistoryTable() {
|
||||
console.log('========================================');
|
||||
console.log('开始创建 Tool C AI对话历史表');
|
||||
console.log('========================================\n');
|
||||
|
||||
try {
|
||||
// 1. 检查表是否已存在
|
||||
console.log('[1/4] 检查表是否已存在...');
|
||||
const checkResult = await prisma.$queryRawUnsafe(`
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'dc_schema'
|
||||
AND table_name = 'dc_tool_c_ai_history'
|
||||
) as exists
|
||||
`);
|
||||
|
||||
const tableExists = checkResult[0].exists;
|
||||
|
||||
if (tableExists) {
|
||||
console.log('✅ 表已存在: dc_schema.dc_tool_c_ai_history');
|
||||
console.log('\n如需重新创建,请手动执行: DROP TABLE dc_schema.dc_tool_c_ai_history CASCADE;\n');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 表不存在,准备创建\n');
|
||||
|
||||
// 2. 创建表
|
||||
console.log('[2/4] 创建表 dc_tool_c_ai_history...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE dc_schema.dc_tool_c_ai_history (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id VARCHAR(255) NOT NULL,
|
||||
user_id VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(50) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
|
||||
-- Tool C特有字段
|
||||
generated_code TEXT,
|
||||
code_explanation TEXT,
|
||||
execute_status VARCHAR(50),
|
||||
execute_result JSONB,
|
||||
execute_error TEXT,
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
|
||||
-- LLM相关
|
||||
model VARCHAR(100),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
console.log('✅ 表创建成功\n');
|
||||
|
||||
// 3. 创建索引
|
||||
console.log('[3/4] 创建索引...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX idx_dc_tool_c_ai_history_session_id
|
||||
ON dc_schema.dc_tool_c_ai_history(session_id)
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX idx_dc_tool_c_ai_history_user_id
|
||||
ON dc_schema.dc_tool_c_ai_history(user_id)
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX idx_dc_tool_c_ai_history_created_at
|
||||
ON dc_schema.dc_tool_c_ai_history(created_at)
|
||||
`);
|
||||
console.log('✅ 索引创建成功\n');
|
||||
|
||||
// 4. 添加注释
|
||||
console.log('[4/4] 添加表注释...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON TABLE dc_schema.dc_tool_c_ai_history
|
||||
IS 'Tool C (科研数据编辑器) AI对话历史表'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_ai_history.session_id
|
||||
IS '关联Tool C Session ID'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_ai_history.generated_code
|
||||
IS 'AI生成的Pandas代码'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_ai_history.execute_status
|
||||
IS '执行状态: pending/success/failed'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_ai_history.retry_count
|
||||
IS '自我修正重试次数'
|
||||
`);
|
||||
console.log('✅ 注释添加成功\n');
|
||||
|
||||
// 5. 验证表创建
|
||||
console.log('========================================');
|
||||
console.log('验证表结构');
|
||||
console.log('========================================\n');
|
||||
|
||||
const columns = await prisma.$queryRawUnsafe(`
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'dc_schema'
|
||||
AND table_name = 'dc_tool_c_ai_history'
|
||||
ORDER BY ordinal_position
|
||||
`);
|
||||
|
||||
console.log('表结构:');
|
||||
console.table(columns);
|
||||
|
||||
const indexes = await prisma.$queryRawUnsafe(`
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE schemaname = 'dc_schema'
|
||||
AND tablename = 'dc_tool_c_ai_history'
|
||||
`);
|
||||
|
||||
console.log('\n索引:');
|
||||
console.table(indexes);
|
||||
|
||||
console.log('\n========================================');
|
||||
console.log('🎉 Tool C AI对话历史表创建成功!');
|
||||
console.log('========================================\n');
|
||||
console.log('表名: dc_schema.dc_tool_c_ai_history');
|
||||
console.log(`列数: ${columns.length}`);
|
||||
console.log(`索引数: ${indexes.length}\n`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ 创建表失败:', error.message);
|
||||
console.error('\n详细错误:');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// 执行
|
||||
createAiHistoryTable()
|
||||
.then(() => {
|
||||
console.log('脚本执行完成');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('脚本执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
142
backend/scripts/create-tool-c-table.js
Normal file
142
backend/scripts/create-tool-c-table.js
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 创建 Tool C Session 表
|
||||
*
|
||||
* 执行方式:node scripts/create-tool-c-table.js
|
||||
*/
|
||||
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function createToolCTable() {
|
||||
console.log('========================================');
|
||||
console.log('开始创建 Tool C Session 表');
|
||||
console.log('========================================\n');
|
||||
|
||||
try {
|
||||
// 1. 检查表是否已存在
|
||||
console.log('[1/4] 检查表是否已存在...');
|
||||
const checkResult = await prisma.$queryRawUnsafe(`
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'dc_schema'
|
||||
AND table_name = 'dc_tool_c_sessions'
|
||||
) as exists
|
||||
`);
|
||||
|
||||
const tableExists = checkResult[0].exists;
|
||||
|
||||
if (tableExists) {
|
||||
console.log('✅ 表已存在: dc_schema.dc_tool_c_sessions');
|
||||
console.log('\n是否需要重新创建?(这将删除现有数据)');
|
||||
console.log('如需重新创建,请手动执行: DROP TABLE dc_schema.dc_tool_c_sessions CASCADE;\n');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 表不存在,准备创建\n');
|
||||
|
||||
// 2. 创建表
|
||||
console.log('[2/4] 创建表 dc_tool_c_sessions...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE dc_schema.dc_tool_c_sessions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR(255) NOT NULL,
|
||||
file_name VARCHAR(500) NOT NULL,
|
||||
file_key VARCHAR(500) NOT NULL,
|
||||
|
||||
total_rows INTEGER NOT NULL,
|
||||
total_cols INTEGER NOT NULL,
|
||||
columns JSONB NOT NULL,
|
||||
encoding VARCHAR(50),
|
||||
file_size INTEGER NOT NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL
|
||||
)
|
||||
`);
|
||||
console.log('✅ 表创建成功\n');
|
||||
|
||||
// 3. 创建索引
|
||||
console.log('[3/4] 创建索引...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX idx_dc_tool_c_sessions_user_id ON dc_schema.dc_tool_c_sessions(user_id)
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE INDEX idx_dc_tool_c_sessions_expires_at ON dc_schema.dc_tool_c_sessions(expires_at)
|
||||
`);
|
||||
console.log('✅ 索引创建成功\n');
|
||||
|
||||
// 4. 添加注释
|
||||
console.log('[4/4] 添加表注释...');
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON TABLE dc_schema.dc_tool_c_sessions IS 'Tool C (科研数据编辑器) Session会话表'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_sessions.file_key IS 'OSS存储路径: dc/tool-c/sessions/{timestamp}-{fileName}'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_sessions.columns IS '列名数组 ["age", "gender", "diagnosis"]'
|
||||
`);
|
||||
await prisma.$executeRawUnsafe(`
|
||||
COMMENT ON COLUMN dc_schema.dc_tool_c_sessions.expires_at IS '过期时间(创建后10分钟)'
|
||||
`);
|
||||
console.log('✅ 注释添加成功\n');
|
||||
|
||||
// 5. 验证表创建
|
||||
console.log('========================================');
|
||||
console.log('验证表结构');
|
||||
console.log('========================================\n');
|
||||
|
||||
const columns = await prisma.$queryRawUnsafe(`
|
||||
SELECT column_name, data_type, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'dc_schema'
|
||||
AND table_name = 'dc_tool_c_sessions'
|
||||
ORDER BY ordinal_position
|
||||
`);
|
||||
|
||||
console.log('表结构:');
|
||||
console.table(columns);
|
||||
|
||||
const indexes = await prisma.$queryRawUnsafe(`
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE schemaname = 'dc_schema'
|
||||
AND tablename = 'dc_tool_c_sessions'
|
||||
`);
|
||||
|
||||
console.log('\n索引:');
|
||||
console.table(indexes);
|
||||
|
||||
console.log('\n========================================');
|
||||
console.log('🎉 Tool C Session 表创建成功!');
|
||||
console.log('========================================\n');
|
||||
console.log('表名: dc_schema.dc_tool_c_sessions');
|
||||
console.log(`列数: ${columns.length}`);
|
||||
console.log(`索引数: ${indexes.length}\n`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ 创建表失败:', error.message);
|
||||
console.error('\n详细错误:');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// 执行
|
||||
createToolCTable()
|
||||
.then(() => {
|
||||
console.log('脚本执行完成');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('脚本执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
||||
@@ -136,3 +136,4 @@ createToolCTable()
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user