Files
brunoandClaude 842fa8dbe5 feat: 完整AI SOC分析师平台 - LLM集成与前后端优化
本次提交包含完整的AI SOC(Security Operations Center)分析师平台,支持本地大模型和Claude API集成,实现端到端的安全威胁分析。

## 🚀 主要功能

### 后端架构 (FastAPI)
- **多源数据接入**: 支持JSON/CSV格式安全告警数据上传
- **智能预处理**: 基于YAML配置的字段映射和实体提取
- **图分析引擎**: NetworkX驱动的攻击链图构建和分析
- **评分系统**: 实体和子图的多维度风险评分算法
- **LLM集成**: 支持多提供商(Claude、OpenAI、本地模型)的智能报告生成
- **API接口**: 完整的RESTful API (Swagger文档: /docs)

### 前端界面 (Vue 3 + TypeScript)
- **拖拽上传**: 支持拖拽上传和实时预览
- **管道分析**: 可视化的数据处理管道状态
- **智能报告**: 动态生成的威胁分析报告和可视化
- **响应式设计**: 适配桌面和移动端的现代UI

### LLM智能分析
- **多模型支持**: qwen3(8B/32B)、deepseek-r1(70B)、Claude 4等
- **超时优化**: 分层超时配置(120s-600s)适配不同模型规模
- **内容清理**: 自动过滤模型思考过程,输出专业分析报告
- **中文优化**: 针对中文安全分析场景的prompt工程

## 🛠️ 技术栈

**后端**: FastAPI + SQLAlchemy + NetworkX + 多LLM提供商
**前端**: Vue 3 + TypeScript + Naive UI + Tailwind CSS + Vite
**数据处理**: YAML配置 + JSONPath表达式
**部署**: Docker支持 + 环境变量配置

## 🐛 修复的关键问题

1. **LLM超时问题**: 实现前后端分层超时配置,支持大模型长时间推理
2. **报告格式化**: 修复Markdown渲染和换行符显示问题
3. **数据映射**: 统一前后端字段命名和数据结构映射
4. **时间格式**: 修复时间戳解析和中文本地化显示
5. **思考标签清理**: 自动过滤qwen模型的<think>标签

## 📊 测试数据

包含完整的多阶段APT攻击场景测试数据:
- 钓鱼邮件 → 恶意软件执行 → C2通信
- 云凭证窃取 → 资源探测 → 横向渗透
- 后门用户创建 → 权限提升 → 容器控制

## 🔧 开发工具

- **模型切换**: switch_model.py 支持快速切换本地LLM模型
- **超时测试**: test_llm_timeout.py 验证不同模型性能
- **依赖安装**: install_llm_deps.py 自动安装LLM依赖

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-06 06:56:09 +08:00

165 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
LLM集成配置助手
"""
import os
import shutil
import yaml
def main():
print("🤖 AI SOC分析平台 LLM集成配置助手")
print("=" * 50)
# 创建.env文件
if not os.path.exists(".env"):
if os.path.exists(".env.example"):
shutil.copy(".env.example", ".env")
print("✅ 已创建 .env 文件")
else:
print("❌ .env.example 文件不存在")
return
else:
print("ℹ️ .env 文件已存在")
# 显示配置选项
print("\n🎯 选择你的LLM提供商:")
print("1. Claude 4 (推荐,需API密钥)")
print("2. 本地模型 (免费,需安装Ollama)")
print("3. OpenAI (需API密钥)")
print("4. 暂不配置 (使用模板生成)")
try:
choice = input("\n请输入选项 (1-4): ").strip()
if choice == "1":
configure_claude()
elif choice == "2":
configure_local()
elif choice == "3":
configure_openai()
elif choice == "4":
print("✅ 将使用模板生成,你可以稍后配置LLM")
else:
print("❌ 无效选项")
return
print(f"\n🎉 配置完成!请重启后端服务生效")
print("重启命令: python3 run_backend.py")
except KeyboardInterrupt:
print("\n\n👋 配置已取消")
def configure_claude():
print("\n🎨 配置Claude 4")
print("请访问 https://console.anthropic.com/ 获取API密钥")
api_key = input("请输入Claude API Key (sk-ant-...): ").strip()
if not api_key.startswith("sk-ant-"):
print("⚠️ API密钥格式可能不正确")
# 更新.env文件
update_env_file("CLAUDE_API_KEY", api_key)
# 更新llm.yaml配置
update_llm_config("claude")
print("✅ Claude 4 配置完成")
def configure_local():
print("\n🏠 配置本地模型")
print("请确保已安装Ollama: https://ollama.ai/")
print("\n推荐模型:")
print("- qwen2.5:7b (中文优秀, ~4.4GB)")
print("- qwen2.5:14b (性能更强, ~8.2GB)")
print("- llama3.1:8b (英文强, ~4.7GB)")
model = input("请输入模型名称 (默认: qwen2.5:7b): ").strip()
if not model:
model = "qwen2.5:7b"
port = input("请输入Ollama端口 (默认: 11434): ").strip()
if not port:
port = "11434"
# 更新llm.yaml配置
update_llm_config("local", model, f"http://localhost:{port}/v1")
print(f"✅ 本地模型配置完成")
print(f"请确保运行: ollama pull {model}")
print("然后启动服务: ollama serve")
def configure_openai():
print("\n🌐 配置OpenAI")
api_key = input("请输入OpenAI API Key (sk-proj-...): ").strip()
if not api_key.startswith("sk-"):
print("⚠️ API密钥格式可能不正确")
model = input("请输入模型名称 (默认: gpt-3.5-turbo): ").strip()
if not model:
model = "gpt-3.5-turbo"
# 更新.env文件
update_env_file("OPENAI_API_KEY", api_key)
# 更新llm.yaml配置
update_llm_config("openai", model)
print("✅ OpenAI 配置完成")
def update_env_file(key, value):
"""更新.env文件"""
try:
# 读取现有内容
lines = []
if os.path.exists(".env"):
with open(".env", "r") as f:
lines = f.readlines()
# 更新或添加键值
found = False
for i, line in enumerate(lines):
if line.startswith(f"{key}="):
lines[i] = f"{key}={value}\n"
found = True
break
if not found:
lines.append(f"{key}={value}\n")
# 写回文件
with open(".env", "w") as f:
f.writelines(lines)
except Exception as e:
print(f"❌ 更新.env文件失败: {e}")
def update_llm_config(provider, model=None, api_base=None):
"""更新LLM配置文件"""
try:
config_path = "configs/llm.yaml"
# 读取现有配置
with open(config_path, "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
# 更新提供商
config["provider"] = provider
# 更新具体配置
if model and provider in config.get("providers", {}):
config["providers"][provider]["model"] = model
if api_base and provider in config.get("providers", {}):
config["providers"][provider]["api_base"] = api_base
# 写回文件
with open(config_path, "w", encoding="utf-8") as f:
yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
except Exception as e:
print(f"❌ 更新配置文件失败: {e}")
if __name__ == "__main__":
main()