使用 openai-agent-python 和 dify-workflows-mcp 进行前端代码优化

使用 openai-agent-pythondify-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

执行过程

  1. 启动 Dify MCP Server
  2. 读取并处理前端代码文件
  3. 通过 Agent 调用 Dify 工作流进行代码优化
  4. 输出优化结果

中间结果

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;

优化说明

  1. 代码整洁度提升

    • 使用清晰的类型定义和接口
    • 添加详细的注释,解释每个函数和变量的作用
  2. 模块化设计

    • 将时间计算和格式化逻辑拆分为独立的函数
    • 使用 useCallback 缓存 run 函数,避免不必要的重复渲染
  3. 逻辑简化

    • 使用提前返回的策略简化条件判断
    • 添加错误处理,防止无效日期字符串导致程序崩溃
  4. 性能优化

    • 使用 useMemo 缓存格式化后的剩余时间
    • useEffect 中清理定时器,防止内存泄漏

验证方法

  • 代码审查:逐行对比原始代码和优化后的代码
  • 单元测试:覆盖各种场景(如目标日期为空、已过期等)
  • 手动测试:在实际应用中验证倒计时行为
  • 边界条件测试:测试极端情况(如 interval 为 0 或负数)

通过以上优化,代码的可读性、可维护性和性能均得到显著提升,同时保持了原始功能的一致性。