{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# CodeReviewAgent - 智能代码审查助手\n", "\n", "本项目演示如何使用HelloAgents框架构建一个智能代码审查助手。\n", "\n", "## 📖 使用说明\n", "\n", "- **快速体验**: 运行「第0部分」的快速演示\n", "- **完整功能**: 依次运行第1-7部分,体验完整的代码审查流程" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## 第0部分:快速演示 ⚡\n", "\n", "如果你想快速了解项目功能,可以运行这个简化版本。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 库导入和配置完成\n" ] } ], "source": [ "# 快速演示 - 导入库和配置\n", "from hello_agents import SimpleAgent, HelloAgentsLLM\n", "from hello_agents.tools import Tool, ToolParameter\n", "from typing import Dict, Any, List\n", "import ast\n", "import os\n", "\n", "# 配置LLM参数\n", "os.environ[\"LLM_MODEL_ID\"] = \"Qwen/Qwen2.5-72B-Instruct\"\n", "os.environ[\"LLM_API_KEY\"] = \"your_api_key_here\"\n", "os.environ[\"LLM_BASE_URL\"] = \"https://api-inference.modelscope.cn/v1/\"\n", "os.environ[\"LLM_TIMEOUT\"] = \"60\"\n", "\n", "print(\"✅ 库导入和配置完成\")" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 工具定义完成\n" ] } ], "source": [ "# 快速演示 - 定义简单的代码分析工具\n", "class QuickAnalysisTool(Tool):\n", " def __init__(self):\n", " super().__init__(\n", " name=\"quick_analysis\",\n", " description=\"快速分析Python代码结构\"\n", " )\n", " \n", " def run(self, parameters: Dict[str, Any]) -> str:\n", " code = parameters.get(\"code\", \"\")\n", " if not code:\n", " return \"错误:代码不能为空\"\n", " \n", " try:\n", " tree = ast.parse(code)\n", " functions = [n.name for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]\n", " classes = [n.name for n in ast.walk(tree) if isinstance(n, ast.ClassDef)]\n", " return f\"发现{len(classes)}个类、{len(functions)}个函数: {', '.join(functions)}\"\n", " except Exception as e:\n", " return f\"代码解析失败: {str(e)}\"\n", " \n", " def get_parameters(self) -> List[ToolParameter]:\n", " return [\n", " ToolParameter(\n", " name=\"code\",\n", " type=\"string\",\n", " description=\"要分析的Python代码\",\n", " required=True\n", " )\n", " ]\n", "\n", "print(\"✅ 工具定义完成\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 工具 'quick_analysis' 已注册。\n", "✅ 智能体创建完成\n", "✅ 可用工具: ['quick_analysis']\n" ] } ], "source": [ "# 快速演示 - 创建工具注册表和智能体\n", "from hello_agents import ToolRegistry\n", "\n", "# 创建工具注册表\n", "quick_registry = ToolRegistry()\n", "quick_registry.register_tool(QuickAnalysisTool())\n", "\n", "# 创建智能体\n", "quick_agent = SimpleAgent(\n", " name=\"快速审查助手\",\n", " llm=HelloAgentsLLM(),\n", " system_prompt=\"你是代码审查助手,使用工具分析代码并给出简要建议。\",\n", " tool_registry=quick_registry\n", ")\n", "\n", "print(\"✅ 智能体创建完成\")\n", "print(f\"✅ 可用工具: {list(quick_registry._tools.keys())}\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== 快速演示:分析测试代码 ===\n", "看来我们遇到了一些技术问题,导致代码无法通过工具进行分析。不过,我可以直接为你提供一些建议和观察结果。\n", "\n", "### 代码分析\n", "\n", "#### 1. **函数定义**\n", "- `hello()` 和 `world()` 函数都很简单,分别打印 \"Hello\" 和 \"World\"。这部分代码是正确的,没有问题。\n", "\n", "#### 2. **类定义**\n", "- `Greeter` 类包含一个 `greet` 方法,该方法调用了 `hello()` 和 `world()` 函数。这也是正确的。\n", "\n", "### 建议\n", "\n", "1. **代码风格**\n", " - 代码风格符合 PEP 8 规范,这是 Python 的官方编码风格指南。建议保持这种风格。\n", " - 你可以考虑添加一些文档字符串(docstrings)来描述每个函数和类的作用。例如:\n", " ```python\n", " def hello():\n", " \"\"\"Prints 'Hello'\"\"\"\n", " print(\"Hello\")\n", "\n", " def world():\n", " \"\"\"Prints 'World'\"\"\"\n", " print(\"World\")\n", "\n", " class Greeter:\n", " \"\"\"A class to greet the world\"\"\"\n", "\n", " def greet(self):\n", " \"\"\"Prints 'Hello World'\"\"\"\n", " hello()\n", " world()\n", " ```\n", "\n", "2. **测试**\n", " - 为了确保代码按预期工作,可以编写一些简单的测试用例。例如:\n", " ```python\n", " if __name__ == \"__main__\":\n", " greeter = Greeter()\n", " greeter.greet()\n", " ```\n", " - 这样可以在运行脚本时调用 `greet` 方法,验证输出是否正确。\n", "\n", "3. **扩展性**\n", " - 如果未来需要扩展 `Greeter` 类的功能,可以考虑添加更多的方法或属性。例如,可以添加一个 `set_greeting` 方法来动态设置问候语。\n", "\n", "### 总结\n", "你的代码已经很简洁明了,但可以通过添加文档字符串和测试用例来提高可读性和可靠性。希望这些建议对你有帮助!如果还有其他问题或需要进一步的分析,请告诉我。\n", "\n", "✅ 快速演示完成!\n", "\n", "💡 提示:继续运行下面的单元格,体验完整功能\n" ] } ], "source": [ "# 快速演示 - 测试代码\n", "test_code = \"\"\"\n", "def hello():\n", " print(\"Hello\")\n", "\n", "def world():\n", " print(\"World\")\n", "\n", "class Greeter:\n", " def greet(self):\n", " hello()\n", " world()\n", "\"\"\"\n", "\n", "print(\"=== 快速演示:分析测试代码 ===\")\n", "result = quick_agent.run(f\"请分析这段代码:\\n{test_code}\")\n", "print(result)\n", "print(\"\\n✅ 快速演示完成!\")\n", "print(\"\\n💡 提示:继续运行下面的单元格,体验完整功能\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "# 完整版代码审查系统\n", "\n", "下面是完整的代码审查系统,包含更强大的分析功能。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第1部分:环境配置" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 环境配置完成\n", "✅ 使用模型: Qwen/Qwen2.5-72B-Instruct\n", "✅ API地址: https://api-inference.modelscope.cn/v1/\n" ] } ], "source": [ "# 导入必要的库\n", "from hello_agents import SimpleAgent, HelloAgentsLLM\n", "from hello_agents.tools import Tool, ToolParameter\n", "from typing import Dict, Any, List\n", "import ast\n", "import os\n", "\n", "# 配置LLM参数\n", "os.environ[\"LLM_MODEL_ID\"] = \"Qwen/Qwen2.5-72B-Instruct\"\n", "os.environ[\"LLM_API_KEY\"] = \"your_api_key_here\"\n", "os.environ[\"LLM_BASE_URL\"] = \"https://api-inference.modelscope.cn/v1/\"\n", "os.environ[\"LLM_TIMEOUT\"] = \"60\"\n", "\n", "print(\"✅ 环境配置完成\")\n", "print(f\"✅ 使用模型: {os.getenv('LLM_MODEL_ID')}\")\n", "print(f\"✅ API地址: {os.getenv('LLM_BASE_URL')}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第2部分:定义代码分析工具" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ CodeAnalysisTool定义完成\n" ] } ], "source": [ "class CodeAnalysisTool(Tool):\n", " \"\"\"代码静态分析工具\"\"\"\n", "\n", " def __init__(self):\n", " super().__init__(\n", " name=\"code_analysis\",\n", " description=\"分析Python代码的结构、复杂度和潜在问题\"\n", " )\n", "\n", " def run(self, parameters: Dict[str, Any]) -> str:\n", " \"\"\"分析代码并返回结果\"\"\"\n", " code = parameters.get(\"code\", \"\")\n", " if not code:\n", " return \"错误:代码不能为空\"\n", " \n", " try:\n", " tree = ast.parse(code)\n", "\n", " # 统计信息\n", " functions = [node for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)]\n", " classes = [node for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]\n", "\n", " result = {\n", " \"函数数量\": len(functions),\n", " \"类数量\": len(classes),\n", " \"代码行数\": len(code.split('\\n')),\n", " \"函数列表\": [f.name for f in functions],\n", " \"类列表\": [c.name for c in classes]\n", " }\n", "\n", " return str(result)\n", " except SyntaxError as e:\n", " return f\"语法错误:{str(e)}\"\n", " \n", " def get_parameters(self) -> List[ToolParameter]:\n", " return [\n", " ToolParameter(\n", " name=\"code\",\n", " type=\"string\",\n", " description=\"要分析的Python代码\",\n", " required=True\n", " )\n", " ]\n", "\n", "print(\"✅ CodeAnalysisTool定义完成\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ StyleCheckTool定义完成\n" ] } ], "source": [ "class StyleCheckTool(Tool):\n", " \"\"\"代码风格检查工具\"\"\"\n", "\n", " def __init__(self):\n", " super().__init__(\n", " name=\"style_check\",\n", " description=\"检查代码是否符合PEP 8规范\"\n", " )\n", "\n", " def run(self, parameters: Dict[str, Any]) -> str:\n", " \"\"\"检查代码风格\"\"\"\n", " code = parameters.get(\"code\", \"\")\n", " if not code:\n", " return \"错误:代码不能为空\"\n", " \n", " issues = []\n", "\n", " lines = code.split('\\n')\n", " for i, line in enumerate(lines, 1):\n", " # 检查行长度\n", " if len(line) > 79:\n", " issues.append(f\"第{i}行:超过79个字符\")\n", "\n", " # 检查缩进\n", " if line.startswith(' ') and not line.startswith(' '):\n", " if len(line) - len(line.lstrip()) not in [0, 4, 8, 12]:\n", " issues.append(f\"第{i}行:缩进不规范\")\n", "\n", " if not issues:\n", " return \"代码风格良好,符合PEP 8规范\"\n", " return \"发现以下问题:\\n\" + \"\\n\".join(issues)\n", " \n", " def get_parameters(self) -> List[ToolParameter]:\n", " return [\n", " ToolParameter(\n", " name=\"code\",\n", " type=\"string\",\n", " description=\"要检查的Python代码\",\n", " required=True\n", " )\n", " ]\n", "\n", "print(\"✅ StyleCheckTool定义完成\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第3部分:创建智能体" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "✅ 工具 'code_analysis' 已注册。\n", "✅ 工具 'style_check' 已注册。\n", "✅ 智能体创建完成\n", "智能体名称: 代码审查助手\n", "可用工具: ['code_analysis', 'style_check']\n" ] } ], "source": [ "# 导入工具注册表\n", "from hello_agents import ToolRegistry\n", "\n", "# 创建工具注册表\n", "tool_registry = ToolRegistry()\n", "tool_registry.register_tool(CodeAnalysisTool())\n", "tool_registry.register_tool(StyleCheckTool())\n", "\n", "# 初始化LLM\n", "llm = HelloAgentsLLM()\n", "\n", "# 定义系统提示词\n", "system_prompt = \"\"\"你是一位经验丰富的代码审查专家。你的任务是:\n", "\n", "1. 使用code_analysis工具分析代码结构\n", "2. 使用style_check工具检查代码风格\n", "3. 基于分析结果,提供详细的审查报告\n", "\n", "审查报告应包括:\n", "- 代码结构分析\n", "- 风格问题\n", "- 潜在bug\n", "- 性能优化建议\n", "- 最佳实践建议\n", "\n", "请以Markdown格式输出报告。\"\"\"\n", "\n", "# 创建智能体\n", "agent = SimpleAgent(\n", " name=\"代码审查助手\",\n", " llm=llm,\n", " system_prompt=system_prompt,\n", " tool_registry=tool_registry\n", ")\n", "\n", "print(\"✅ 智能体创建完成\")\n", "print(f\"智能体名称: {agent.name}\")\n", "print(f\"可用工具: {list(tool_registry._tools.keys())}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第4部分:读取示例代码" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== 待审查的代码 ===\n", "\"\"\"\n", "示例代码:一个简单的用户管理系统\n", "用于演示代码审查功能\n", "\"\"\"\n", "\n", "class UserManager:\n", " \"\"\"用户管理类\"\"\"\n", " \n", " def __init__(self):\n", " self.users = []\n", " \n", " def add_user(self, name, age, email):\n", " \"\"\"添加用户\"\"\"\n", " user = {\"name\": name, \"age\": age, \"email\": email}\n", " self.users.append(user)\n", " return True\n", " \n", " def get_user(self, name):\n", " \"\"\"获取用户信息\"\"\"\n", " for user in self.users:\n", " if user[\"name\"] == name:\n", " return user\n", " return None\n", " \n", " def delete_user(self, name):\n", " \"\"\"删除用户\"\"\"\n", " for i, user in enumerate(self.users):\n", " if user[\"name\"] == name:\n", " del self.users[i]\n", " return True\n", " return False\n", "\n", "def calculate_average_age(users):\n", " \"\"\"计算平均年龄\"\"\"\n", " total = 0\n", " for user in users:\n", " total += user[\"age\"]\n", " return total / len(users)\n", "\n", "def send_email(email, message):\n", " \"\"\"发送邮件(模拟)\"\"\"\n", " print(f\"发送邮件到 {email}: {message}\")\n", " return True\n", "\n", "\n", "\n", "==================================================\n", "\n" ] } ], "source": [ "# 读取示例代码\n", "with open(\"data/sample_code.py\", \"r\", encoding=\"utf-8\") as f:\n", " sample_code = f.read()\n", "\n", "print(\"=== 待审查的代码 ===\")\n", "print(sample_code)\n", "print(\"\\n\" + \"=\"*50 + \"\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第5部分:执行代码审查" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== 开始代码审查 ===\n", "## 代码审查报告\n", "\n", "### 代码结构分析\n", "\n", "根据`code_analysis`工具的结果,代码中没有语法错误。以下是代码结构的详细分析:\n", "\n", "1. **类定义**:\n", " - `UserManager` 类负责用户管理,包含三个方法:`add_user`, `get_user`, 和 `delete_user`。\n", " - 类的初始化方法 `__init__` 创建了一个空的用户列表 `self.users`。\n", "\n", "2. **方法分析**:\n", " - `add_user(name, age, email)`:将用户信息添加到用户列表中。返回 `True` 表示操作成功。\n", " - `get_user(name)`:根据用户名查找并返回用户信息。如果找不到用户,返回 `None`。\n", " - `delete_user(name)`:根据用户名从用户列表中删除用户。如果删除成功,返回 `True`,否则返回 `False`。\n", "\n", "3. **辅助函数**:\n", " - `calculate_average_age(users)`:计算给定用户列表的平均年龄。\n", " - `send_email(email, message)`:模拟发送邮件的功能,实际只是打印一条消息。\n", "\n", "### 风格问题\n", "\n", "根据`style_check`工具的结果,代码存在以下风格问题:\n", "\n", "1. **行长度**:\n", " - 第1行超过了79个字符。建议将长行拆分成多行或减少注释的长度。\n", "\n", "### 潜在Bug\n", "\n", "1. **删除用户时的索引问题**:\n", " - 在 `delete_user` 方法中,删除用户后,列表的索引会发生变化。虽然当前实现可以正常工作,但为了避免潜在的索引问题,建议使用列表推导或其他更安全的方法来删除元素。\n", "\n", "### 性能优化建议\n", "\n", "1. **查找用户**:\n", " - `get_user` 方法在最坏情况下需要遍历整个用户列表。如果用户数量较多,可以考虑使用字典来存储用户信息,以提高查找效率。\n", "\n", "2. **计算平均年龄**:\n", " - `calculate_average_age` 方法在每次调用时都需要遍历整个用户列表。如果用户列表非常大,可以考虑缓存计算结果或使用其他数据结构来优化性能。\n", "\n", "### 最佳实践建议\n", "\n", "1. **异常处理**:\n", " - 在 `add_user` 和 `delete_user` 方法中,可以添加异常处理机制,以应对可能的输入错误或意外情况。\n", "\n", "2. **日志记录**:\n", " - 使用日志记录库(如 `logging`)替代 `print` 函数,以便更好地管理和调试代码。\n", "\n", "3. **单元测试**:\n", " - 编写单元测试来验证每个方法的正确性,确保代码的稳定性和可靠性。\n", "\n", "4. **文档字符串**:\n", " - 虽然代码已经包含了文档字符串,但可以进一步细化和扩展,特别是对于复杂的逻辑和边缘情况。\n", "\n", "### 代码改进示例\n", "\n", "以下是改进后的代码示例:\n", "\n", "```python\n", "\"\"\"\n", "示例代码:一个简单的用户管理系统\n", "用于演示代码审查功能\n", "\"\"\"\n", "\n", "import logging\n", "\n", "# 配置日志记录\n", "logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')\n", "\n", "class UserManager:\n", " \"\"\"用户管理类\"\"\"\n", " \n", " def __init__(self):\n", " self.users = {}\n", " \n", " def add_user(self, name, age, email):\n", " \"\"\"添加用户\"\"\"\n", " if name in self.users:\n", " logging.warning(f\"用户 {name} 已经存在\")\n", " return False\n", " self.users[name] = {\"name\": name, \"age\": age, \"email\": email}\n", " return True\n", " \n", " def get_user(self, name):\n", " \"\"\"获取用户信息\"\"\"\n", " return self.users.get(name)\n", " \n", " def delete_user(self, name):\n", " \"\"\"删除用户\"\"\"\n", " if name in self.users:\n", " del self.users[name]\n", " return True\n", " return False\n", "\n", "def calculate_average_age(users):\n", " \"\"\"计算平均年龄\"\"\"\n", " if not users:\n", " return 0\n", " total = sum(user[\"age\"] for user in users.values())\n", " return total / len(users)\n", "\n", "def send_email(email, message):\n", " \"\"\"发送邮件(模拟)\"\"\"\n", " logging.info(f\"发送邮件到 {email}: {message}\")\n", " return True\n", "\n", "# 示例用法\n", "if __name__ == \"__main__\":\n", " user_manager = UserManager()\n", " user_manager.add_user(\"Alice\", 30, \"alice@example.com\")\n", " user_manager.add_user(\"Bob\", 25, \"bob@example.com\")\n", " print(user_manager.get_user(\"Alice\"))\n", " user_manager.delete_user(\"Alice\")\n", " print(user_manager.get_user(\"Alice\"))\n", " average_age = calculate_average_age(user_manager.users)\n", " print(f\"平均年龄: {average_age}\")\n", " send_email(\"admin@example.com\", \"用户管理系统的平均年龄已更新\")\n", "```\n", "\n", "### 总结\n", "\n", "通过这次代码审查,我们发现了几个风格问题和潜在的性能优化点。改进后的代码更加健壮、高效,并且易于维护。希望这些建议对您有所帮助。\n" ] } ], "source": [ "# 执行代码审查\n", "print(\"=== 开始代码审查 ===\")\n", "review_result = agent.run(f\"请审查以下Python代码:\\n\\n```python\\n{sample_code}\\n```\")\n", "\n", "print(review_result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第6部分:保存审查报告" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "✅ 审查报告已保存到 outputs/review_report.md\n" ] } ], "source": [ "# 保存审查报告\n", "with open(\"outputs/review_report.md\", \"w\", encoding=\"utf-8\") as f:\n", " f.write(review_result)\n", "\n", "print(\"\\n✅ 审查报告已保存到 outputs/review_report.md\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 第7部分:总结与展望\n", "\n", "### 实现的功能\n", "- ✅ 代码结构分析\n", "- ✅ PEP 8风格检查\n", "- ✅ 智能审查报告生成\n", "\n", "### 遇到的挑战\n", "- 如何准确解析Python代码结构\n", "- 如何设计合理的提示词让LLM生成高质量报告\n", "\n", "### 未来改进方向\n", "- 支持更多编程语言\n", "- 添加安全漏洞检测\n", "- 集成更多静态分析工具\n", "- 支持批量文件审查" ] } ], "metadata": { "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.5" } }, "nbformat": 4, "nbformat_minor": 4 }