基于Electron与LangGraph的智能文档分析助手开发实战
Agent工作流ElectronLangGraph
于 2026-07-31 04:13:03 修改 ·本内容遵循CC 4.0 BY-SA版权协议
在实际全栈项目中,单纯调用大模型 API 已经无法满足复杂业务需求。真正能体现技术深度的,是如何让 AI 按照预设流程执行多步骤任务、管理状态、处理异常,并最终通过桌面应用交付给用户。这正是 Agent 工作流技术的核心价值。
Electron 作为跨平台桌面应用框架,能让我们用 Web 技术构建原生体验的应用界面。而 LangGraph 作为 LangChain 生态中的工作流引擎,专门解决多步骤 AI 任务的编排问题。将两者结合,就能打造出既有智能决策能力又有良好用户体验的桌面级 AI 应用。
本文将以一个完整的“智能文档分析助手”项目为例,带你从零搭建基于 Electron + LangGraph 的 AI 全栈应用。你会学到如何设计 Agent 工作流、处理进程间通信、集成大模型能力,最终得到一个可直接用于面试展示的生产级项目。
1. 理解 LangGraph 如何为 AI 任务编排工作流
1.1 从单次问答到多步骤工作流
传统的大模型调用通常是单次请求-响应模式。但在真实业务场景中,很多任务需要多个步骤才能完成。比如分析一份技术文档,可能需要先提取关键信息,然后进行分类,最后生成总结报告。如果只用简单的 API 调用,就需要手动编写大量胶水代码来管理这些步骤之间的状态传递和流程控制。
LangGraph 的核心思想是将 AI 任务建模为有向图(Graph),每个节点代表一个处理步骤,边代表步骤之间的流转条件。这种设计让复杂的工作流变得可视化和可维护。
1.2 LangGraph 的核心概念解析
State 是工作流中传递的共享状态对象,通常是一个字典或 Pydantic 模型,包含了当前任务的所有相关信息。
PYTHON
1
from typing import TypedDict, List, Annotated
2
from langgraph.graph import add_messages
4
class AgentState(TypedDict):
8
collected_info: List[str]
12
reasoning: Annotated[str, add_messages]
Node 是工作流中的处理单元,每个节点接收当前状态,执行特定操作,返回更新后的状态。
PYTHON
1
def information_collector_node(state: AgentState):
3
question = state["question"]
6
collected_info = search_related_documents(question)
10
"collected_info": collected_info,
11
"reasoning": f"已收集到 {len(collected_info)} 条相关信息"
Edge 定义节点之间的流转逻辑,可以是无条件流转,也可以基于条件判断。
PYTHON
1
from langgraph.graph import END, START
3
def should_continue_analysis(state: AgentState) -> str:
5
if len(state["collected_info"]) >= 3:
1.3 与 LangChain 的关系和区别
LangChain 提供了构建 AI 应用的基础组件,比如模型调用、提示词模板、记忆管理等。而 LangGraph 是在此基础上增加了工作流编排能力。可以理解为 LangChain 解决的是"怎么做"的问题,LangGraph 解决的是"按什么顺序做"的问题。
在实际项目中,通常会同时使用两者:用 LangChain 的组件实现具体功能,用 LangGraph 将这些功能组织成完整的工作流。
2. 搭建 Electron 项目基础架构
2.1 环境准备和项目初始化
首先确保你的开发环境满足以下要求:
| 组件 |
版本要求 |
检查命令 |
| Node.js |
18.x 或更高 |
node --version |
| npm |
9.x 或更高 |
npm --version |
| Python |
3.8+ |
python --version |
创建项目目录结构:
BASH
2
mkdir smart-doc-analyzer
11
npm install electron --save-dev
12
npm install electron-builder --save-dev
13
npm install concurrently --save-dev
25
source venv/bin/activate
28
pip install langgraph langchain-openai python-dotenv
2.2 Electron 主进程和渲染进程配置
Electron 应用采用主进程-渲染进程架构。主进程负责应用生命周期管理,渲染进程负责 UI 展示。
主进程配置 (electron-app/main.js):
JAVASCRIPT
1
const { app, BrowserWindow, ipcMain } = require('electron');
2
const path = require('path');
3
const { spawn } = require('child_process');
8
function createWindow() {
9
mainWindow = new BrowserWindow({
13
nodeIntegration: false,
14
contextIsolation: true,
15
preload: path.join(__dirname, 'preload.js')
19
mainWindow.loadFile('index.html');
22
if (process.env.NODE_ENV === 'development') {
23
mainWindow.webContents.openDevTools();
28
function startPythonBackend() {
29
const pythonPath = process.platform === 'win32' ? 'venv/Scripts/python.exe' : 'venv/bin/python';
30
const scriptPath = path.join(__dirname, '../python-backend/app.py');
32
pythonProcess = spawn(pythonPath, [scriptPath], {
33
cwd: path.join(__dirname, '../python-backend')
36
pythonProcess.stdout.on('data', (data) => {
37
console.log(`Python 输出: ${data}`);
40
pythonProcess.stderr.on('data', (data) => {
41
console.error(`Python 错误: ${data}`);
45
app.whenReady().then(() => {
50
app.on('window-all-closed', () => {
预加载脚本 (electron-app/preload.js) 负责安全地暴露 API 给渲染进程:
JAVASCRIPT
1
const { contextBridge, ipcRenderer } = require('electron');
3
contextBridge.exposeInMainWorld('electronAPI', {
4
analyzeDocument: (content) => ipcRenderer.invoke('analyze-document', content),
5
getAnalysisStatus: () => ipcRenderer.invoke('get-analysis-status')
2.3 进程间通信机制设计
Electron 中主进程和渲染进程不能直接共享内存,需要通过 IPC(进程间通信)进行数据交换。我们的设计采用请求-响应模式:
JAVASCRIPT
2
ipcMain.handle('analyze-document', async (event, documentContent) => {
5
const response = await fetch('http://localhost:8000/analyze', {
8
'Content-Type': 'application/json',
10
body: JSON.stringify({ content: documentContent })
13
const result = await response.json();
16
console.error('分析请求失败:', error);
17
return { error: '分析服务不可用' };
3. 实现智能文档分析 Agent 工作流
3.1 定义文档分析的工作流状态
首先设计分析任务的状态结构,明确每个步骤需要传递和保存哪些信息:
PYTHON
1
from typing import TypedDict, List, Optional
2
from langchain_core.messages import BaseMessage
5
class DocumentAnalysisState(TypedDict):
11
document_type: Optional[str]
15
complexity_level: Optional[str]
17
summary_report: Optional[str]
19
error_message: Optional[str]
21
messages: Annotated[List[BaseMessage], operator.add]
3.2 构建四阶段分析工作流
一个完整的文档分析包含四个核心阶段,每个阶段由专门的 Agent 负责:
PYTHON
1
from langgraph.graph import StateGraph, END
3
def create_analysis_workflow():
5
workflow = StateGraph(DocumentAnalysisState)
8
workflow.add_node("document_classifier", document_classifier_node)
9
workflow.add_node("information_extractor", information_extractor_node)
10
workflow.add_node("tech_analyzer", tech_analyzer_node)
11
workflow.add_node("report_generator", report_generator_node)
14
workflow.set_entry_point("document_classifier")
17
workflow.add_edge("document_classifier", "information_extractor")
18
workflow.add_edge("information_extractor", "tech_analyzer")
19
workflow.add_edge("tech_analyzer", "report_generator")
20
workflow.add_edge("report_generator", END)
22
return workflow.compile()
25
def document_classifier_node(state: DocumentAnalysisState):
26
from langchain_core.prompts import ChatPromptTemplate
27
from langchain_openai import ChatOpenAI
29
classifier_prompt = ChatPromptTemplate.from_template("""
42
llm = ChatOpenAI(model="gpt-3.5-turbo")
43
chain = classifier_prompt | llm
45
response = chain.invoke({"document_content": state["document_content"]})
48
"document_type": response.content,
49
"messages": [{"role": "system", "content": f"文档类型识别为: {response.content}"}]
53
def information_extractor_node(state: DocumentAnalysisState):
54
extractor_prompt = ChatPromptTemplate.from_template("""
55
根据识别的文档类型「{document_type}」,从以下内容中提取关键信息点:
64
返回格式:JSON数组,每个元素是一个信息点字符串。
67
llm = ChatOpenAI(model="gpt-3.5-turbo")
68
chain = extractor_prompt | llm
70
response = chain.invoke({
71
"document_type": state["document_type"],
72
"document_content": state["document_content"]
78
key_points = json.loads(response.content)
81
key_points = [point.strip() for point in response.content.split('\n') if point.strip()]
84
"key_points": key_points,
85
"messages": [{"role": "system", "content": f"提取到 {len(key_points)} 个关键信息点"}]
3.3 配置大模型连接和参数调优
在 Python 后端创建模型配置管理:
PYTHON
3
from dotenv import load_dotenv
8
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
9
MODEL_NAME = "gpt-3.5-turbo"
15
from langchain_openai import ChatOpenAI
18
temperature=cls.TEMPERATURE,
19
max_tokens=cls.MAX_TOKENS,
20
api_key=cls.OPENAI_API_KEY
创建 FastAPI 后端服务:
PYTHON
2
from fastapi import FastAPI, HTTPException
3
from fastapi.middleware.cors import CORSMiddleware
4
from pydantic import BaseModel
5
from workflow import create_analysis_workflow
7
app = FastAPI(title="智能文档分析服务")
12
allow_origins=["http://localhost:3000", "electron://localhost"],
13
allow_credentials=True,
18
class AnalysisRequest(BaseModel):
21
class AnalysisResponse(BaseModel):
27
processing_time: float
30
async def analyze_document(request: AnalysisRequest):
33
workflow = create_analysis_workflow()
37
start_time = time.time()
39
result = workflow.invoke({
40
"document_content": request.content,
46
processing_time = time.time() - start_time
48
return AnalysisResponse(
49
document_type=result.get("document_type", "未知"),
50
key_points=result.get("key_points", []),
51
tech_stack=result.get("tech_stack", []),
52
complexity_level=result.get("complexity_level", "中等"),
53
summary_report=result.get("summary_report", ""),
54
processing_time=processing_time
57
except Exception as e:
58
raise HTTPException(status_code=500, detail=f"分析失败: {str(e)}")
60
if __name__ == "__main__":
62
uvicorn.run(app, host="0.0.0.0", port=8000)
4. 前端界面与工作流状态可视化
4.1 设计响应式文档分析界面
创建 Electron 渲染进程的界面 (electron-app/index.html):
HTML
5
<title>智能文档分析助手</title>
11
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
22
border: 1px solid #ddd;
38
.analyze-btn:disabled {
47
.workflow-visualization {
49
justify-content: space-between;
63
border: 2px solid #2196f3;
68
border: 2px solid #4caf50;
73
<div class="container">
76
<div class="input-section">
77
<textarea id="documentInput" placeholder="请输入要分析的文档内容..."></textarea>
78
<button id="analyzeBtn" class="analyze-btn">开始分析</button>
81
<div class="workflow-visualization" id="workflowVis">
82
<div class="workflow-step" id="step1">
86
<div class="workflow-step" id="step2">
90
<div class="workflow-step" id="step3">
94
<div class="workflow-step" id="step4">
100
<div class="results-section" id="resultsSection">
102
<div id="analysisResults"></div>
106
<script src="renderer.js"></script>
4.2 实时工作流状态监控
在渲染进程中实现状态监控逻辑 (electron-app/renderer.js):
JAVASCRIPT
1
class WorkflowMonitor {
4
this.steps = ['step1', 'step2', 'step3', 'step4'];
5
this.intervalId = null;
9
this.updateStepVisualization(0, 'active');
12
this.intervalId = setInterval(() => {
13
this.simulateProgress();
18
if (this.currentStep > 0) {
19
this.updateStepVisualization(this.currentStep - 1, 'completed');
22
if (this.currentStep < this.steps.length) {
23
this.updateStepVisualization(this.currentStep, 'active');
26
this.stopMonitoring();
30
updateStepVisualization(stepIndex, status) {
31
const stepElement = document.getElementById(this.steps[stepIndex]);
32
stepElement.className = `workflow-step step-${status}`;
36
if (this.intervalId) {
37
clearInterval(this.intervalId);
38
this.intervalId = null;
42
this.steps.forEach((stepId, index) => {
43
this.updateStepVisualization(index, 'completed');
49
document.getElementById('analyzeBtn').addEventListener('click', async () => {
50
const documentContent = document.getElementById('documentInput').value.trim();
51
const analyzeBtn = document.getElementById('analyzeBtn');
53
if (!documentContent) {
58
analyzeBtn.disabled = true;
59
analyzeBtn.textContent = '分析中...';
62
document.getElementById('workflowVis').style.display = 'flex';
65
const monitor = new WorkflowMonitor();
66
monitor.startMonitoring();
70
const result = await window.electronAPI.analyzeDocument(documentContent);
74
monitor.stopMonitoring();
75
displayResults(result);
76
analyzeBtn.disabled = false;
77
analyzeBtn.textContent = '开始分析';
81
console.error('分析失败:', error);
82
alert('分析失败,请检查网络连接和后端服务');
83
analyzeBtn.disabled = false;
84
analyzeBtn.textContent = '开始分析';
88
function displayResults(result) {
89
const resultsSection = document.getElementById('resultsSection');
90
const resultsDiv = document.getElementById('analysisResults');
92
resultsDiv.innerHTML = `
93
<div style="background: #f5f5f5; padding: 20px; border-radius: 6px;">
94
<h3>📄 文档类型: ${result.document_type}</h3>
95
<h3>⚡ 复杂度: ${result.complexity_level}</h3>
98
${result.tech_stack.map(tech => `<li>${tech}</li>`).join('')}
102
${result.key_points.map(point => `<li>${point}</li>`).join('')}
105
<p>${result.summary_report}</p>
106
<p><small>处理时间: ${result.processing_time.toFixed(2)} 秒</small></p>
110
resultsSection.style.display = 'block';
5. 项目部署与生产环境优化
5.1 应用打包和分发配置
配置 Electron Builder 进行应用打包 (electron-app/package.json):
JSON
2
"name": "smart-doc-analyzer",
4
"description": "智能文档分析桌面应用",
8
"build": "electron-builder",
9
"build-win": "electron-builder --win",
10
"build-mac": "electron-builder --mac",
11
"build-linux": "electron-builder --linux",
12
"dev": "concurrently \"npm run start-backend\" \"wait-on http://localhost:8000 && electron .\"",
13
"start-backend": "cd ../python-backend && venv/bin/python app.py"
16
"appId": "com.yourcompany.smart-doc-analyzer",
17
"productName": "智能文档分析助手",
23
"!../python-backend/venv",
24
"!../python-backend/__pycache__"
28
"icon": "assets/icon.ico"
32
"icon": "assets/icon.icns"
36
"icon": "assets/icon.png"
40
"electron": "^27.0.0",
41
"electron-builder": "^24.6.0",
42
"concurrently": "^8.0.0",
5.2 生产环境配置和安全加固
创建环境配置管理:
PYTHON
4
class ProductionConfig:
6
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
13
CORS_ORIGINS = ["app://localhost"]
14
RATE_LIMIT = "100/hour"
18
LOG_FILE = "/var/log/smart-analyzer/app.log"
21
def validate_config(cls):
22
if not cls.OPENAI_API_KEY:
23
raise ValueError("OPENAI_API_KEY 环境变量未设置")
6. 常见问题排查与性能优化
6.1 Electron 应用典型问题解决
问题1:Electron 应用启动失败
现象:应用无法启动,控制台报错 Error: Cannot find module
排查步骤:
- 检查
package.json 中的 main 字段指向正确的入口文件
- 确认所有依赖已正确安装:
npm install
- 检查 Node.js 版本兼容性
问题2:Python 后端服务连接失败
现象:前端显示"分析服务不可用"
排查步骤:
- 确认 Python 后端服务已启动:
ps aux | grep python
- 检查端口占用:
netstat -an | grep 8000
- 查看后端日志:
tail -f python-backend/app.log
问题3:大模型 API 调用超时
现象:分析过程卡住,最终超时
解决方案:
PYTHON
3
model=ModelConfig.MODEL_NAME,
4
temperature=ModelConfig.TEMPERATURE,
5
max_tokens=ModelConfig.MAX_TOKENS,
6
api_key=ModelConfig.OPENAI_API_KEY,
6.2 LangGraph 工作流性能优化
优化1:缓存中间结果
对于重复的文档分析,可以缓存中间结果避免重复计算:
PYTHON
1
from functools import lru_cache
4
@lru_cache(maxsize=100)
5
def get_document_hash(content: str) -> str:
6
return hashlib.md5(content.encode()).hexdigest()
8
def document_classifier_node(state: DocumentAnalysisState):
9
content_hash = get_document_hash(state["document_content"])
12
cached_result = cache.get(f"classification_{content_hash}")
17
result = process_classification(state)
20
cache.set(f"classification_{content_hash}", result, timeout=3600)
优化2:并行处理独立步骤
对于可以并行执行的步骤,使用 LangGraph 的并行节点:
PYTHON
1
from langgraph.graph import StateGraph, END
2
from langgraph.prebuilt import create_react_agent
4
def create_parallel_workflow():
5
workflow = StateGraph(DocumentAnalysisState)
8
workflow.add_node("tech_analyzer", tech_analyzer_node)
9
workflow.add_node("complexity_analyzer", complexity_analyzer_node)
12
workflow.add_conditional_edges(
13
"information_extractor",
14
lambda state: ["tech_analyzer", "complexity_analyzer"],
6.3 内存管理和资源清理
Electron 应用需要特别注意内存管理,避免内存泄漏:
JAVASCRIPT
2
mainWindow.on('closed', () => {
11
function setupIPCHandlers() {
14
handlers.push(ipcMain.handle('analyze-document', analyzeHandler));
18
handlers.forEach(handler => {
19
ipcMain.removeHandler(handler);
7. 扩展方向与面试项目建议
7.1 项目功能扩展思路
扩展1:支持多文档批量分析
修改工作流状态,支持文档列表处理:
PYTHON
1
class BatchAnalysisState(TypedDict):
2
documents: List[Dict[str, str]]
扩展2:增加自定义分析模板
允许用户定义自己的分析规则和流程:
PYTHON
1
class AnalysisTemplate:
2
def __init__(self, name: str, steps: List[str], prompts: Dict):
7
def create_workflow(self):
9
workflow = StateGraph(DocumentAnalysisState)
11
return workflow.compile()
扩展3:集成本地模型
除了 OpenAI,可以集成本地部署的模型:
PYTHON
1
from langchain_community.llms import Ollama
4
return Ollama(model="llama2", temperature=0.1)
7.2 面试项目展示要点
在技术面试中展示这个项目时,重点突出以下技术深度:
架构设计能力
- 前后端分离架构(Electron + FastAPI)
- 进程间通信设计
- 工作流引擎选型和实现
AI 工程化能力
- Agent 工作流设计模式
- 大模型集成最佳实践
- 提示词工程和结果处理
工程实践能力
- 错误处理和重试机制
- 性能监控和优化
- 安全配置和部署方案
准备具体的 metrics 来证明项目价值:
- 分析准确率提升数据
- 处理时间优化对比
- 用户满意度反馈
这个项目架构展示了现代 AI 应用的完整技术栈,从桌面端到后端服务,从工作流编排到模型集成,覆盖了全栈开发的各个关键环节。在实际面试中,可以根据岗位需求侧重展示不同的技术维度。