Initial commit: 国土空间规划课程智能体 v1.0

单容器 Docker 架构的国土空间规划课程智能问答系统,集成 FastAPI 后端与 Next.js 前端。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 09:40:18 +08:00
commit ddbb79b9f6
167 changed files with 44147 additions and 0 deletions
@@ -0,0 +1,97 @@
"""
统一图像生成服务基类
支持硅基流动平台的多种图像生成模型
"""
import base64
import uuid
from pathlib import Path
from typing import Dict, Any
import httpx
from src.core.config import settings
class ImageGenerationService:
"""统一的图像生成服务基类"""
def __init__(self):
self.base_url = "https://api.siliconflow.cn/v1/image/generations"
self.api_key = settings.siliconflow_api_key
self.timeout = 60
async def call_api(self, model: str, payload: dict) -> dict:
"""调用硅基流动 API"""
print(f"[DEBUG] 调用SiliconFlow API: {self.base_url}")
print(f"[DEBUG] 模型: {model}")
print(f"[DEBUG] 请求参数: {payload}")
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.post(
self.base_url,
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
},
json={"model": model, **payload}
)
response.raise_for_status()
result = response.json()
print(f"[DEBUG] API响应状态: {response.status_code}")
print(f"[DEBUG] API响应类型: {type(result)}")
print(f"[DEBUG] API响应键: {list(result.keys()) if isinstance(result, dict) else '非字典类型'}")
return result
def save_image(self, image_id: str, base64_data: str) -> str:
"""保存 base64 图像到本地文件系统"""
try:
# 清理base64数据(移除可能的data URL前缀)
if base64_data.startswith('data:image'):
base64_data = base64_data.split(',')[1]
# 移除可能的空白字符
base64_data = base64_data.strip()
print(f"[DEBUG] 开始解码base64数据,长度: {len(base64_data)}")
# 解码 base64 数据
image_bytes = base64.b64decode(base64_data)
# 验证是否为有效的图片数据
if len(image_bytes) == 0:
raise Exception("解码后的图像数据为空")
print(f"[DEBUG] 图像数据大小: {len(image_bytes)} bytes")
# 确保目录存在
image_dir = Path(settings.generated_images_dir)
image_dir.mkdir(parents=True, exist_ok=True)
# 保存图像文件
image_path = image_dir / f"{image_id}.png"
with open(image_path, "wb") as f:
f.write(image_bytes)
print(f"[DEBUG] 图像已保存到: {image_path}")
return str(image_path)
except Exception as e:
print(f"[ERROR] 保存图像失败: {str(e)}")
print(f"[ERROR] base64数据长度: {len(base64_data) if base64_data else 0}")
print(f"[ERROR] base64数据前100字符: {base64_data[:100] if base64_data else 'None'}")
raise Exception(f"保存图像失败: {str(e)}")
def generate_image_id(self) -> str:
"""生成唯一的图像ID"""
return str(uuid.uuid4())
def get_image_url(self, image_id: str) -> str:
"""获取图像的访问URL"""
return f"/generated_images/{image_id}.png"