使用 openai-agent-python
和 dify-workflows-mcp
进行前端代码优化
介绍
openai-agent-python
最新发布了 MCP
(Model Control Protocol)能力,本文将结合 dify-workflows-mcp
进行代码演示,展示如何利用这些工具优化前端代码。
准备工作
安装依赖包
首先需要安装必要的 Python 包:
pip install openai-agents python-dotenv
配置环境变量
创建 .env
文件并配置以下变量:
OPEN_API_MODEL=deepseek-v3
OPEN_API_KEY=sk-xxx
OPEN_API_BASE=https://api.deepseek.com/v1
注意:如果使用 OpenAI 官方模型,只需配置
OPEN_API_KEY
即可。
配置自定义大语言模型
创建 llm.py
文件配置自定义 LLM 客户端:
from dotenv import load_dotenv
from openai import AsyncOpenAI
from agents import set_default_openai_api, set_default_openai_client, set_tracing_disabled
import os
load_dotenv()
BASE_URL = os.getenv("OPEN_API_BASE") or ""
API_KEY = os.getenv("OPEN_API_KEY") or ""
MODEL_NAME = os.getenv("OPEN_API_MODEL") or ""
if not BASE_URL or not API_KEY or not MODEL_NAME:
raise ValueError("Please set OPEN_API_BASE, OPEN_API_KEY, OPEN_API_MODEL in .env file")
client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY, max_retries=3)
set_default_openai_client(client=client, use_for_tracing=False)
set_default_openai_api("chat_completions")
set_tracing_disabled(disabled=True)
Dify 工作流调用实现
创建 dify_agent.py
文件实现 Dify 工作流调用:
import asyncio
import os
import shutil
from agents import Agent, Runner, ModelSettings
from agents.mcp import MCPServer, MCPServerStdio
from llm import MODEL_NAME
async def run(server: MCPServer):
# 创建 Agent 并配置 dify mcp server
agent = Agent(
name="dify agent",
instructions="You are a helpful assistant.",
model=MODEL_NAME,
model_settings=ModelSettings(temperature=0.3),
mcp_servers=[server]
)
current_dir = os.path.dirname(os.path.abspath(__file__))
target_file = os.path.join(current_dir, "files/useCountdown.ts")
with open(target_file, "r") as f:
code = f.read()
message = """
使用 dify workflows mcp 帮我进行前端代码的优化,代码如下:
```
{code}
```
""".format(code=code)
print(f"Running: {
message}")
result = await Runner.run(starting_agent=agent, input=message)
print(result) # 输出 dify 工作流执行结果
async def main():
# 加载 dify-workflow-mcp 打包的入口文件
mcp_file = os.path.join(os.getcwd(), "dify-workflow-mcp/build/index.js")
# 启动 dify MCP Server
async with MCPServerStdio(
name="dify workflows mcp",
params={
"command": "node",
"args": [mcp_file]
}
) as server:
await run(server)
if __name__ == "__main__":
# 确保可以使用 npx 命令
if not shutil.which("npx"):
raise RuntimeError("npx is not installed. Please install it with `npm install -g npx`.")
asyncio.run(main())
执行流程
启动脚本
python dify_agent.py
执行过程
- 启动 Dify MCP Server
- 读取并处理前端代码文件
- 通过 Agent 调用 Dify 工作流进行代码优化
- 输出优化结果
中间结果
Dify MCP Server running on stdio
Running:
使用 dify workflows mcp 帮我进行前端代码的优化,代码如下:
[原始代码内容...]
最终优化结果
以下是优化后的前端代码及其详细说明:
优化后的代码
import React, {
useState, useEffect, useMemo, useCallback } from 'react';
// 定义日期类型,允许 Date 对象、数字、字符串或 undefined
type TDate = Date | number | string | undefined;
// 定义格式化后的剩余时间类型
interface IFormattedTimeLeft {
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
}
// 定义倒计时 Hook 的配置选项
interface IOptions {
targetDate?: TDate;
interval?: number;
}
// 定义倒计时 Hook 的返回值类型
interface IReturn {
timeLeft: number;
setTargetDate: React.Dispatch<React.SetStateAction<TDate>>;
formattedTimeLeft: IFormattedTimeLeft;
run: () => void;
currentStatus: ECurrentStatus;
}
// 定义倒计时的状态枚举
export enum ECurrentStatus {
NOT_STARTED,
STARTED,
FINISHED
}
// 计算剩余时间(毫秒)
const calculateTimeLeft = (targetDate: TDate | undefined): number => {
if (!targetDate) return 0;
try {
const timeLeft = new Date(targetDate).getTime() - new Date().getTime();
return timeLeft > 0 ? timeLeft : 0;
} catch (error) {
console.error("Invalid date format:", targetDate, error);
return 0;
}
};
// 格式化剩余时间
const formatTimeLeft = (milliseconds: number): IFormattedTimeLeft => {
const days = Math.floor(milliseconds / 86400000);
const hours = Math.floor((milliseconds % 86400000) / 3600000);
const minutes = Math.floor((milliseconds % 3600000) / 60000);
const seconds = Math.floor((milliseconds % 60000) / 1000);
const millisecondsValue = Math.floor(milliseconds % 1000);
return {
days, hours, minutes, seconds, milliseconds: millisecondsValue };
};
// 自定义倒计时 Hook
const useCountDown = (options: IOptions = {
}): IReturn => {
const {
targetDate, interval = 1000 } = options;
const [isRunning, setIsRunning] = useState(false);
const [currentStatus, setCurrentStatus] = useState(ECurrentStatus.NOT_STARTED);
const [target, setTargetDate] = useState<TDate>(targetDate);
const [timeLeft, setTimeLeft] = useState<number>(() => calculateTimeLeft(target));
useEffect(() => {
if (!isRunning) return;
if (!target) {
setTimeLeft(0);
return;
}
const remainingTime = calculateTimeLeft(target);
setTimeLeft(remainingTime);
if (remainingTime === 0) {
setIsRunning(false);
setCurrentStatus(ECurrentStatus.FINISHED);
return;
}
const timerId = setInterval(() => {
const remainingTime = calculateTimeLeft(target);
setTimeLeft(remainingTime);
if (remainingTime === 0) {
clearInterval(timerId);
setIsRunning(false);
setCurrentStatus(ECurrentStatus.FINISHED);
}
}, interval);
return () => clearInterval(timerId);
}, [target, interval, isRunning]);
const formattedTimeLeft = useMemo<IFormattedTimeLeft>(() => {
return formatTimeLeft(timeLeft);
}, [timeLeft]);
const run = useCallback(() => {
if (!isRunning) {
setIsRunning(true);
setCurrentStatus(ECurrentStatus.STARTED);
}
}, [isRunning]);
return {
timeLeft,
setTargetDate,
formattedTimeLeft,
currentStatus,
run
};
};
export default useCountDown;
优化说明
-
代码整洁度提升:
- 使用清晰的类型定义和接口
- 添加详细的注释,解释每个函数和变量的作用
-
模块化设计:
- 将时间计算和格式化逻辑拆分为独立的函数
- 使用
useCallback
缓存run
函数,避免不必要的重复渲染
-
逻辑简化:
- 使用提前返回的策略简化条件判断
- 添加错误处理,防止无效日期字符串导致程序崩溃
-
性能优化:
- 使用
useMemo
缓存格式化后的剩余时间 - 在
useEffect
中清理定时器,防止内存泄漏
- 使用
验证方法
- 代码审查:逐行对比原始代码和优化后的代码
- 单元测试:覆盖各种场景(如目标日期为空、已过期等)
- 手动测试:在实际应用中验证倒计时行为
- 边界条件测试:测试极端情况(如
interval
为 0 或负数)
通过以上优化,代码的可读性、可维护性和性能均得到显著提升,同时保持了原始功能的一致性。