Files
erp-ass/backend/app/services/requirement_service.py
dazhuang acd73431ae feat: implement ERP AI Assistant Phase 1
Backend (FastAPI + SQLAlchemy + Claude API + RAG):
- Config management with Pydantic v2
- Database engine with connection pooling and SQL injection prevention
- AI engine with Claude API integration (support custom base URL)
- RAG engine with ChromaDB and sentence-transformers
- Requirement analysis service
- Config generation service
- Executor engine with SQL validation
- REST API endpoints: /analyze, /generate, /execute

Frontend (Vue 3 + Element Plus + Pinia):
- Complete 3-step workflow: analyze → generate → execute
- Step indicator with progress visualization
- Analysis result display with field table
- SQL preview with monospace font
- Execute confirmation dialog with safety warning
- Execution result display
- State management with Pinia
- API service integration

Security:
- SQL injection prevention with parameterized queries
- Dangerous SQL operation blocking
- Database password URL encoding
- Transaction auto-rollback
- Pydantic config validation

Features:
- Natural language requirement analysis
- Automated SQL configuration generation
- Safe execution with human review
- LAN access support
- Custom Claude API endpoint support

Documentation:
- README with quick start guide
- Quick start guide
- LAN access configuration
- Dependency fixes guide
- Claude API configuration
- Git operation guide
- Implementation report

Dependencies fixed:
- numpy<2.0.0 for chromadb compatibility
- sentence-transformers==2.7.0 for huggingface_hub compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:23:20 +00:00

147 lines
5.2 KiB
Python

"""Requirement Analysis Service.
This module provides the RequirementService class for analyzing user requirements
using Claude AI with RAG knowledge retrieval.
"""
from typing import Optional, Dict, Any
import uuid
from loguru import logger
from app.core.ai_engine import ClaudeEngine
from app.core.rag_engine import RAGEngine
from app.core.prompts import SYSTEM_PROMPT, ANALYZE_PROMPT_TEMPLATE
from app.core.db_engine import DatabaseEngine
class RequirementService:
"""Service for analyzing user requirements with AI assistance.
This service integrates Claude AI, RAG knowledge retrieval, and database
metadata to provide comprehensive requirement analysis.
"""
def __init__(self) -> None:
"""Initialize requirement service with required engines."""
self.ai_engine = ClaudeEngine()
self.rag_engine = RAGEngine()
self.db_engine = DatabaseEngine()
logger.info("RequirementService initialized")
async def analyze(
self,
user_input: str,
session_id: Optional[str] = None
) -> Dict[str, Any]:
"""Analyze user requirement and generate structured specification.
Args:
user_input: Natural language requirement from user
session_id: Session ID for context management (auto-generated if None)
Returns:
Structured requirement document as dictionary
Raises:
ValueError: If user_input is empty
Exception: If AI analysis fails
"""
# Validate input
if not user_input or not user_input.strip():
raise ValueError("User input cannot be empty")
# Generate session ID if not provided
session_id = session_id or str(uuid.uuid4())
logger.info(f"[{session_id}] Starting requirement analysis: {user_input[:50]}...")
try:
# Step 1: Retrieve relevant knowledge from RAG
logger.debug(f"[{session_id}] Searching knowledge base")
knowledge_results = self.rag_engine.search(user_input, top_k=3)
knowledge_context = self._format_knowledge_context(knowledge_results)
logger.info(f"[{session_id}] Retrieved {len(knowledge_results)} knowledge chunks")
# Step 2: Query existing database tables
logger.debug(f"[{session_id}] Querying existing tables")
existing_tables = self._get_existing_tables(user_input)
logger.info(f"[{session_id}] Retrieved existing table information")
# Step 3: Build prompt
prompt = ANALYZE_PROMPT_TEMPLATE.format(
user_input=user_input,
knowledge_context=knowledge_context,
existing_tables=existing_tables
)
messages = [
{"role": "user", "content": SYSTEM_PROMPT},
{"role": "assistant", "content": "我已了解平台配置规范,请告诉我您的需求。"},
{"role": "user", "content": prompt}
]
# Step 4: Call Claude API
logger.debug(f"[{session_id}] Calling Claude API")
response = await self.ai_engine.call_claude(messages, temperature=0.7)
# Step 5: Parse JSON response
result = self.ai_engine.parse_json_response(response)
function_name = result.get("功能名称", "Unknown")
logger.success(f"[{session_id}] Requirement analysis completed: {function_name}")
return result
except Exception as e:
logger.error(f"[{session_id}] Requirement analysis failed: {e}")
raise
def _format_knowledge_context(self, knowledge_results: list) -> str:
"""Format knowledge search results into context string.
Args:
knowledge_results: List of knowledge search results
Returns:
Formatted knowledge context string
"""
if not knowledge_results:
return "未找到相关知识库内容"
context_parts = []
for result in knowledge_results:
source = result.get("metadata", {}).get("source", "文档")
content = result.get("content", "")
if content:
context_parts.append(f"{source}\n{content}")
return "\n\n".join(context_parts) if context_parts else "未找到相关知识库内容"
def _get_existing_tables(self, user_input: str) -> str:
"""Query existing database tables relevant to user input.
Args:
user_input: User requirement text
Returns:
Formatted string listing existing tables
"""
try:
# Query top 10 tables (simplified version - could be enhanced with relevance matching)
sql = """
SELECT TOP 10 TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_NAME
"""
tables = self.db_engine.execute_sql(sql)
if not tables:
return "未找到现有数据表"
table_list = [f"- {t[0]}" for t in tables]
return "\n".join(table_list)
except Exception as e:
logger.warning(f"Failed to query existing tables: {e}")
return "无法获取现有表信息"