├── .env_demo ├── .gitignore ├── 1.MetaGPT安装配置(OpenAI).ipynb ├── 2.LLM Agent智能体综述及多智能体框架介绍.ipynb ├── 3.单智能体-单Action.py ├── 3.单智能体-多Action.py ├── 3.单智能体-技术文档撰写助手.py ├── 3.单智能体-课后作业 New.py ├── 3.单智能体-课后作业.py ├── 3.基于MetaGPT构建单Agent.ipynb ├── 4.HuggfacePaperOSSAgent.py ├── 4.OSSAgent.py ├── 4.githubTrending爬取.py ├── 5.MetaGPT中Team开发团队.py ├── 5.你画我猜.py ├── 5.师生交互多Agent系统.py ├── DeepSeek调用测试.ipynb ├── LICENSE ├── README.md ├── data └── tutorial_docx │ └── 2024-05-16_18-22-02 │ └── .md ├── logs └── 20240517.txt ├── requirement.txt └── test.md /.env_demo: -------------------------------------------------------------------------------- 1 | # GitHub访问令牌,用于访问GitHub API 2 | GITHUB_ACCESS_TOKEN= 3 | 4 | # Discord机器人令牌,用于登录Discord客户端 5 | DISCORD_TOKEN= 6 | 7 | # Discord频道ID,用于发送消息的目标频道 8 | DISCORD_CHANNEL_ID= 9 | 10 | # 发送者邮箱 11 | QQ_EMAIL_USER= 12 | 13 | # 发送者密匙 14 | QQ_EMAIL_PASSWORD= 15 | 16 | # 接受者邮箱 17 | QQ_EMAIL_TO= 18 | 19 | # 代理配置(如果需要的话) 20 | # GLOBAL_PROXY=http://your_proxy_server:port 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | MetaGPT/ 2 | .MetaGPT/ 3 | .config/* 4 | config/* 5 | metagpt/ 6 | .env -------------------------------------------------------------------------------- /1.MetaGPT安装配置(OpenAI).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "#### 1.查看Python版本\n", 8 | "- 查看python版本,如果使用python3命令不行,这里可以使用python --version" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [ 16 | { 17 | "name": "stdout", 18 | "output_type": "stream", 19 | "text": [ 20 | "Python 3.10.13\n" 21 | ] 22 | } 23 | ], 24 | "source": [ 25 | "!python3 --version" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "name": "stdout", 35 | "output_type": "stream", 36 | "text": [ 37 | "Python 3.10.13\n" 38 | ] 39 | } 40 | ], 41 | "source": [ 42 | "!python --version" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "#### 2.安装MetaGPT\n", 50 | "\n", 51 | "- 使用pip获取MetaGPT\n", 52 | "metagpt可以直接用 pip 来获取至本地环境中,这样我们就可以在像使用任何python包一样导入MetaGPT\n", 53 | "通过在终端内运行下面的代码来获取稳定版metagpt\n", 54 | "官网镜像按照\n", 55 | "```\n", 56 | "pip install metagpt==0.6.6\n", 57 | "```\n", 58 | "国内环境可以通过清华源加速\n", 59 | "```\n", 60 | "pip install -i https://pypi.tuna.tsinghua.edu.cn/simple metagpt==0.6.6\n", 61 | "```\n", 62 | "拉取官方仓库进行按照\n", 63 | "```\n", 64 | "git clone https://github.com/geekan/MetaGPT.git\n", 65 | "cd /your/path/to/MetaGPT\n", 66 | "pip install -e .\n", 67 | "```\n", 68 | "\n", 69 | "更多内容可以了解官方文档:\n", 70 | "https://docs.deepwisdom.ai/\n" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 4, 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "name": "stdout", 80 | "output_type": "stream", 81 | "text": [ 82 | "Found existing installation: metagpt 0.8.1\n", 83 | "Uninstalling metagpt-0.8.1:\n", 84 | " Would remove:\n", 85 | " /usr/local/python/3.10.13/bin/metagpt\n", 86 | " /usr/local/python/3.10.13/lib/python3.10/site-packages/__editable__.metagpt-0.8.1.pth\n", 87 | " /usr/local/python/3.10.13/lib/python3.10/site-packages/__editable___metagpt_0_8_1_finder.py\n", 88 | " /usr/local/python/3.10.13/lib/python3.10/site-packages/metagpt-0.8.1.dist-info/*\n", 89 | "Proceed (Y/n)? ^C\n", 90 | "\u001b[31mERROR: Operation cancelled by user\u001b[0m\u001b[31m\n", 91 | "\u001b[0m" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "# 安装metaGPT\n", 97 | "# !pip install metagpt==0.6.6" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 1, 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "name": "stdout", 107 | "output_type": "stream", 108 | "text": [ 109 | "Cloning into 'MetaGPT'...\n", 110 | "remote: Enumerating objects: 32141, done.\u001b[K\n", 111 | "remote: Total 32141 (delta 0), reused 0 (delta 0), pack-reused 32141\u001b[K\n", 112 | "Receiving objects: 100% (32141/32141), 92.46 MiB | 13.88 MiB/s, done.\n", 113 | "Resolving deltas: 100% (24080/24080), done.\n", 114 | "Obtaining file:///workspaces/MetaGPT-Learn\n", 115 | "\u001b[31mERROR: file:///workspaces/MetaGPT-Learn does not appear to be a Python project: neither 'setup.py' nor 'pyproject.toml' found.\u001b[0m\u001b[31m\n", 116 | "\u001b[0m" 117 | ] 118 | } 119 | ], 120 | "source": [ 121 | "# 我这里由于使用的中转的API KEY,因此选择了第三种方法\n", 122 | "!git clone https://github.com/geekan/MetaGPT.git\n", 123 | "!cd MetaGPT\n", 124 | "!pip install -e .\n", 125 | "\n", 126 | "# 我们在config/config2.yaml中配置自己的api key和 base_url 以及选择的model" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "#### 配置MetaGPT\n", 134 | "- 调用ChatGPT API服务(科学环境) https://platform.openai.com/docs/introduction/overview\n", 135 | "如果没有科学环境或者嫌麻烦,可以直接去tb买一个key,5美元的apiKey价格5-10元左右" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": 1, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "!export OPENAI_API_KEY=\"sxxxxxxxxxxxxxxxxxxxxxxxxxxp\" # 填入你自己的OpenAI API key\n", 145 | "!export OPENAI_API_MODEL=\"gpt-3.5-turbo\" # 选择你要使用的模型,例如:gpt-4, gpt-3.5-turbo\n", 146 | "# !export OPENAI_API_BASE=\"https://api.openai-forward.com/v1\" # 如上配置后依然网络访问不通时,可以尝试再添加此行命令来配置中转代理服务" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "- 如果你觉得直接通过命令行配置API不方便,也可以直接在代码中配置环境变量" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 1, 159 | "metadata": {}, 160 | "outputs": [], 161 | "source": [ 162 | "import os\n", 163 | "os.environ[\"OPENAI_API_KEY\"] = \"sk-Oxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa\" # 填入你自己的OpenAI API key\n", 164 | "os.environ[\"OPENAI_API_MODEL\"] = \"gpt-3.5-turbo\" # 选择你要使用的模型,例如:gpt-4, gpt-3.5-turbo\n", 165 | "# os.environ[\"OPENAI_API_BASE\"] = \"https://api.openai-forward.com/v1\" # 调整API请求地址,设置访问中转代理服务器\n", 166 | "os.environ[\"OPENAI_API_BASE\"] = \"https://xxxxxxxxx/v1\" # 调整API请求地址,设置访问中转代理服务器" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 2, 172 | "metadata": {}, 173 | "outputs": [ 174 | { 175 | "name": "stdout", 176 | "output_type": "stream", 177 | "text": [ 178 | "当WebGIS开发与人工智能(LLM Agent)结合时,可以创造出许多有趣和有用的应用场景。以下是一些国内外的例子:\n", 179 | "\n", 180 | "1. 地图数据智能化处理:结合AI技术,可以对大量的地图数据进行智能化处理,如自动识别地理信息、优化路径规划、实时更新地图信息等。这样可以提高地图数据的质量和实用性。\n", 181 | "\n", 182 | "2. 智能推荐系统:通过AI算法分析用户的地理位置、搜索历史和偏好,为用户提供个性化的地图推荐服务。比如,根据用户的兴趣推荐周边的景点、餐厅或商店。\n", 183 | "\n", 184 | "3. GIS数据分析与预测:利用AI技术处理大规模的地理信息数据,可以进行更精确的地理数据分析和预测。比如,预测城市交通拥堵情况、自然灾害风险等。\n", 185 | "\n", 186 | "4. 灾害应急响应:结合WebGIS和AI技术,可以实现对灾害情况的智能监测、分析和应急响应。比如,利用卫星图像和机器学习算法实现灾害风险评估,提前预警。\n", 187 | "\n", 188 | "5. 智能城市规划:AI技术可以辅助城市规划师进行智能化的城市规划。通过分析大数据和模拟算法,可以为城市规划提供更科学的决策支持。\n", 189 | "\n", 190 | "总的来说,将WebGIS开发与AI结合可以提升地理信息系统的智能化和数据处理能力,为用户提供更个性化、精准的地理信息服务。在未来,随着AI技术的不断发展,这些应用场景将会变得越来越普遍和成熟。\n" 191 | ] 192 | } 193 | ], 194 | "source": [ 195 | "# 测试OpenAI的模型调用是否成功\n", 196 | "from openai import OpenAI\n", 197 | "client = OpenAI(base_url=\"https://xxxxxxx/v1\",\n", 198 | " api_key='sk-Oxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4a')\n", 199 | "\n", 200 | "completion = client.chat.completions.create(\n", 201 | " model=\"gpt-3.5-turbo\",\n", 202 | " messages=[\n", 203 | " {\"role\": \"system\", \"content\": \"你是一个WebGIS开发者,测绘地理和全栈开发精通.\"},\n", 204 | " {\"role\": \"user\", \"content\": \"聊聊国内外WebGIS开发与AI结合的场景现在我们可以聊聊国内外WebGIS开发与AI LLM Agent结合的场景吧\"}\n", 205 | " ]\n", 206 | ")\n", 207 | "\n", 208 | "print(completion.choices[0].message.content)" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "- 通过下面这个案例,我们用以验证环境配置是否成功,并初次体验多智能体框架中的指令 - 动作 - 角色 - 环境 - 团队的抽象概念。在这个示例中,我们创建了一个团队,其中包括产品经理、架构师、项目经理和工程师。然后,我们投资并运行一个项目,最后让团队运行五轮。" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 2, 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "name": "stderr", 225 | "output_type": "stream", 226 | "text": [ 227 | "2024-05-12 17:36:37.952 | INFO | metagpt.team:invest:93 - Investment: $3.0.\n", 228 | "2024-05-12 17:36:37.954 | INFO | metagpt.roles.role:_act:396 - Alice(Product Manager): to do PrepareDocuments(PrepareDocuments)\n", 229 | "2024-05-12 17:36:37.988 | INFO | metagpt.utils.file_repository:save:57 - save to: /workspaces/MetaGPT-Learn/MetaGPT/workspace/20240512173637/docs/requirement.txt\n", 230 | "2024-05-12 17:36:37.992 | INFO | metagpt.roles.role:_act:396 - Alice(Product Manager): to do WritePRD(WritePRD)\n", 231 | "2024-05-12 17:36:37.994 | INFO | metagpt.actions.write_prd:run:86 - New requirement detected: write a cli blackjack game\n" 232 | ] 233 | }, 234 | { 235 | "name": "stdout", 236 | "output_type": "stream", 237 | "text": [ 238 | "[CONTENT]\n", 239 | "{\n", 240 | " \"Language\": \"en_us\",\n", 241 | " \"Programming Language\": \"Python\",\n", 242 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 243 | " \"Project Name\": \"cli_blackjack_game\",\n", 244 | " \"Product Goals\": [\n", 245 | " \"Create an engaging and interactive gameplay experience\",\n", 246 | " \"Ensure smooth and intuitive user interface for seamless gameplay\",\n", 247 | " \"Implement various difficulty levels to cater to different player skills\"\n", 248 | " ],\n", 249 | " \"User Stories\": [\n", 250 | " \"As a player, I want to be able to start a new game easily\",\n", 251 | " \"As a player, I want to see my current score and progress during the game\",\n", 252 | " \"As a player, I want to have options to hit, stand, or double down during my turn\",\n", 253 | " \"As a player, I want to receive clear instructions on how to play the game\",\n", 254 | " \"As a player, I want to feel the excitement and challenge of a real blackjack game\"\n", 255 | " ],\n", 256 | " \"Competitive Analysis\": [\n", 257 | " \"Blackjack Game A: Basic interface, lacks interactive features\",\n", 258 | " \"Blackjack Pro: Offers advanced gameplay options and strategy guides\",\n", 259 | " \"Blackjack Master: Provides a realistic casino experience with multiplayer mode\"\n", 260 | " ],\n", 261 | " \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Engagement and User Experience\\\"\\n x-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n y-axis \\\"Low User Experience\\\" --> \\\"High User Experience\\\"\\n quadrant-1 \\\"Enhance Features\\\"\\n quadrant-2 \\\"Improve User Experience\\\"\\n quadrant-3 \\\"Optimize Engagement\\\"\\n quadrant-4 \\\"Maximize User Satisfaction\\\"\\n \\\"Blackjack Game A\\\": [0.3, 0.4]\\n \\\"Blackjack Pro\\\": [0.6, 0.7]\\n \\\"Blackjack Master\\\": [0.8, 0.9]\\n \\\"Our CLI Blackjack Game\\\": [0.5, 0.6]\",\n", 262 | " \"Requirement Analysis\": \"\",\n", 263 | " \"Requirement Pool\": [\n", 264 | " [\n", 265 | " \"P0\",\n", 266 | " \"Implement basic game logic for blackjack\"\n", 267 | " ],\n", 268 | " [\n", 269 | " \"P1\",\n", 270 | " \"Create a scoring system to track player progress\"\n", 271 | " ],\n", 272 | " [\n", 273 | " \"P2\",\n", 274 | " \"Develop a user-friendly interface for easy navigation\"\n", 275 | " ],\n", 276 | " [\n", 277 | " \"P2\",\n", 278 | " \"Incorporate different difficulty levels for player choice\"\n", 279 | " ],\n", 280 | " [\n", 281 | " \"P1\",\n", 282 | " \"Include clear instructions on how to play the game\"\n", 283 | " ]\n", 284 | " ],\n", 285 | " \"UI Design draft\": \"The UI will include options for hitting, standing, and doubling down. It will display the player's current score and provide clear instructions for gameplay.\",\n", 286 | " \"Anything" 287 | ] 288 | }, 289 | { 290 | "name": "stderr", 291 | "output_type": "stream", 292 | "text": [ 293 | "2024-05-12 17:36:48.720 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 10.724(s), this was the 1st time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n" 294 | ] 295 | }, 296 | { 297 | "name": "stdout", 298 | "output_type": "stream", 299 | "text": [ 300 | " UNCLEAR\": \"\"\n", 301 | "}\n", 302 | "[/CONTENT][CONTENT]\n", 303 | "{\n", 304 | " \"Language\": \"en_us\",\n", 305 | " \"Programming Language\": \"Python\",\n", 306 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 307 | " \"Project Name\": \"cli_blackjack_game\",\n", 308 | " \"Product Goals\": [\n", 309 | " \"Create an engaging CLI experience for users\",\n", 310 | " \"Ensure smooth gameplay and fair card dealing logic\",\n", 311 | " \"Provide an enjoyable and interactive blackjack game\"\n", 312 | " ],\n", 313 | " \"User Stories\": [\n", 314 | " \"As a player, I want to be able to place bets and receive cards\",\n", 315 | " \"As a player, I want to have options like hit, stand, double down\",\n", 316 | " \"As a player, I want to see my current balance and game outcome\"\n", 317 | " ],\n", 318 | " \"Competitive Analysis\": [\n", 319 | " \"Blackjack Game A: Basic CLI interface, lacks interactive features\",\n", 320 | " \"cli-blackjack.io: Offers various betting options and clear game instructions\",\n", 321 | " \"blackjack-cli.com: Provides realistic card dealing but lacks betting flexibility\"\n", 322 | " ],\n", 323 | " \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Engagement and User Experience\\\"\\n x-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n y-axis \\\"Low User Experience\\\" --> \\\"High User Experience\\\"\\n quadrant-1 \\\"Enhance Features\\\"\\n quadrant-2 \\\"Improve User Experience\\\"\\n quadrant-3 \\\"Optimize Engagement\\\"\\n quadrant-4 \\\"Maintain Quality\\\"\\n \\\"Blackjack Game A\\\": [0.3, 0.6]\\n \\\"cli-blackjack.io\\\": [0.45, 0.23]\\n \\\"blackjack-cli.com\\\": [0.57, 0.69]\\n \\\"Our CLI Blackjack Game\\\": [0.5, 0.6]\",\n", 324 | " \"Requirement Analysis\": \"\",\n", 325 | " \"Requirement Pool\": [\n", 326 | " [\n", 327 | " \"P0\",\n", 328 | " \"Implement card dealing and betting system\"\n", 329 | " ],\n", 330 | " [\n", 331 | " \"P1\",\n", 332 | " \"Include game logic for hit, stand, and double down actions\"\n", 333 | " ],\n", 334 | " [\n", 335 | " \"P2\",\n", 336 | " \"Display player balance and game outcomes\"\n", 337 | " ]\n", 338 | " ],\n", 339 | " \"UI Design draft\": \"Simple text-based interface with clear instructions and game status" 340 | ] 341 | }, 342 | { 343 | "name": "stderr", 344 | "output_type": "stream", 345 | "text": [ 346 | "2024-05-12 17:36:57.136 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 19.140(s), this was the 2nd time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n" 347 | ] 348 | }, 349 | { 350 | "name": "stdout", 351 | "output_type": "stream", 352 | "text": [ 353 | " updates.\",\n", 354 | " \"Anything UNCLEAR\": \"\"\n", 355 | "}\n", 356 | "[/CONTENT][CONTENT]\n", 357 | "{\n", 358 | " \"Language\": \"en_us\",\n", 359 | " \"Programming Language\": \"Python\",\n", 360 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 361 | " \"Project Name\": \"cli_blackjack_game\",\n", 362 | " \"Product Goals\": [\n", 363 | " \"Create an engaging and interactive gameplay experience\",\n", 364 | " \"Ensure smooth and intuitive user interface for seamless gameplay\",\n", 365 | " \"Implement various difficulty levels to cater to different player skills\"\n", 366 | " ],\n", 367 | " \"User Stories\": [\n", 368 | " \"As a player, I want to be able to place bets and play against the dealer\",\n", 369 | " \"As a player, I want to see my current score and balance during the game\",\n", 370 | " \"As a player, I want to have the option to hit, stand, or double down during my turn\",\n", 371 | " \"As a player, I want to be able to start a new game or quit at any point\",\n", 372 | " \"As a player, I want to experience the thrill of blackjack through a command-line interface\"\n", 373 | " ],\n", 374 | " \"Competitive Analysis\": [\n", 375 | " \"CLI Blackjack A: Offers basic gameplay with limited features\",\n", 376 | " \"BlackjackConsole.com: Provides a comprehensive CLI blackjack experience with detailed game statistics\",\n", 377 | " \"Terminal21: Focuses on simplicity and quick gameplay sessions\"\n", 378 | " ],\n", 379 | " \"Competitive Quadrant Chart\": \"\",\n", 380 | " \"Requirement Analysis\": \"\",\n", 381 | " \"Requirement Pool\": [\n", 382 | " [\n", 383 | " \"P0\",\n", 384 | " \"Implement core blackjack game logic including card dealing, scoring, and win/loss conditions\"\n", 385 | " ],\n", 386 | " [\n", 387 | " \"P1\",\n", 388 | " \"Incorporate betting system with balance management and payout calculations\"\n", 389 | " ],\n", 390 | " [\n", 391 | " \"P2\",\n", 392 | " \"Add interactive player options like hit, stand, and double down for engaging gameplay\"\n", 393 | " ]\n", 394 | " ],\n", 395 | " \"UI Design draft\": \"Utilize text-based interface with clear instructions and game status updates for a user-friendly experience" 396 | ] 397 | }, 398 | { 399 | "name": "stderr", 400 | "output_type": "stream", 401 | "text": [ 402 | "2024-05-12 17:37:08.165 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 30.169(s), this was the 3rd time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n" 403 | ] 404 | }, 405 | { 406 | "name": "stdout", 407 | "output_type": "stream", 408 | "text": [ 409 | ".\",\n", 410 | " \"Anything UNCLEAR\": \"\"\n", 411 | "}\n", 412 | "[/CONTENT][CONTENT]\n", 413 | "{\n", 414 | " \"Language\": \"en_us\",\n", 415 | " \"Programming Language\": \"Python\",\n", 416 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 417 | " \"Project Name\": \"cli_blackjack_game\",\n", 418 | " \"Product Goals\": [\n", 419 | " \"Create an engaging and interactive gameplay experience\",\n", 420 | " \"Ensure smooth and intuitive user interface for seamless gameplay\",\n", 421 | " \"Implement various difficulty levels to cater to different player skills\"\n", 422 | " ],\n", 423 | " \"User Stories\": [\n", 424 | " \"As a player, I want to be able to place bets and play blackjack against the computer\",\n", 425 | " \"As a player, I want to see my current balance and winnings displayed during the game\",\n", 426 | " \"As a player, I want to have the option to quit or restart the game at any point\",\n", 427 | " \"As a player, I want to experience the thrill of playing blackjack through a command-line interface\",\n", 428 | " \"As a player, I want to easily understand the game rules and options available\"\n", 429 | " ],\n", 430 | " \"Competitive Analysis\": [\n", 431 | " \"CLI Blackjack A: Basic gameplay with limited features\",\n", 432 | " \"BlackjackConsole.com: Offers various customization options and detailed game statistics\",\n", 433 | " \"TerminalBlackjack.io: Simple interface with quick gameplay\"\n", 434 | " ],\n", 435 | " \"Competitive Quadrant Chart\": \"\",\n", 436 | " \"Requirement Analysis\": \"\",\n", 437 | " \"Requirement Pool\": [\n", 438 | " [\n", 439 | " \"P0\",\n", 440 | " \"Implement core blackjack game logic and rules\"\n", 441 | " ],\n", 442 | " [\n", 443 | " \"P1\",\n", 444 | " \"Create betting system and balance management\"\n", 445 | " ],\n", 446 | " [\n", 447 | " \"P1\",\n", 448 | " \"Develop game restart and quit functionality\"\n", 449 | " ],\n", 450 | " [\n", 451 | " \"P2\",\n", 452 | " \"Enhance user interface for better user experience\"\n", 453 | " ],\n", 454 | " [\n", 455 | " \"P2\",\n", 456 | " \"Add difficulty levels for player customization\"\n", 457 | " ]\n", 458 | " ],\n", 459 | " \"UI Design draft\": \"The UI should display player balance, current hand, available actions (hit, stand, double down), and game messages in a clear and concise manner. Use ASCII art for card representation.\",\n", 460 | " \"" 461 | ] 462 | }, 463 | { 464 | "name": "stderr", 465 | "output_type": "stream", 466 | "text": [ 467 | "2024-05-12 17:37:17.396 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 39.399(s), this was the 4th time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n" 468 | ] 469 | }, 470 | { 471 | "name": "stdout", 472 | "output_type": "stream", 473 | "text": [ 474 | "Anything UNCLEAR\": \"\"\n", 475 | "}\n", 476 | "[/CONTENT][CONTENT]\n", 477 | "{\n", 478 | " \"Language\": \"en_us\",\n", 479 | " \"Programming Language\": \"Python\",\n", 480 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 481 | " \"Project Name\": \"cli_blackjack_game\",\n", 482 | " \"Product Goals\": [\n", 483 | " \"Create an engaging and interactive gameplay experience\",\n", 484 | " \"Ensure smooth and intuitive user interface for seamless gameplay\",\n", 485 | " \"Implement various difficulty levels to cater to different player skills\"\n", 486 | " ],\n", 487 | " \"User Stories\": [\n", 488 | " \"As a player, I want to be able to place bets and play blackjack against the computer\",\n", 489 | " \"As a player, I want to see my current balance and track my wins and losses\",\n", 490 | " \"As a player, I want to have the option to quit or restart the game at any point\",\n", 491 | " \"As a player, I want to experience a realistic blackjack gameplay with clear instructions\",\n", 492 | " \"As a player, I want to enjoy the game on both desktop and mobile devices\"\n", 493 | " ],\n", 494 | " \"Competitive Analysis\": [\n", 495 | " \"Blackjack Game A: Basic interface, lacks interactive features\",\n", 496 | " \"playblackjack.com: Offers multiplayer mode and detailed statistics\",\n", 497 | " \"blackjackonline.net: Provides a wide range of customization options for players\"\n", 498 | " ],\n", 499 | " \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Engagement and User Experience\\\"\\n x-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n y-axis \\\"Low User Experience\\\" --> \\\"High User Experience\\\"\\n quadrant-1 \\\"Enhance Features\\\"\\n quadrant-2 \\\"Improve User Experience\\\"\\n quadrant-3 \\\"Optimize Engagement\\\"\\n quadrant-4 \\\"Maintain Quality\\\"\\n \\\"Blackjack Game A\\\": [0.2, 0.4]\\n \\\"playblackjack.com\\\": [0.6, 0.7]\\n \\\"blackjackonline.net\\\": [0.5, 0.6]\\n \\\"cli_blackjack_game\\\": [0.7, 0.8]\",\n", 500 | " \"Requirement Analysis\": \"\",\n", 501 | " \"Requirement Pool\": [\n", 502 | " [\n", 503 | " \"P0\",\n", 504 | " \"Implement basic blackjack game logic and rules\"\n", 505 | " ],\n", 506 | " [\n", 507 | " \"P1\",\n", 508 | " \"Incorporate betting system and balance management\"\n", 509 | " ],\n", 510 | " [\n", 511 | " \"P1\",\n", 512 | " \"Develop interactive user interface for smooth gameplay\"\n", 513 | " ],\n", 514 | " [\n", 515 | " \"P2\",\n", 516 | " \"Add option for players to adjust difficulty levels\"\n", 517 | " ],\n", 518 | " [\n", 519 | " \"P2\",\n", 520 | " \"Include clear instructions and game guidance\"\n", 521 | " ]\n", 522 | " ],\n", 523 | " \"UI Design draft\": \"The UI should include a visual representation of cards, buttons for player actions like hit, stand, bet, and clear. Display player balance, current hand value, and game outcome clearly.\",\n", 524 | " \"" 525 | ] 526 | }, 527 | { 528 | "name": "stderr", 529 | "output_type": "stream", 530 | "text": [ 531 | "2024-05-12 17:37:31.587 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 53.591(s), this was the 5th time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n" 532 | ] 533 | }, 534 | { 535 | "name": "stdout", 536 | "output_type": "stream", 537 | "text": [ 538 | "Anything UNCLEAR\": \"\"\n", 539 | "}\n", 540 | "[/CONTENT][CONTENT]\n", 541 | "{\n", 542 | " \"Language\": \"en_us\",\n", 543 | " \"Programming Language\": \"Python\",\n", 544 | " \"Original Requirements\": \"write a cli blackjack game\",\n", 545 | " \"Project Name\": \"cli_blackjack_game\",\n", 546 | " \"Product Goals\": [\n", 547 | " \"Create an engaging and interactive gameplay experience\",\n", 548 | " \"Ensure smooth and intuitive user interface for seamless gameplay\",\n", 549 | " \"Implement various difficulty levels to cater to different player skills\"\n", 550 | " ],\n", 551 | " \"User Stories\": [\n", 552 | " \"As a player, I want to be able to place bets and play blackjack against the computer\",\n", 553 | " \"As a player, I want to see my current balance and winnings displayed during the game\",\n", 554 | " \"As a player, I want to have the option to quit or restart the game at any point\",\n", 555 | " \"As a player, I want to experience a realistic blackjack gameplay with clear instructions\",\n", 556 | " \"As a player, I want to enjoy the game on both desktop and mobile devices\"\n", 557 | " ],\n", 558 | " \"Competitive Analysis\": [\n", 559 | " \"Blackjack Game A: Basic interface, lacks interactive features\",\n", 560 | " \"playblackjack.com: Offers a variety of blackjack games with detailed statistics\",\n", 561 | " \"blackjackonline.net: Provides a realistic blackjack experience with multiplayer options\"\n", 562 | " ],\n", 563 | " \"Competitive Quadrant Chart\": \"quadrantChart\\n title \\\"Engagement and User Experience of Blackjack Games\\\"\\n x-axis \\\"Low Engagement\\\" --> \\\"High Engagement\\\"\\n y-axis \\\"Low User Experience\\\" --> \\\"High User Experience\\\"\\n quadrant-1 \\\"Enhance Features\\\"\\n quadrant-2 \\\"Improve User Experience\\\"\\n quadrant-3 \\\"Optimize Engagement\\\"\\n quadrant-4 \\\"Maintain Quality\\\"\\n \\\"Blackjack Game A\\\": [0.3, 0.4]\\n \\\"playblackjack.com\\\": [0.6, 0.7]\\n \\\"blackjackonline.net\\\": [0.8, 0.6]\\n \\\"cli_blackjack_game\\\": [0.7, 0.8]\",\n", 564 | " \"Requirement Analysis\": \"\",\n", 565 | " \"Requirement Pool\": [\n", 566 | " [\n", 567 | " \"P0\",\n", 568 | " \"Implement the core blackjack game logic and rules\"\n", 569 | " ],\n", 570 | " [\n", 571 | " \"P1\",\n", 572 | " \"Integrate a betting system and balance management\"\n", 573 | " ],\n", 574 | " [\n", 575 | " \"P1\",\n", 576 | " \"Develop a user-friendly CLI interface for smooth gameplay\"\n", 577 | " ],\n", 578 | " [\n", 579 | " \"P2\",\n", 580 | " \"Include options for game restart and quitting\"\n", 581 | " ],\n", 582 | " [\n", 583 | " \"P2\",\n", 584 | " \"Ensure cross-platform compatibility for desktop and mobile devices\"\n", 585 | " ]\n", 586 | " ],\n", 587 | " \"UI Design draft\": \"The CLI interface should display clear game instructions, current balance, and game status. Use intuitive commands for player interaction.\",\n", 588 | " \"" 589 | ] 590 | }, 591 | { 592 | "name": "stderr", 593 | "output_type": "stream", 594 | "text": [ 595 | "2024-05-12 17:37:55.354 | ERROR | metagpt.utils.common:log_it:554 - Finished call to 'metagpt.actions.action_node.ActionNode._aask_v1' after 77.358(s), this was the 6th time calling it. exp: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n", 596 | "2024-05-12 17:37:55.356 | WARNING | metagpt.utils.common:wrapper:649 - There is a exception in role's execution, in order to resume, we delete the newest role communication message in the role's memory.\n", 597 | "2024-05-12 17:37:55.358 | ERROR | metagpt.utils.common:wrapper:631 - Exception occurs, start to serialize the project, exp:\n", 598 | "Traceback (most recent call last):\n", 599 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 50, in __call__\n", 600 | " result = await fn(*args, **kwargs)\n", 601 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/action_node.py\", line 420, in _aask_v1\n", 602 | " content = await self.llm.aask(prompt, system_msgs, images=images, timeout=timeout)\n", 603 | "TypeError: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n", 604 | "\n", 605 | "The above exception was the direct cause of the following exception:\n", 606 | "\n", 607 | "Traceback (most recent call last):\n", 608 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/utils/common.py\", line 640, in wrapper\n", 609 | " return await func(self, *args, **kwargs)\n", 610 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/roles/role.py\", line 555, in run\n", 611 | " rsp = await self.react()\n", 612 | "tenacity.RetryError: RetryError[]\n", 613 | "\n", 614 | "During handling of the above exception, another exception occurred:\n", 615 | "\n", 616 | "Traceback (most recent call last):\n", 617 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/utils/common.py\", line 626, in wrapper\n", 618 | " result = await func(self, *args, **kwargs)\n", 619 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/team.py\", line 131, in run\n", 620 | " await self.env.run()\n", 621 | "Exception: Traceback (most recent call last):\n", 622 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 50, in __call__\n", 623 | " result = await fn(*args, **kwargs)\n", 624 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/action_node.py\", line 420, in _aask_v1\n", 625 | " content = await self.llm.aask(prompt, system_msgs, images=images, timeout=timeout)\n", 626 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/provider/base_llm.py\", line 150, in aask\n", 627 | " rsp = await self.acompletion_text(message, stream=stream, timeout=self.get_timeout(timeout))\n", 628 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 88, in async_wrapped\n", 629 | " return await fn(*args, **kwargs)\n", 630 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 47, in __call__\n", 631 | " do = self.iter(retry_state=retry_state)\n", 632 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/__init__.py\", line 314, in iter\n", 633 | " return fut.result()\n", 634 | " File \"/home/codespace/.python/current/lib/python3.10/concurrent/futures/_base.py\", line 451, in result\n", 635 | " return self.__get_result()\n", 636 | " File \"/home/codespace/.python/current/lib/python3.10/concurrent/futures/_base.py\", line 403, in __get_result\n", 637 | " raise self._exception\n", 638 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 50, in __call__\n", 639 | " result = await fn(*args, **kwargs)\n", 640 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/provider/openai_api.py\", line 155, in acompletion_text\n", 641 | " return await self._achat_completion_stream(messages, timeout=timeout)\n", 642 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/provider/openai_api.py\", line 105, in _achat_completion_stream\n", 643 | " usage = CompletionUsage(**chunk.usage)\n", 644 | "TypeError: openai.types.completion_usage.CompletionUsage() argument after ** must be a mapping, not NoneType\n", 645 | "\n", 646 | "The above exception was the direct cause of the following exception:\n", 647 | "\n", 648 | "Traceback (most recent call last):\n", 649 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/utils/common.py\", line 640, in wrapper\n", 650 | " return await func(self, *args, **kwargs)\n", 651 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/roles/role.py\", line 555, in run\n", 652 | " rsp = await self.react()\n", 653 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/roles/role.py\", line 522, in react\n", 654 | " rsp = await self._react()\n", 655 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/roles/role.py\", line 468, in _react\n", 656 | " rsp = await self._act()\n", 657 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/roles/role.py\", line 397, in _act\n", 658 | " response = await self.rc.todo.run(self.rc.history)\n", 659 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/write_prd.py\", line 87, in run\n", 660 | " return await self._handle_new_requirement(req)\n", 661 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/write_prd.py\", line 108, in _handle_new_requirement\n", 662 | " node = await WRITE_PRD_NODE.fill(context=context, llm=self.llm, exclude=exclude) # schema=schema\n", 663 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/action_node.py\", line 504, in fill\n", 664 | " return await self.simple_fill(schema=schema, mode=mode, images=images, timeout=timeout, exclude=exclude)\n", 665 | " File \"/workspaces/MetaGPT-Learn/MetaGPT/metagpt/actions/action_node.py\", line 456, in simple_fill\n", 666 | " content, scontent = await self._aask_v1(\n", 667 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 88, in async_wrapped\n", 668 | " return await fn(*args, **kwargs)\n", 669 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/_asyncio.py\", line 47, in __call__\n", 670 | " do = self.iter(retry_state=retry_state)\n", 671 | " File \"/home/codespace/.python/current/lib/python3.10/site-packages/tenacity/__init__.py\", line 326, in iter\n", 672 | " raise retry_exc from fut.exception()\n", 673 | "tenacity.RetryError: RetryError[]\n", 674 | "\n", 675 | "\n" 676 | ] 677 | }, 678 | { 679 | "name": "stdout", 680 | "output_type": "stream", 681 | "text": [ 682 | "Anything UNCLEAR\": \"\"\n", 683 | "}\n", 684 | "[/CONTENT]" 685 | ] 686 | } 687 | ], 688 | "source": [ 689 | "import asyncio\n", 690 | "from metagpt.roles import (\n", 691 | " Architect,\n", 692 | " Engineer,\n", 693 | " ProductManager,\n", 694 | " ProjectManager,\n", 695 | ")\n", 696 | "from metagpt.team import Team\n", 697 | "\n", 698 | "async def startup(idea: str):\n", 699 | " company = Team()\n", 700 | " company.hire(\n", 701 | " [\n", 702 | " ProductManager(),\n", 703 | " Architect(),\n", 704 | " ProjectManager(),\n", 705 | " Engineer(),\n", 706 | " ]\n", 707 | " )\n", 708 | " company.invest(investment=3.0)\n", 709 | " company.run_project(idea=idea)\n", 710 | "\n", 711 | " await company.run(n_round=5)\n", 712 | " \n", 713 | "await startup(idea=\"write a cli blackjack game\")" 714 | ] 715 | } 716 | ], 717 | "metadata": { 718 | "kernelspec": { 719 | "display_name": "Python 3", 720 | "language": "python", 721 | "name": "python3" 722 | }, 723 | "language_info": { 724 | "codemirror_mode": { 725 | "name": "ipython", 726 | "version": 3 727 | }, 728 | "file_extension": ".py", 729 | "mimetype": "text/x-python", 730 | "name": "python", 731 | "nbconvert_exporter": "python", 732 | "pygments_lexer": "ipython3", 733 | "version": "3.10.13" 734 | } 735 | }, 736 | "nbformat": 4, 737 | "nbformat_minor": 2 738 | } 739 | -------------------------------------------------------------------------------- /3.单智能体-单Action.py: -------------------------------------------------------------------------------- 1 | import re 2 | import asyncio 3 | from metagpt.actions import Action 4 | from metagpt.roles import Role 5 | from metagpt.schema import Message 6 | from metagpt.logs import logger 7 | 8 | class CodeWrite(Action): 9 | PROMPT_TEMPLATE: str = """ 10 | 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。 11 | 返回的格式为:```python\n你的代码\n```,请不要包含其他的文本。 12 | ```python 13 | # your code here 14 | ``` 15 | """ 16 | 17 | name: str = "CodeWriter" 18 | 19 | async def run(self, requirements: str): 20 | prompt = self.PROMPT_TEMPLATE.format(requirements=requirements) 21 | rsp = await self._aask(prompt) 22 | code_text = CodeWrite.parse_code(rsp) 23 | return code_text 24 | 25 | @staticmethod 26 | def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码 27 | pattern = r'```python(.*?)```' # 使用非贪婪匹配 28 | match = re.search(pattern, rsp, re.DOTALL) 29 | code_text = match.group(1) if match else rsp 30 | return code_text 31 | 32 | class CodeWriter(Role): 33 | """ 34 | CodeWriter 角色类,继承自 Role 基类 35 | """ 36 | 37 | name: str = "Cheems" # 角色昵称 38 | profile: str = "CodeWriter" # 角色人设 39 | 40 | def __init__(self, **kwargs): 41 | """ 42 | 初始化 CodeWriter 角色 43 | """ 44 | super().__init__(**kwargs) # 调用基类构造函数 45 | self.set_actions([CodeWrite]) # 为角色配备 CodeWrite 动作 46 | 47 | async def _act(self) -> Message: 48 | """ 49 | 定义角色行动逻辑 50 | """ 51 | logger.info(f"{self._setting}: ready to {self.rc.todo}") # 记录日志 52 | todo = self.rc.todo # 获取待执行的动作 (CodeWriter) 53 | 54 | msg = self.get_memories(k=1)[0] # 获取最近一条记忆 (用户输入) 55 | 56 | code_text = await todo.run(msg.content) # 执行 CodeWrite 动作,获取生成的代码 57 | msg = Message(content=code_text, role=self.profile, cause_by=type(todo)) # 构造 Message 对象 58 | 59 | return msg # 返回生成的 Message 60 | 61 | async def main(): 62 | msg = "如何用python获取最新的股票统计数据?" 63 | role = CodeWriter() # 实例化CodeWrite 64 | logger.info(msg) # 记录日志信息 65 | result = await role.run(msg) # 得到运行结果 66 | logger.info(result) # 记录运行结果 67 | 68 | asyncio.run(main()) # 异步运行main函数 # 正常python文件使用 -------------------------------------------------------------------------------- /3.单智能体-多Action.py: -------------------------------------------------------------------------------- 1 | import re 2 | import asyncio 3 | import subprocess 4 | from metagpt.actions import Action 5 | from metagpt.roles import Role 6 | from metagpt.schema import Message 7 | from metagpt.logs import logger 8 | 9 | # 代码撰写Action 10 | class CodeWrite(Action): 11 | PROMPT_TEMPLATE: str = """ 12 | 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。 13 | 返回的格式为:```python\n你的代码\n```,请不要包含其他的文本。 14 | ```python 15 | # your code here 16 | ``` 17 | """ 18 | 19 | name: str = "CodeWriter" 20 | 21 | async def run(self, requirements: str): 22 | prompt = self.PROMPT_TEMPLATE.format(requirements=requirements) 23 | rsp = await self._aask(prompt) 24 | code_text = CodeWrite.parse_code(rsp) 25 | return code_text 26 | 27 | @staticmethod 28 | def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码 29 | pattern = r'```python(.*?)```' # 使用非贪婪匹配 30 | match = re.search(pattern, rsp, re.DOTALL) 31 | code_text = match.group(1) if match else rsp 32 | return code_text 33 | 34 | 35 | # 需求优化Action 36 | class RequirementsOpt(Action): 37 | PROMPT_TEMPLATE: str = """ 38 | 你要遵守的规范有: 39 | 1.简要说明 (Brief Description) 40 |   简要介绍该用例的作用和目的。 41 |   2.事件流 (Flow of Event) 42 |   包括基本流和备选流,事件流应该表示出所有的场景。 43 |   3.用例场景 (Use-Case Scenario) 44 |   包括成功场景和失败场景,场景主要是由基本流和备选流组合而成的。 45 |   4.特殊需求 (Special Requirement) 46 |   描述与该用例相关的非功能性需求(包括性能、可靠性、可用性和可扩展性等)和设计约束(所使用的操作系统、开发工具等)。 47 |   5.前置条件 (Pre-Condition) 48 |   执行用例之前系统必须所处的状态。 49 |   6.后置条件 (Post-Condition) 50 |   用例执行完毕后系统可能处于的一组状态。 51 | 无需测试用例,所有的代码在一个```python```中 52 |   请优化以下需求,使其更加明确和全面: 53 | {requirements} 54 | """ 55 | 56 | name: str = "RequirementsOpt" 57 | 58 | async def run(self, requirements: str): 59 | prompt = self.PROMPT_TEMPLATE.format(requirements=requirements) 60 | rsp = await self._aask(prompt) 61 | return rsp.strip() # 返回优化后的需求 62 | 63 | 64 | # 代码运行Action 65 | class CodeRun(Action): 66 | name: str = "CodeRun" 67 | 68 | async def run(self, code_text: str): 69 | try: 70 | result = subprocess.run( 71 | ['python', '-c', code_text], 72 | text=True, 73 | capture_output=True, 74 | check=True 75 | ) 76 | return result.stdout 77 | except subprocess.CalledProcessError as e: 78 | return e.stderr 79 | 80 | 81 | # 设计Programmer Agent人设 82 | class Programmer(Role): 83 | """ 84 | Programmer 角色类,继承自 Role 基类 85 | """ 86 | 87 | name: str = "cheems" 88 | profile: str = "Programmer" 89 | 90 | def __init__(self, **kwargs): 91 | """ 92 | 初始化 Programmer 角色 93 | """ 94 | super().__init__(**kwargs) # 调用基类构造函数 95 | self.set_actions([RequirementsOpt, CodeWrite, CodeRun]) # 为角色配备三个动作 96 | self._set_react_mode(react_mode="by_order") # 顺序执行 97 | 98 | async def _act(self) -> Message: 99 | """ 100 | 定义角色行动逻辑 101 | """ 102 | logger.info(f"{self._setting}: 准备 {self.rc.todo}") # 记录日志 103 | todo = self.rc.todo # 按照排列顺序获取待执行的动作 104 | 105 | msg = self.get_memories(k=1)[0] # 获取最相似的一条记忆 (用户输入) 106 | 107 | # 优化需求》编写代码》运行代码 108 | result = await todo.run(msg.content) 109 | 110 | # 构造 Message 对象 111 | msg = Message(content=result, role=self.profile, cause_by=type(todo)) 112 | self.rc.memory.add(msg) # 将运行结果添加到记忆 113 | 114 | return msg # 返回最终的 Message 115 | 116 | # 运行我们的Agent 117 | async def main(): 118 | msg = "如何用python设计一个ToDoList,使用Tkinter库,尽量不要安装额外包,安装包的代码要直接在python代码中运行,而非手动输入cmd;" 119 | role = Programmer() # 实例化 Programmer 120 | logger.info(msg) # 记录日志信息 121 | result = await role.run(msg) # 得到运行结果 122 | logger.info(result) # 记录运行结果 123 | 124 | asyncio.run(main()) # 异步运行 main 函数 -------------------------------------------------------------------------------- /3.单智能体-技术文档撰写助手.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Dict 3 | import asyncio 4 | from metagpt.actions.write_tutorial import WriteDirectory, WriteContent 5 | from metagpt.const import TUTORIAL_PATH 6 | from metagpt.logs import logger 7 | from metagpt.roles.role import Role, RoleReactMode 8 | from metagpt.schema import Message 9 | from metagpt.utils.file import File 10 | 11 | from typing import Dict 12 | 13 | from metagpt.actions import Action 14 | from metagpt.prompts.tutorial_assistant import DIRECTORY_PROMPT, CONTENT_PROMPT 15 | from metagpt.utils.common import OutputParser 16 | 17 | class WriteDirectory(Action): 18 | """Action class for writing tutorial directories. 19 | 20 | Args: 21 | name: The name of the action. 22 | language: The language to output, default is "Chinese". 23 | """ 24 | 25 | name: str = "WriteDirectory" 26 | language: str = "Chinese" 27 | 28 | async def run(self, topic: str, *args, **kwargs) -> Dict: 29 | """Execute the action to generate a tutorial directory according to the topic. 30 | 31 | Args: 32 | topic: The tutorial topic. 33 | 34 | Returns: 35 | the tutorial directory information, including {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]}. 36 | """ 37 | COMMON_PROMPT = """ 38 | You are now a seasoned technical professional in the field of the internet. 39 | We need you to write a technical tutorial with the topic "{topic}". 40 | """ 41 | 42 | DIRECTORY_PROMPT = COMMON_PROMPT + """ 43 | Please provide the specific table of contents for this tutorial, strictly following the following requirements: 44 | 1. The output must be strictly in the specified language, {language}. 45 | 2. Answer strictly in the dictionary format like {{"title": "xxx", "directory": [{{"dir 1": ["sub dir 1", "sub dir 2"]}}, {{"dir 2": ["sub dir 3", "sub dir 4"]}}]}}. 46 | 3. The directory should be as specific and sufficient as possible, with a primary and secondary directory.The secondary directory is in the array. 47 | 4. Do not have extra spaces or line breaks. 48 | 5. Each directory title has practical significance. 49 | """ 50 | prompt = DIRECTORY_PROMPT.format(topic=topic, language=self.language) 51 | resp = await self._aask(prompt=prompt) 52 | return OutputParser.extract_struct(resp, dict) 53 | 54 | class WriteContent(Action): 55 | """Action class for writing tutorial content. 56 | 57 | Args: 58 | name: The name of the action. 59 | directory: The content to write. 60 | language: The language to output, default is "Chinese". 61 | """ 62 | 63 | name: str = "WriteContent" 64 | directory: dict = dict() 65 | language: str = "Chinese" 66 | 67 | async def run(self, topic: str, *args, **kwargs) -> str: 68 | """Execute the action to write document content according to the directory and topic. 69 | 70 | Args: 71 | topic: The tutorial topic. 72 | 73 | Returns: 74 | The written tutorial content. 75 | """ 76 | COMMON_PROMPT = """ 77 | You are now a seasoned technical professional in the field of the internet. 78 | We need you to write a technical tutorial with the topic "{topic}". 79 | """ 80 | CONTENT_PROMPT = COMMON_PROMPT + """ 81 | Now I will give you the module directory titles for the topic. 82 | Please output the detailed principle content of this title in detail. 83 | If there are code examples, please provide them according to standard code specifications. 84 | Without a code example, it is not necessary. 85 | 86 | The module directory titles for the topic is as follows: 87 | {directory} 88 | 89 | Strictly limit output according to the following requirements: 90 | 1. Follow the Markdown syntax format for layout. 91 | 2. If there are code examples, they must follow standard syntax specifications, have document annotations, and be displayed in code blocks. 92 | 3. The output must be strictly in the specified language, {language}. 93 | 4. Do not have redundant output, including concluding remarks. 94 | 5. Strict requirement not to output the topic "{topic}". 95 | """ 96 | prompt = CONTENT_PROMPT.format( 97 | topic=topic, language=self.language, directory=self.directory) 98 | return await self._aask(prompt=prompt) 99 | 100 | class TutorialAssistant(Role): 101 | """Tutorial assistant, input one sentence to generate a tutorial document in markup format. 102 | 103 | Args: 104 | name: The name of the role. 105 | profile: The role profile description. 106 | goal: The goal of the role. 107 | constraints: Constraints or requirements for the role. 108 | language: The language in which the tutorial documents will be generated. 109 | """ 110 | 111 | name: str = "Stitch" 112 | profile: str = "Tutorial Assistant" 113 | goal: str = "Generate tutorial documents" 114 | constraints: str = "Strictly follow Markdown's syntax, with neat and standardized layout" 115 | language: str = "Chinese" 116 | 117 | topic: str = "" 118 | main_title: str = "" 119 | total_content: str = "" 120 | 121 | def __init__(self, **kwargs): 122 | super().__init__(**kwargs) 123 | self.set_actions([WriteDirectory(language=self.language)]) 124 | self._set_react_mode(react_mode=RoleReactMode.REACT.value) 125 | 126 | async def _think(self) -> None: 127 | """Determine the next action to be taken by the role.""" 128 | logger.info(self.rc.state) 129 | logger.info(self,) 130 | if self.rc.todo is None: 131 | self._set_state(0) 132 | return 133 | 134 | if self.rc.state + 1 < len(self.states): 135 | self._set_state(self.rc.state + 1) 136 | else: 137 | self.rc.todo = None 138 | 139 | async def _handle_directory(self, titles: Dict) -> Message: 140 | """Handle the directories for the tutorial document. 141 | 142 | Args: 143 | titles: A dictionary containing the titles and directory structure, 144 | such as {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]} 145 | 146 | Returns: 147 | A message containing information about the directory. 148 | """ 149 | self.main_title = titles.get("title") 150 | directory = f"{self.main_title}\n" 151 | self.total_content += f"# {self.main_title}" 152 | actions = list() 153 | print(titles,"diandiandian") 154 | for first_dir in titles.get("目录"): 155 | actions.append(WriteContent( 156 | language=self.language, directory=first_dir)) 157 | key = list(first_dir.keys())[0] 158 | directory += f"- {key}\n" 159 | for second_dir in first_dir[key]: 160 | directory += f" - {second_dir}\n" 161 | self.set_actions(actions) 162 | self.rc.todo = None 163 | return Message(content=directory) 164 | 165 | async def _act(self) -> Message: 166 | """Perform an action as determined by the role. 167 | 168 | Returns: 169 | A message containing the result of the action. 170 | """ 171 | todo = self.rc.todo 172 | if type(todo) is WriteDirectory: 173 | msg = self.rc.memory.get(k=1)[0] 174 | self.topic = msg.content 175 | resp = await todo.run(topic=self.topic) 176 | logger.info(resp) 177 | return await self._handle_directory(resp) 178 | resp = await todo.run(topic=self.topic) 179 | logger.info(resp) 180 | if self.total_content != "": 181 | self.total_content += "\n\n\n" 182 | self.total_content += resp 183 | return Message(content=resp, role=self.profile) 184 | 185 | async def _react(self) -> Message: 186 | """Execute the assistant's think and actions. 187 | 188 | Returns: 189 | A message containing the final result of the assistant's actions. 190 | """ 191 | while True: 192 | await self._think() 193 | if self.rc.todo is None: 194 | break 195 | msg = await self._act() 196 | root_path = TUTORIAL_PATH / datetime.now().strftime("%Y-%m-%d_%H-%M-%S") 197 | await File.write(root_path, f"{self.main_title}.md", self.total_content.encode('utf-8')) 198 | return msg 199 | 200 | async def main(): 201 | msg = "Git 教程" 202 | role = TutorialAssistant() 203 | logger.info(msg) 204 | result = await role.run(msg) 205 | logger.info(result) 206 | 207 | asyncio.run(main()) -------------------------------------------------------------------------------- /3.单智能体-课后作业 New.py: -------------------------------------------------------------------------------- 1 | import re 2 | import asyncio 3 | import subprocess 4 | from metagpt.actions import Action 5 | from metagpt.roles import Role 6 | from metagpt.schema import Message 7 | from metagpt.logs import logger 8 | 9 | # 代码撰写Action 10 | class RolePrinter(Action): 11 | PROMPT_TEMPLATE: str = """ 12 | 我是{name},{birth}岁,我已经来到这个世界{day}天了,我现在身份是{role},等级为{level},这些天,我的经历是{history},我将要去做{goal} 13 | """ 14 | 15 | name: str = "CodeWriter" 16 | 17 | async def run(self, name: str,birth:int,day:int,role:str,level:int,history:str,goal:str): 18 | prompt = self.PROMPT_TEMPLATE.format(name=name,birth=birth,day=day,role=role,level=level,history=history,goal=goal) 19 | rsp = await self._aask(prompt) 20 | code_text = CodeWrite.parse_code(rsp) 21 | return code_text 22 | 23 | @staticmethod 24 | def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码 25 | pattern = r'```python(.*?)```' # 使用非贪婪匹配 26 | match = re.search(pattern, rsp, re.DOTALL) 27 | code_text = match.group(1) if match else rsp 28 | return code_text 29 | 30 | 31 | 32 | 33 | class CustomAgent: 34 | def __init__(Role): 35 | self.actions = [] 36 | self.memory = [] 37 | self.execution_count = 0 38 | # 设定角色属性 39 | self.level = 1 # 修炼等级,初始为1 40 | self.world_view = "仙侠世界" 41 | self.name = "未觉醒修炼者" 42 | self.personality = "性格狠辣" 43 | self.status = "初学者" 44 | 45 | # 初始化动作 46 | self.set_actions(self.generate_initial_actions()) 47 | 48 | def generate_new_action(self, actions: List[Action]): 49 | self.actions = actions 50 | self.current_action_index = 0 51 | 52 | def generate_initial_actions(self): 53 | prompts = [ 54 | self.generate_prompt("我重生了,我回到了我14岁时候"), 55 | self.generate_prompt("距离域外天魔,入侵还有5年"), 56 | self.generate_prompt("我现在是捷克城的平民,是一个拥有空间天赋的未觉醒异能者,我需要尽快强大起来,先从吃饱饭开始,可是我身无分文...") 57 | ] 58 | return [Action(str(uuid.uuid4()), f"Print{i+1}", prompts[i]) for i in range(3)] 59 | 60 | def generate_prompt(self, event): 61 | return (f"你是{self.name}, 现在正处于{self.world_view}, 你的性格是{self.personality}, " 62 | f"你当前身份是{self.status}, 你在世界的地位是{self.level}, 面对{event}, " 63 | "你打算说:") 64 | 65 | async def _ask(self, prompt): 66 | # 模拟从外部获取内容 67 | return f"这是对提示 [{prompt}] 的响应内容。" 68 | 69 | async def store_to_ceramic(self, action_id, content): 70 | # 模拟将数据存储到Ceramic网络 71 | print(f"Storing action {action_id} content to Ceramic: {content}") 72 | 73 | def reflect_and_update(self): 74 | # 简单的反思机制,根据记忆更新角色属性 75 | if self.execution_count % 5 == 0: 76 | self.level += 1 # 每执行两轮,修炼等级提升一级 77 | self.status = "高级修炼者" if self.level > 1 else "初学者" 78 | print(f"反思:当前修炼等级为 {self.level}") 79 | 80 | async def _act(self): 81 | while self.current_action_index < len(self.actions): 82 | action = self.actions[self.current_action_index] 83 | result = await action.run(self) 84 | self.current_action_index += 1 85 | 86 | # 存储运行结果到记忆中 87 | self.memory.append({ 88 | 'id': action.id, 89 | 'name': action.name, 90 | 'content': result, 91 | 'state': action.state 92 | }) 93 | 94 | # 打印日志 95 | print(f"Action {self.current_action_index} completed: {result}") 96 | 97 | # 动作执行完毕后生成新的动作列表 98 | if self.current_action_index >= len(self.actions): 99 | self.execution_count += 1 100 | if self.execution_count < 10: # 循环执行10次 101 | self.reflect_and_update() 102 | print("All initial actions completed. Generating new actions.") 103 | new_actions = [Action(str(uuid.uuid4()), "Print4", self.generate_prompt("打印4")), 104 | Action(str(uuid.uuid4()), "Print5", self.generate_prompt("打印5")), 105 | Action(str(uuid.uuid4()), "Print6", self.generate_prompt("打印6"))] 106 | self.set_actions(new_actions) 107 | await self._act() # 递归调用继续执行新动作 108 | 109 | async def run(self): 110 | print(f"Agent {self.name} started in {self.world_view}.") 111 | await self._act() 112 | print(f"Agent {self.name} finished all actions with level {self.level}.") 113 | 114 | 115 | # 运行我们的 Agent 116 | async def main(): 117 | agent = CustomAgent() # 实例化 CustomAgent 118 | await agent.run() # 运行 agent 119 | 120 | asyncio.run(main()) # 异步运行 main -------------------------------------------------------------------------------- /3.单智能体-课后作业.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from metagpt.actions.write_tutorial import WriteDirectory, WriteContent 3 | from metagpt.logs import logger 4 | from metagpt.roles.role import Role 5 | from metagpt.schema import Message 6 | from metagpt.actions import Action 7 | from metagpt.prompts.tutorial_assistant import DIRECTORY_PROMPT, CONTENT_PROMPT 8 | from metagpt.utils.common import OutputParser 9 | 10 | # 定义 Action 类,继承自 metagpt.actions.Action 11 | class PrintAction(Action): 12 | def __init__(self, ID, name, content, day, period): 13 | super().__init__() 14 | self.ID = ID 15 | self.name = name 16 | self.content = content 17 | self.day = day 18 | self.period = period 19 | self.state = 0 # 初始化状态为 0,未执行 20 | 21 | async def run(self): 22 | try: 23 | self.content = await self._aask(f"这是我们的聊天历史:{self.content},当前时间是第{self.day}天,{self.period},请你继续与我以一个心理医生角度交谈,内容要符合时间,而不是一个AI,,回复要推动事情发展前进,而不是只考虑一个话题;现在针对我的话进行回复即可") 24 | self.state = 2 # 执行成功,状态更新为 2 25 | except Exception as e: 26 | print(e) 27 | self.state = 1 # 执行失败,状态更新为 1 28 | return self.content # 确保返回一个字符串 29 | 30 | class PrintAgent(Role): 31 | def __init__(self, **kwargs): 32 | super().__init__(**kwargs) 33 | self.actions = [] # 初始化动作列表 34 | self.action_id = 0 # 初始化动作 ID 35 | self.day = 1 # 从第1天开始 36 | self.periods = ["早晨", "下午", "晚上"] 37 | self.profile = "cheems" 38 | 39 | # 初始化前三个固定的 PrintAction 40 | self.add_initial_actions() 41 | 42 | def add_initial_actions(self): 43 | initial_contents = [ 44 | '你叫什么名字?', 45 | 'Cheems,我感到很累?我整天996工作,但是我别无选择,医生,我该怎么办', 46 | '讲讲你的故事,Cheems,我愿意倾听..' 47 | ] 48 | for index, content in enumerate(initial_contents): 49 | self.action_id += 1 50 | action = PrintAction(self.action_id, f"打印{self.action_id}", content, self.day, self.periods[index]) 51 | self.add_action(action) 52 | 53 | def add_action(self, action): 54 | self.actions.append(action) # 添加动作到动作列表 55 | 56 | async def run_actions(self): 57 | for action in self.actions: 58 | todo = self.rc.todo # 按照排列顺序获取待执行的动作 59 | logger.info(f"{self._setting}: 准备动作{action.ID},今天是第{action.day}天, {action.period}") # 记录日志 60 | msg = await action.run() # 顺序执行动作 61 | msg = Message(content=msg or "", role=self.profile, cause_by=type(todo)) 62 | self.rc.memory.add(msg) # 将执行结果添加到记忆 63 | self.day += 1 64 | 65 | self.actions = [] # 清空动作列表 66 | 67 | def generate_actions(self): 68 | # 生成三个新的动作,ID 递增 69 | for i in range(3): 70 | self.action_id += 1 71 | msg = self.get_memories(k=1)[0] # 获取最相似的1条记忆 72 | action = PrintAction(self.action_id, f"打印{self.action_id}", msg, self.day, self.periods[i]) 73 | self.add_action(action) 74 | 75 | async def _act(self) -> Message: 76 | while True: 77 | if not self.actions: # 如果动作列表为空 78 | self.generate_actions() # 生成新的动作 79 | await self.run_actions() # 执行动作 80 | await asyncio.sleep(1) # 添加一个短暂的休眠,以防止无限循环导致过高的 CPU 占用 81 | return Message(content="动作执行完毕", role=self.profile) 82 | 83 | # 异步主函数 84 | async def main(): 85 | agent = PrintAgent() # 创建 医生 实例 86 | await agent._act() # 执行动作 87 | 88 | # 运行异步主函数 89 | asyncio.run(main()) -------------------------------------------------------------------------------- /3.基于MetaGPT构建单Agent.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### 环境配置\n", 15 | "我们clone MetaGPT项目到本地进行研究:\n", 16 | "```bash\n", 17 | "!git clone https://github.com/geekan/MetaGPT.git\n", 18 | "!cd MetaGPT\n", 19 | "!pip install -e .\n", 20 | "```" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 8, 26 | "metadata": {}, 27 | "outputs": [ 28 | { 29 | "name": "stdout", 30 | "output_type": "stream", 31 | "text": [ 32 | "Cloning into 'MetaGPT'...\n", 33 | "remote: Enumerating objects: 32223, done.\u001b[K\n", 34 | "remote: Counting objects: 100% (41/41), done.\u001b[K\n", 35 | "remote: Compressing objects: 100% (33/33), done.\u001b[K\n", 36 | "remote: Total 32223 (delta 20), reused 13 (delta 8), pack-reused 32182\u001b[K\n", 37 | "Receiving objects: 100% (32223/32223), 92.49 MiB | 12.40 MiB/s, done.\n", 38 | "Resolving deltas: 100% (24132/24132), done.\n" 39 | ] 40 | } 41 | ], 42 | "source": [ 43 | "!git clone https://github.com/geekan/MetaGPT.git\n" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 15, 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "Dockerfile README.md\t docs\t requirements.txt tests\n", 56 | "LICENSE SECURITY.md examples ruff.toml\n", 57 | "MANIFEST.in config\t metagpt setup.py\n" 58 | ] 59 | } 60 | ], 61 | "source": [ 62 | "!cd ./MetaGPT/\n", 63 | "!dir ./MetaGPT/" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 18, 69 | "metadata": {}, 70 | "outputs": [ 71 | { 72 | "name": "stdout", 73 | "output_type": "stream", 74 | "text": [ 75 | "Obtaining file:///workspaces/MetaGPT-Learn/MetaGPT\n", 76 | " Installing build dependencies ... \u001b[?25ldone\n", 77 | "\u001b[?25h Checking if build backend supports build_editable ... \u001b[?25ldone\n", 78 | "\u001b[?25h Getting requirements to build editable ... \u001b[?25ldone\n", 79 | "\u001b[?25h Installing backend dependencies ... \u001b[?25ldone\n", 80 | "\u001b[?25h Preparing editable metadata (pyproject.toml) ... \u001b[?25ldone\n", 81 | "\u001b[?25hRequirement already satisfied: aiohttp==3.8.6 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (3.8.6)\n", 82 | "Requirement already satisfied: channels==4.0.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (4.0.0)\n", 83 | "Requirement already satisfied: faiss-cpu==1.7.4 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.7.4)\n", 84 | "Requirement already satisfied: fire==0.4.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.4.0)\n", 85 | "Collecting typer==0.9.0 (from metagpt==0.8.1)\n", 86 | " Using cached typer-0.9.0-py3-none-any.whl.metadata (14 kB)\n", 87 | "Requirement already satisfied: lancedb==0.4.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.4.0)\n", 88 | "Requirement already satisfied: loguru==0.6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.6.0)\n", 89 | "Requirement already satisfied: meilisearch==0.21.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.21.0)\n", 90 | "Requirement already satisfied: numpy>=1.24.3 in /home/codespace/.local/lib/python3.10/site-packages (from metagpt==0.8.1) (1.26.4)\n", 91 | "Requirement already satisfied: openai>=1.6.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.28.1)\n", 92 | "Requirement already satisfied: openpyxl in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (3.1.2)\n", 93 | "Requirement already satisfied: beautifulsoup4==4.12.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (4.12.3)\n", 94 | "Requirement already satisfied: pandas==2.1.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (2.1.1)\n", 95 | "Requirement already satisfied: pydantic>=2.5.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (2.5.3)\n", 96 | "Requirement already satisfied: python-docx==0.8.11 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.8.11)\n", 97 | "Requirement already satisfied: PyYAML==6.0.1 in /home/codespace/.local/lib/python3.10/site-packages (from metagpt==0.8.1) (6.0.1)\n", 98 | "Requirement already satisfied: setuptools==65.6.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (65.6.3)\n", 99 | "Requirement already satisfied: tenacity==8.2.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (8.2.3)\n", 100 | "Requirement already satisfied: tiktoken==0.6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.6.0)\n", 101 | "Requirement already satisfied: tqdm==4.66.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (4.66.2)\n", 102 | "Requirement already satisfied: anthropic==0.18.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.18.1)\n", 103 | "Requirement already satisfied: typing-inspect==0.8.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.8.0)\n", 104 | "Requirement already satisfied: libcst==1.0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.0.1)\n", 105 | "Requirement already satisfied: qdrant-client==1.7.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.7.0)\n", 106 | "Requirement already satisfied: ta==0.10.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.10.2)\n", 107 | "Requirement already satisfied: semantic-kernel==0.4.3.dev0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.4.3.dev0)\n", 108 | "Requirement already satisfied: wrapt==1.15.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.15.0)\n", 109 | "Requirement already satisfied: aioredis~=2.0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (2.0.1)\n", 110 | "Requirement already satisfied: websocket-client==1.6.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.6.2)\n", 111 | "Requirement already satisfied: aiofiles==23.2.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (23.2.1)\n", 112 | "Requirement already satisfied: gitpython==3.1.40 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (3.1.40)\n", 113 | "Requirement already satisfied: zhipuai==2.0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (2.0.1)\n", 114 | "Requirement already satisfied: rich==13.6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (13.6.0)\n", 115 | "Requirement already satisfied: nbclient==0.9.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.9.0)\n", 116 | "Requirement already satisfied: nbformat==5.9.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (5.9.2)\n", 117 | "Requirement already satisfied: ipython==8.17.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (8.17.2)\n", 118 | "Requirement already satisfied: ipykernel==6.27.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (6.27.1)\n", 119 | "Requirement already satisfied: scikit-learn==1.3.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.3.2)\n", 120 | "Requirement already satisfied: typing-extensions==4.9.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (4.9.0)\n", 121 | "Requirement already satisfied: socksio~=1.0.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.0.0)\n", 122 | "Requirement already satisfied: gitignore-parser==0.1.9 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.1.9)\n", 123 | "Requirement already satisfied: websockets<12.0,>=10.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (11.0.3)\n", 124 | "Requirement already satisfied: networkx~=3.2.1 in /home/codespace/.local/lib/python3.10/site-packages (from metagpt==0.8.1) (3.2.1)\n", 125 | "Requirement already satisfied: google-generativeai==0.4.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.4.1)\n", 126 | "Requirement already satisfied: playwright>=1.26 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.43.0)\n", 127 | "Requirement already satisfied: anytree in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (2.12.1)\n", 128 | "Requirement already satisfied: ipywidgets==8.1.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (8.1.1)\n", 129 | "Requirement already satisfied: Pillow in /home/codespace/.local/lib/python3.10/site-packages (from metagpt==0.8.1) (10.3.0)\n", 130 | "Requirement already satisfied: imap-tools==1.5.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.5.0)\n", 131 | "Requirement already satisfied: qianfan==0.3.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.3.2)\n", 132 | "Requirement already satisfied: dashscope==1.14.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (1.14.1)\n", 133 | "Requirement already satisfied: rank-bm25==0.2.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.2.2)\n", 134 | "Requirement already satisfied: gymnasium==0.29.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from metagpt==0.8.1) (0.29.1)\n", 135 | "Requirement already satisfied: attrs>=17.3.0 in /home/codespace/.local/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (23.2.0)\n", 136 | "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /home/codespace/.local/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (3.3.2)\n", 137 | "Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (6.0.5)\n", 138 | "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (4.0.3)\n", 139 | "Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (1.9.4)\n", 140 | "Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (1.4.1)\n", 141 | "Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from aiohttp==3.8.6->metagpt==0.8.1) (1.3.1)\n", 142 | "Requirement already satisfied: anyio<5,>=3.5.0 in /home/codespace/.local/lib/python3.10/site-packages (from anthropic==0.18.1->metagpt==0.8.1) (4.3.0)\n", 143 | "Requirement already satisfied: distro<2,>=1.7.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from anthropic==0.18.1->metagpt==0.8.1) (1.9.0)\n", 144 | "Requirement already satisfied: httpx<1,>=0.23.0 in /home/codespace/.local/lib/python3.10/site-packages (from anthropic==0.18.1->metagpt==0.8.1) (0.27.0)\n", 145 | "Requirement already satisfied: sniffio in /home/codespace/.local/lib/python3.10/site-packages (from anthropic==0.18.1->metagpt==0.8.1) (1.3.1)\n", 146 | "Requirement already satisfied: tokenizers>=0.13.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from anthropic==0.18.1->metagpt==0.8.1) (0.15.2)\n", 147 | "Requirement already satisfied: soupsieve>1.2 in /home/codespace/.local/lib/python3.10/site-packages (from beautifulsoup4==4.12.3->metagpt==0.8.1) (2.5)\n", 148 | "Requirement already satisfied: Django>=3.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from channels==4.0.0->metagpt==0.8.1) (5.0.6)\n", 149 | "Requirement already satisfied: asgiref<4,>=3.5.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from channels==4.0.0->metagpt==0.8.1) (3.8.1)\n", 150 | "Requirement already satisfied: requests in /home/codespace/.local/lib/python3.10/site-packages (from dashscope==1.14.1->metagpt==0.8.1) (2.31.0)\n", 151 | "Requirement already satisfied: six in /home/codespace/.local/lib/python3.10/site-packages (from fire==0.4.0->metagpt==0.8.1) (1.16.0)\n", 152 | "Requirement already satisfied: termcolor in /usr/local/python/3.10.13/lib/python3.10/site-packages (from fire==0.4.0->metagpt==0.8.1) (2.4.0)\n", 153 | "Requirement already satisfied: gitdb<5,>=4.0.1 in /home/codespace/.local/lib/python3.10/site-packages (from gitpython==3.1.40->metagpt==0.8.1) (4.0.11)\n", 154 | "Requirement already satisfied: google-ai-generativelanguage==0.4.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-generativeai==0.4.1->metagpt==0.8.1) (0.4.0)\n", 155 | "Requirement already satisfied: google-auth>=2.15.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-generativeai==0.4.1->metagpt==0.8.1) (2.29.0)\n", 156 | "Requirement already satisfied: google-api-core in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-generativeai==0.4.1->metagpt==0.8.1) (2.19.0)\n", 157 | "Requirement already satisfied: protobuf in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-generativeai==0.4.1->metagpt==0.8.1) (4.25.3)\n", 158 | "Requirement already satisfied: cloudpickle>=1.2.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from gymnasium==0.29.1->metagpt==0.8.1) (3.0.0)\n", 159 | "Requirement already satisfied: farama-notifications>=0.0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from gymnasium==0.29.1->metagpt==0.8.1) (0.0.4)\n", 160 | "Requirement already satisfied: comm>=0.1.1 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (0.2.2)\n", 161 | "Requirement already satisfied: debugpy>=1.6.5 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (1.8.1)\n", 162 | "Requirement already satisfied: jupyter-client>=6.1.12 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (8.6.1)\n", 163 | "Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (5.7.2)\n", 164 | "Requirement already satisfied: matplotlib-inline>=0.1 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (0.1.6)\n", 165 | "Requirement already satisfied: nest-asyncio in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (1.6.0)\n", 166 | "Requirement already satisfied: packaging in /usr/local/python/3.10.13/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (23.2)\n", 167 | "Requirement already satisfied: psutil in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (5.9.8)\n", 168 | "Requirement already satisfied: pyzmq>=20 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (25.1.2)\n", 169 | "Requirement already satisfied: tornado>=6.1 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (6.4)\n", 170 | "Requirement already satisfied: traitlets>=5.4.0 in /home/codespace/.local/lib/python3.10/site-packages (from ipykernel==6.27.1->metagpt==0.8.1) (5.14.2)\n", 171 | "Requirement already satisfied: decorator in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (5.1.1)\n", 172 | "Requirement already satisfied: jedi>=0.16 in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (0.19.1)\n", 173 | "Requirement already satisfied: prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30 in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (3.0.43)\n", 174 | "Requirement already satisfied: pygments>=2.4.0 in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (2.17.2)\n", 175 | "Requirement already satisfied: stack-data in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (0.6.3)\n", 176 | "Requirement already satisfied: exceptiongroup in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (1.2.0)\n", 177 | "Requirement already satisfied: pexpect>4.3 in /home/codespace/.local/lib/python3.10/site-packages (from ipython==8.17.2->metagpt==0.8.1) (4.9.0)\n", 178 | "Requirement already satisfied: widgetsnbextension~=4.0.9 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from ipywidgets==8.1.1->metagpt==0.8.1) (4.0.10)\n", 179 | "Requirement already satisfied: jupyterlab-widgets~=3.0.9 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from ipywidgets==8.1.1->metagpt==0.8.1) (3.0.10)\n", 180 | "Requirement already satisfied: deprecation in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (2.1.0)\n", 181 | "Requirement already satisfied: pylance==0.9.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (0.9.0)\n", 182 | "Requirement already satisfied: ratelimiter~=1.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (1.2.0.post0)\n", 183 | "Requirement already satisfied: retry>=0.9.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (0.9.2)\n", 184 | "Requirement already satisfied: semver>=3.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (3.0.2)\n", 185 | "Requirement already satisfied: cachetools in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (5.3.3)\n", 186 | "Requirement already satisfied: click>=8.1.7 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (8.1.7)\n", 187 | "Requirement already satisfied: overrides>=0.7 in /home/codespace/.local/lib/python3.10/site-packages (from lancedb==0.4.0->metagpt==0.8.1) (7.7.0)\n", 188 | "Requirement already satisfied: camel-converter[pydantic] in /usr/local/python/3.10.13/lib/python3.10/site-packages (from meilisearch==0.21.0->metagpt==0.8.1) (3.1.2)\n", 189 | "Requirement already satisfied: fastjsonschema in /home/codespace/.local/lib/python3.10/site-packages (from nbformat==5.9.2->metagpt==0.8.1) (2.19.1)\n", 190 | "Requirement already satisfied: jsonschema>=2.6 in /home/codespace/.local/lib/python3.10/site-packages (from nbformat==5.9.2->metagpt==0.8.1) (4.21.1)\n", 191 | "Requirement already satisfied: python-dateutil>=2.8.2 in /home/codespace/.local/lib/python3.10/site-packages (from pandas==2.1.1->metagpt==0.8.1) (2.9.0.post0)\n", 192 | "Requirement already satisfied: pytz>=2020.1 in /home/codespace/.local/lib/python3.10/site-packages (from pandas==2.1.1->metagpt==0.8.1) (2024.1)\n", 193 | "Requirement already satisfied: tzdata>=2022.1 in /home/codespace/.local/lib/python3.10/site-packages (from pandas==2.1.1->metagpt==0.8.1) (2024.1)\n", 194 | "Requirement already satisfied: lxml>=2.3.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from python-docx==0.8.11->metagpt==0.8.1) (5.2.1)\n", 195 | "Requirement already satisfied: grpcio>=1.41.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qdrant-client==1.7.0->metagpt==0.8.1) (1.63.0)\n", 196 | "Requirement already satisfied: grpcio-tools>=1.41.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qdrant-client==1.7.0->metagpt==0.8.1) (1.62.2)\n", 197 | "Requirement already satisfied: portalocker<3.0.0,>=2.7.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qdrant-client==1.7.0->metagpt==0.8.1) (2.8.2)\n", 198 | "Collecting urllib3<2.0.0,>=1.26.14 (from qdrant-client==1.7.0->metagpt==0.8.1)\n", 199 | " Using cached urllib3-1.26.18-py2.py3-none-any.whl.metadata (48 kB)\n", 200 | "Requirement already satisfied: aiolimiter>=1.1.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qianfan==0.3.2->metagpt==0.8.1) (1.1.0)\n", 201 | "Requirement already satisfied: bce-python-sdk>=0.8.79 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qianfan==0.3.2->metagpt==0.8.1) (0.9.7)\n", 202 | "Requirement already satisfied: multiprocess in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qianfan==0.3.2->metagpt==0.8.1) (0.70.16)\n", 203 | "Requirement already satisfied: pyarrow>=14.0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qianfan==0.3.2->metagpt==0.8.1) (16.0.0)\n", 204 | "Requirement already satisfied: python-dotenv>=1.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from qianfan==0.3.2->metagpt==0.8.1) (1.0.0)\n", 205 | "Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from rich==13.6.0->metagpt==0.8.1) (3.0.0)\n", 206 | "Requirement already satisfied: scipy>=1.5.0 in /home/codespace/.local/lib/python3.10/site-packages (from scikit-learn==1.3.2->metagpt==0.8.1) (1.13.0)\n", 207 | "Requirement already satisfied: joblib>=1.1.1 in /home/codespace/.local/lib/python3.10/site-packages (from scikit-learn==1.3.2->metagpt==0.8.1) (1.3.2)\n", 208 | "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/codespace/.local/lib/python3.10/site-packages (from scikit-learn==1.3.2->metagpt==0.8.1) (3.4.0)\n", 209 | "Requirement already satisfied: motor<4.0.0,>=3.3.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (3.4.0)\n", 210 | "Requirement already satisfied: openapi_core<0.19.0,>=0.18.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.18.2)\n", 211 | "Requirement already satisfied: prance<24.0.0.0,>=23.6.21.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (23.6.21.0)\n", 212 | "Requirement already satisfied: regex<2024.0.0,>=2023.6.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (2023.12.25)\n", 213 | "Requirement already satisfied: mypy-extensions>=0.3.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from typing-inspect==0.8.0->metagpt==0.8.1) (1.0.0)\n", 214 | "Requirement already satisfied: pyjwt~=2.8.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from zhipuai==2.0.1->metagpt==0.8.1) (2.8.0)\n", 215 | "Requirement already satisfied: proto-plus<2.0.0dev,>=1.22.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-ai-generativelanguage==0.4.0->google-generativeai==0.4.1->metagpt==0.8.1) (1.23.0)\n", 216 | "Requirement already satisfied: greenlet==3.0.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from playwright>=1.26->metagpt==0.8.1) (3.0.3)\n", 217 | "Requirement already satisfied: pyee==11.1.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from playwright>=1.26->metagpt==0.8.1) (11.1.0)\n", 218 | "Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from pydantic>=2.5.3->metagpt==0.8.1) (0.6.0)\n", 219 | "Requirement already satisfied: pydantic-core==2.14.6 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from pydantic>=2.5.3->metagpt==0.8.1) (2.14.6)\n", 220 | "Requirement already satisfied: et-xmlfile in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openpyxl->metagpt==0.8.1) (1.1.0)\n", 221 | "Requirement already satisfied: idna>=2.8 in /home/codespace/.local/lib/python3.10/site-packages (from anyio<5,>=3.5.0->anthropic==0.18.1->metagpt==0.8.1) (3.6)\n", 222 | "Requirement already satisfied: pycryptodome>=3.8.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from bce-python-sdk>=0.8.79->qianfan==0.3.2->metagpt==0.8.1) (3.20.0)\n", 223 | "Requirement already satisfied: future>=0.6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from bce-python-sdk>=0.8.79->qianfan==0.3.2->metagpt==0.8.1) (1.0.0)\n", 224 | "Requirement already satisfied: sqlparse>=0.3.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from Django>=3.2->channels==4.0.0->metagpt==0.8.1) (0.5.0)\n", 225 | "Requirement already satisfied: smmap<6,>=3.0.1 in /home/codespace/.local/lib/python3.10/site-packages (from gitdb<5,>=4.0.1->gitpython==3.1.40->metagpt==0.8.1) (5.0.1)\n", 226 | "Requirement already satisfied: googleapis-common-protos<2.0.dev0,>=1.56.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-api-core->google-generativeai==0.4.1->metagpt==0.8.1) (1.63.0)\n", 227 | "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-auth>=2.15.0->google-generativeai==0.4.1->metagpt==0.8.1) (0.4.0)\n", 228 | "Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-auth>=2.15.0->google-generativeai==0.4.1->metagpt==0.8.1) (4.9)\n", 229 | "Requirement already satisfied: certifi in /home/codespace/.local/lib/python3.10/site-packages (from httpx<1,>=0.23.0->anthropic==0.18.1->metagpt==0.8.1) (2024.2.2)\n", 230 | "Requirement already satisfied: httpcore==1.* in /home/codespace/.local/lib/python3.10/site-packages (from httpx<1,>=0.23.0->anthropic==0.18.1->metagpt==0.8.1) (1.0.5)\n", 231 | "Requirement already satisfied: h11<0.15,>=0.13 in /home/codespace/.local/lib/python3.10/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->anthropic==0.18.1->metagpt==0.8.1) (0.14.0)\n", 232 | "Requirement already satisfied: h2<5,>=3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from httpx[http2]>=0.14.0->qdrant-client==1.7.0->metagpt==0.8.1) (4.1.0)\n", 233 | "Requirement already satisfied: parso<0.9.0,>=0.8.3 in /home/codespace/.local/lib/python3.10/site-packages (from jedi>=0.16->ipython==8.17.2->metagpt==0.8.1) (0.8.3)\n", 234 | "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat==5.9.2->metagpt==0.8.1) (2023.7.1)\n", 235 | "Requirement already satisfied: referencing>=0.28.4 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat==5.9.2->metagpt==0.8.1) (0.30.2)\n", 236 | "Requirement already satisfied: rpds-py>=0.7.1 in /home/codespace/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat==5.9.2->metagpt==0.8.1) (0.18.0)\n", 237 | "Requirement already satisfied: platformdirs>=2.5 in /home/codespace/.local/lib/python3.10/site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel==6.27.1->metagpt==0.8.1) (4.2.0)\n", 238 | "Requirement already satisfied: mdurl~=0.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from markdown-it-py>=2.2.0->rich==13.6.0->metagpt==0.8.1) (0.1.2)\n", 239 | "Requirement already satisfied: pymongo<5,>=4.5 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from motor<4.0.0,>=3.3.1->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (4.7.2)\n", 240 | "Requirement already satisfied: isodate in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.6.1)\n", 241 | "Requirement already satisfied: jsonschema-spec<0.3.0,>=0.2.3 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.2.4)\n", 242 | "Requirement already satisfied: more-itertools in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (10.2.0)\n", 243 | "Requirement already satisfied: openapi-schema-validator<0.7.0,>=0.6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.6.2)\n", 244 | "Requirement already satisfied: openapi-spec-validator<0.8.0,>=0.7.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.7.1)\n", 245 | "Requirement already satisfied: parse in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (1.20.1)\n", 246 | "Requirement already satisfied: werkzeug in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (3.0.3)\n", 247 | "Requirement already satisfied: ptyprocess>=0.5 in /home/codespace/.local/lib/python3.10/site-packages (from pexpect>4.3->ipython==8.17.2->metagpt==0.8.1) (0.7.0)\n", 248 | "Requirement already satisfied: chardet>=3.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from prance<24.0.0.0,>=23.6.21.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (5.2.0)\n", 249 | "Requirement already satisfied: ruamel.yaml>=0.17.10 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from prance<24.0.0.0,>=23.6.21.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.18.6)\n", 250 | "Requirement already satisfied: wcwidth in /home/codespace/.local/lib/python3.10/site-packages (from prompt-toolkit!=3.0.37,<3.1.0,>=3.0.30->ipython==8.17.2->metagpt==0.8.1) (0.2.13)\n", 251 | "Requirement already satisfied: py<2.0.0,>=1.4.26 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from retry>=0.9.2->lancedb==0.4.0->metagpt==0.8.1) (1.11.0)\n", 252 | "Requirement already satisfied: huggingface_hub<1.0,>=0.16.4 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from tokenizers>=0.13.0->anthropic==0.18.1->metagpt==0.8.1) (0.23.0)\n", 253 | "Requirement already satisfied: dill>=0.3.8 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from multiprocess->qianfan==0.3.2->metagpt==0.8.1) (0.3.8)\n", 254 | "Requirement already satisfied: executing>=1.2.0 in /home/codespace/.local/lib/python3.10/site-packages (from stack-data->ipython==8.17.2->metagpt==0.8.1) (2.0.1)\n", 255 | "Requirement already satisfied: asttokens>=2.1.0 in /home/codespace/.local/lib/python3.10/site-packages (from stack-data->ipython==8.17.2->metagpt==0.8.1) (2.4.1)\n", 256 | "Requirement already satisfied: pure-eval in /home/codespace/.local/lib/python3.10/site-packages (from stack-data->ipython==8.17.2->metagpt==0.8.1) (0.2.2)\n", 257 | "Requirement already satisfied: grpcio-status<2.0.dev0,>=1.33.2 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.0->google-ai-generativelanguage==0.4.0->google-generativeai==0.4.1->metagpt==0.8.1) (1.62.2)\n", 258 | "Requirement already satisfied: hyperframe<7,>=6.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from h2<5,>=3->httpx[http2]>=0.14.0->qdrant-client==1.7.0->metagpt==0.8.1) (6.0.1)\n", 259 | "Requirement already satisfied: hpack<5,>=4.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from h2<5,>=3->httpx[http2]>=0.14.0->qdrant-client==1.7.0->metagpt==0.8.1) (4.0.0)\n", 260 | "Requirement already satisfied: filelock in /home/codespace/.local/lib/python3.10/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic==0.18.1->metagpt==0.8.1) (3.13.3)\n", 261 | "Requirement already satisfied: fsspec>=2023.5.0 in /home/codespace/.local/lib/python3.10/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic==0.18.1->metagpt==0.8.1) (2024.3.1)\n", 262 | "Requirement already satisfied: pathable<0.5.0,>=0.4.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from jsonschema-spec<0.3.0,>=0.2.3->openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.4.3)\n", 263 | "Requirement already satisfied: rfc3339-validator in /home/codespace/.local/lib/python3.10/site-packages (from openapi-schema-validator<0.7.0,>=0.6.0->openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.1.4)\n", 264 | "Requirement already satisfied: jsonschema-path<0.4.0,>=0.3.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi-spec-validator<0.8.0,>=0.7.1->openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.3.2)\n", 265 | "Requirement already satisfied: lazy-object-proxy<2.0.0,>=1.7.1 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from openapi-spec-validator<0.8.0,>=0.7.1->openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (1.10.0)\n", 266 | "Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from pyasn1-modules>=0.2.1->google-auth>=2.15.0->google-generativeai==0.4.1->metagpt==0.8.1) (0.6.0)\n", 267 | "Requirement already satisfied: dnspython<3.0.0,>=1.16.0 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from pymongo<5,>=4.5->motor<4.0.0,>=3.3.1->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (2.6.1)\n", 268 | "Requirement already satisfied: ruamel.yaml.clib>=0.2.7 in /usr/local/python/3.10.13/lib/python3.10/site-packages (from ruamel.yaml>=0.17.10->prance<24.0.0.0,>=23.6.21.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (0.2.8)\n", 269 | "Requirement already satisfied: MarkupSafe>=2.1.1 in /home/codespace/.local/lib/python3.10/site-packages (from werkzeug->openapi_core<0.19.0,>=0.18.0->semantic-kernel==0.4.3.dev0->metagpt==0.8.1) (2.1.5)\n", 270 | "Using cached typer-0.9.0-py3-none-any.whl (45 kB)\n", 271 | "Using cached urllib3-1.26.18-py2.py3-none-any.whl (143 kB)\n", 272 | "Building wheels for collected packages: metagpt\n", 273 | " Building editable for metagpt (pyproject.toml) ... \u001b[?25ldone\n", 274 | "\u001b[?25h Created wheel for metagpt: filename=metagpt-0.8.1-0.editable-py3-none-any.whl size=9177 sha256=8c056108c85398c0646c5eb8e3171908b336cda7d67259075748d9b71ce66dc1\n", 275 | " Stored in directory: /tmp/pip-ephem-wheel-cache-8b_d3_k3/wheels/fc/8a/52/7a1c7d27adf6344504c52041d73fee26e3453f0630f1631db9\n", 276 | "Successfully built metagpt\n", 277 | "Installing collected packages: urllib3, typer, metagpt\n", 278 | " Attempting uninstall: urllib3\n", 279 | " Found existing installation: urllib3 2.2.1\n", 280 | " Uninstalling urllib3-2.2.1:\n", 281 | " Successfully uninstalled urllib3-2.2.1\n", 282 | " Attempting uninstall: typer\n", 283 | " Found existing installation: typer 0.12.3\n", 284 | " Uninstalling typer-0.12.3:\n", 285 | " Successfully uninstalled typer-0.12.3\n", 286 | " Attempting uninstall: metagpt\n", 287 | " Found existing installation: metagpt 0.8.1\n", 288 | " Uninstalling metagpt-0.8.1:\n", 289 | " Successfully uninstalled metagpt-0.8.1\n", 290 | "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", 291 | "fastapi-cli 0.0.3 requires typer>=0.12.3, but you have typer 0.9.0 which is incompatible.\n", 292 | "types-requests 2.31.0.20240406 requires urllib3>=2, but you have urllib3 1.26.18 which is incompatible.\u001b[0m\u001b[31m\n", 293 | "\u001b[0mSuccessfully installed metagpt-0.8.1 typer-0.9.0 urllib3-1.26.18\n", 294 | "Note: you may need to restart the kernel to use updated packages.\n" 295 | ] 296 | } 297 | ], 298 | "source": [ 299 | "%pip install --upgrade -e ./MetaGPT/" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "- 配置API Key,打开/MetaGPT/config/config2.yaml\n", 307 | "- 然后填写自己的请求接口和API Key,作者这里使用的是deepseek的模型" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 1, 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "name": "stdout", 317 | "output_type": "stream", 318 | "text": [ 319 | " Hello! How can I assist you today? If you have any questions or need information on a specific topic, feel free to ask.\n" 320 | ] 321 | } 322 | ], 323 | "source": [ 324 | "# 测试一下接口\n", 325 | "from openai import OpenAI\n", 326 | "\n", 327 | "client = OpenAI(api_key=\"sk-6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX74\", base_url=\"https://api.deepseek.com\")\n", 328 | "\n", 329 | "response = client.chat.completions.create(\n", 330 | " model=\"deepseek-chat\",\n", 331 | " messages=[\n", 332 | " {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n", 333 | " {\"role\": \"user\", \"content\": \"Hello\"},\n", 334 | " ],\n", 335 | " stream=False\n", 336 | ")\n", 337 | "\n", 338 | "# 运行正常没有问题\n", 339 | "print(response.choices[0].message.content)" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": {}, 345 | "source": [ 346 | "### 编写CodeWrite动作\n" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": 2, 352 | "metadata": {}, 353 | "outputs": [ 354 | { 355 | "name": "stderr", 356 | "output_type": "stream", 357 | "text": [ 358 | "2024-05-15 18:11:36.284 | INFO | metagpt.const:get_metagpt_package_root:29 - Package root set to /workspaces/MetaGPT-Learn/MetaGPT\n" 359 | ] 360 | } 361 | ], 362 | "source": [ 363 | "import re\n", 364 | "import asyncio\n", 365 | "from metagpt.actions import Action\n", 366 | "\n", 367 | "class CodeWrite(Action):\n", 368 | " PROMPT_TEMPLATE: str = \"\"\"\n", 369 | " 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。\n", 370 | " 返回的格式为:```python\\n你的代码\\n```,请不要包含其他的文本。\n", 371 | " ```python\n", 372 | " # your code here\n", 373 | " ```\n", 374 | " \"\"\"\n", 375 | "\n", 376 | " name: str = \"CodeWriter\"\n", 377 | "\n", 378 | " async def run(self, requirements: str):\n", 379 | " prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)\n", 380 | " rsp = await self._aask(prompt)\n", 381 | " code_text = CodeWrite.parse_code(rsp)\n", 382 | " return code_text\n", 383 | "\n", 384 | " @staticmethod\n", 385 | " def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码\n", 386 | " pattern = r'```python(.*?)```' # 使用非贪婪匹配\n", 387 | " match = re.search(pattern, rsp, re.DOTALL)\n", 388 | " code_text = match.group(1) if match else rsp\n", 389 | " return code_text" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "### 设计CodeWriterAgent" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": 3, 402 | "metadata": {}, 403 | "outputs": [], 404 | "source": [ 405 | "from metagpt.roles import Role\n", 406 | "from metagpt.schema import Message\n", 407 | "from metagpt.logs import logger\n", 408 | "\n", 409 | "class CodeWriter(Role):\n", 410 | " \"\"\"\n", 411 | " CodeWriter 角色类,继承自 Role 基类\n", 412 | " \"\"\"\n", 413 | "\n", 414 | " name: str = \"Cheems\" # 角色昵称\n", 415 | " profile: str = \"CodeWriter\" # 角色人设\n", 416 | "\n", 417 | " def __init__(self, **kwargs):\n", 418 | " \"\"\"\n", 419 | " 初始化 CodeWriter 角色\n", 420 | " \"\"\"\n", 421 | " super().__init__(**kwargs) # 调用基类构造函数\n", 422 | " self.set_actions([CodeWrite]) # 为角色配备 CodeWrite 动作\n", 423 | "\n", 424 | " async def _act(self) -> Message:\n", 425 | " \"\"\"\n", 426 | " 定义角色行动逻辑\n", 427 | " \"\"\"\n", 428 | " logger.info(f\"{self._setting}: ready to {self.rc.todo}\") # 记录日志\n", 429 | " todo = self.rc.todo # 获取待执行的动作 (CodeWriter)\n", 430 | "\n", 431 | " msg = self.get_memories(k=1)[0] # 获取最近一条记忆 (用户输入)\n", 432 | "\n", 433 | " code_text = await todo.run(msg.content) # 执行 CodeWrite 动作,获取生成的代码\n", 434 | " msg = Message(content=code_text, role=self.profile, cause_by=type(todo)) # 构造 Message 对象\n", 435 | "\n", 436 | " return msg # 返回生成的 Message" 437 | ] 438 | }, 439 | { 440 | "cell_type": "markdown", 441 | "metadata": {}, 442 | "source": [ 443 | "### 运行测试CodeWriterAgent调用效果\n" 444 | ] 445 | }, 446 | { 447 | "cell_type": "code", 448 | "execution_count": 7, 449 | "metadata": {}, 450 | "outputs": [ 451 | { 452 | "name": "stderr", 453 | "output_type": "stream", 454 | "text": [ 455 | "/home/codespace/.python/current/lib/python3.10/ast.py:50: RuntimeWarning: coroutine 'main' was never awaited\n", 456 | " return compile(source, filename, mode, flags,\n", 457 | "RuntimeWarning: Enable tracemalloc to get the object allocation traceback\n" 458 | ] 459 | }, 460 | { 461 | "ename": "RuntimeError", 462 | "evalue": "Cannot close a running event loop", 463 | "output_type": "error", 464 | "traceback": [ 465 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 466 | "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", 467 | "Cell \u001b[0;32mIn[7], line 14\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[38;5;66;03m# asyncio.run(main()) # 异步运行main函数 # 正常python文件使用\u001b[39;00m\n\u001b[1;32m 11\u001b[0m \n\u001b[1;32m 12\u001b[0m \u001b[38;5;66;03m# 获取当前事件循环\u001b[39;00m\n\u001b[1;32m 13\u001b[0m loop \u001b[38;5;241m=\u001b[39m asyncio\u001b[38;5;241m.\u001b[39mget_event_loop() \u001b[38;5;66;03m# jupyter notebook中使用\u001b[39;00m\n\u001b[0;32m---> 14\u001b[0m \u001b[43mloop\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclose\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 16\u001b[0m \u001b[38;5;66;03m# 在当前事件循环中运行协程\u001b[39;00m\n\u001b[1;32m 17\u001b[0m \u001b[38;5;66;03m#loop.run_until_complete(main()) # jupyter notebook中使用\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \n\u001b[1;32m 19\u001b[0m \u001b[38;5;66;03m# 创建一个新的事件循环\u001b[39;00m\n\u001b[1;32m 20\u001b[0m new_loop \u001b[38;5;241m=\u001b[39m asyncio\u001b[38;5;241m.\u001b[39mnew_event_loop()\n", 468 | "File \u001b[0;32m~/.python/current/lib/python3.10/asyncio/unix_events.py:68\u001b[0m, in \u001b[0;36m_UnixSelectorEventLoop.close\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mclose\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m---> 68\u001b[0m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclose\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 69\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m sys\u001b[38;5;241m.\u001b[39mis_finalizing():\n\u001b[1;32m 70\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m sig \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_signal_handlers):\n", 469 | "File \u001b[0;32m~/.python/current/lib/python3.10/asyncio/selector_events.py:84\u001b[0m, in \u001b[0;36mBaseSelectorEventLoop.close\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 82\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mclose\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 83\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_running():\n\u001b[0;32m---> 84\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot close a running event loop\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 85\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_closed():\n\u001b[1;32m 86\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n", 470 | "\u001b[0;31mRuntimeError\u001b[0m: Cannot close a running event loop" 471 | ] 472 | } 473 | ], 474 | "source": [ 475 | "import asyncio\n", 476 | "\n", 477 | "async def main():\n", 478 | " msg = \"如何用python获取最新的股票统计数据?\"\n", 479 | " role = CodeWriter() # 实例化CodeWrite\n", 480 | " logger.info(msg) # 记录日志信息\n", 481 | " result = await role.run(msg) # 得到运行结果\n", 482 | " logger.info(result) # 记录运行结果\n", 483 | "\n", 484 | "asyncio.run(main()) # 异步运行main函数 # 正常python文件使用" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 1, 490 | "metadata": {}, 491 | "outputs": [ 492 | { 493 | "name": "stderr", 494 | "output_type": "stream", 495 | "text": [ 496 | "2024-05-15 18:21:09.414 | INFO | metagpt.const:get_metagpt_package_root:29 - Package root set to /workspaces/MetaGPT-Learn/MetaGPT\n" 497 | ] 498 | }, 499 | { 500 | "ename": "RuntimeError", 501 | "evalue": "asyncio.run() cannot be called from a running event loop", 502 | "output_type": "error", 503 | "traceback": [ 504 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 505 | "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", 506 | "Cell \u001b[0;32mIn[1], line 72\u001b[0m\n\u001b[1;32m 69\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m role\u001b[38;5;241m.\u001b[39mrun(msg) \u001b[38;5;66;03m# 得到运行结果\u001b[39;00m\n\u001b[1;32m 70\u001b[0m logger\u001b[38;5;241m.\u001b[39minfo(result) \u001b[38;5;66;03m# 记录运行结果\u001b[39;00m\n\u001b[0;32m---> 72\u001b[0m \u001b[43masyncio\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmain\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# 异步运行main函数 # 正常python文件使用\u001b[39;00m\n", 507 | "File \u001b[0;32m~/.python/current/lib/python3.10/asyncio/runners.py:33\u001b[0m, in \u001b[0;36mrun\u001b[0;34m(main, debug)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Execute the coroutine and return the result.\u001b[39;00m\n\u001b[1;32m 10\u001b[0m \n\u001b[1;32m 11\u001b[0m \u001b[38;5;124;03mThis function runs the passed coroutine, taking care of\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[38;5;124;03m asyncio.run(main())\u001b[39;00m\n\u001b[1;32m 31\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 32\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m events\u001b[38;5;241m.\u001b[39m_get_running_loop() \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m---> 33\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[1;32m 34\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124masyncio.run() cannot be called from a running event loop\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 36\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m coroutines\u001b[38;5;241m.\u001b[39miscoroutine(main):\n\u001b[1;32m 37\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma coroutine was expected, got \u001b[39m\u001b[38;5;132;01m{!r}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(main))\n", 508 | "\u001b[0;31mRuntimeError\u001b[0m: asyncio.run() cannot be called from a running event loop" 509 | ] 510 | } 511 | ], 512 | "source": [ 513 | "import re\n", 514 | "import asyncio\n", 515 | "from metagpt.actions import Action\n", 516 | "from metagpt.roles import Role\n", 517 | "from metagpt.schema import Message\n", 518 | "from metagpt.logs import logger\n", 519 | "\n", 520 | "class CodeWrite(Action):\n", 521 | " PROMPT_TEMPLATE: str = \"\"\"\n", 522 | " 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。\n", 523 | " 返回的格式为:```python\\n你的代码\\n```,请不要包含其他的文本。\n", 524 | " ```python\n", 525 | " # your code here\n", 526 | " ```\n", 527 | " \"\"\"\n", 528 | "\n", 529 | " name: str = \"CodeWriter\"\n", 530 | "\n", 531 | " async def run(self, requirements: str):\n", 532 | " prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)\n", 533 | " rsp = await self._aask(prompt)\n", 534 | " code_text = CodeWrite.parse_code(rsp)\n", 535 | " return code_text\n", 536 | "\n", 537 | " @staticmethod\n", 538 | " def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码\n", 539 | " pattern = r'```python(.*?)```' # 使用非贪婪匹配\n", 540 | " match = re.search(pattern, rsp, re.DOTALL)\n", 541 | " code_text = match.group(1) if match else rsp\n", 542 | " return code_text\n", 543 | "\n", 544 | "class CodeWriter(Role):\n", 545 | " \"\"\"\n", 546 | " CodeWriter 角色类,继承自 Role 基类\n", 547 | " \"\"\"\n", 548 | "\n", 549 | " name: str = \"Cheems\" # 角色昵称\n", 550 | " profile: str = \"CodeWriter\" # 角色人设\n", 551 | "\n", 552 | " def __init__(self, **kwargs):\n", 553 | " \"\"\"\n", 554 | " 初始化 CodeWriter 角色\n", 555 | " \"\"\"\n", 556 | " super().__init__(**kwargs) # 调用基类构造函数\n", 557 | " self.set_actions([CodeWrite]) # 为角色配备 CodeWrite 动作\n", 558 | "\n", 559 | " async def _act(self) -> Message:\n", 560 | " \"\"\"\n", 561 | " 定义角色行动逻辑\n", 562 | " \"\"\"\n", 563 | " logger.info(f\"{self._setting}: ready to {self.rc.todo}\") # 记录日志\n", 564 | " todo = self.rc.todo # 获取待执行的动作 (CodeWriter)\n", 565 | "\n", 566 | " msg = self.get_memories(k=1)[0] # 获取最近一条记忆 (用户输入)\n", 567 | "\n", 568 | " code_text = await todo.run(msg.content) # 执行 CodeWrite 动作,获取生成的代码\n", 569 | " msg = Message(content=code_text, role=self.profile, cause_by=type(todo)) # 构造 Message 对象\n", 570 | "\n", 571 | " return msg # 返回生成的 Message\n", 572 | "\n", 573 | "async def main():\n", 574 | " msg = \"如何用python获取最新的股票统计数据?\"\n", 575 | " role = CodeWriter() # 实例化CodeWrite\n", 576 | " logger.info(msg) # 记录日志信息\n", 577 | " result = await role.run(msg) # 得到运行结果\n", 578 | " logger.info(result) # 记录运行结果\n", 579 | "\n", 580 | "asyncio.run(main()) # 异步运行main函数 # 正常python文件使用" 581 | ] 582 | }, 583 | { 584 | "cell_type": "code", 585 | "execution_count": null, 586 | "metadata": {}, 587 | "outputs": [], 588 | "source": [ 589 | "# 构建多动作Agent\n", 590 | "import re\n", 591 | "import asyncio\n", 592 | "import subprocess\n", 593 | "from metagpt.actions import Action\n", 594 | "from metagpt.roles import Role\n", 595 | "from metagpt.schema import Message\n", 596 | "from metagpt.logs import logger\n", 597 | "\n", 598 | "# 代码撰写Action\n", 599 | "class CodeWrite(Action):\n", 600 | " PROMPT_TEMPLATE: str = \"\"\"\n", 601 | " 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。\n", 602 | " 返回的格式为:```python\\n你的代码\\n```,请不要包含其他的文本。\n", 603 | " ```python\n", 604 | " # your code here\n", 605 | " ```\n", 606 | " \"\"\"\n", 607 | "\n", 608 | " name: str = \"CodeWriter\"\n", 609 | "\n", 610 | " async def run(self, requirements: str):\n", 611 | " prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)\n", 612 | " rsp = await self._aask(prompt)\n", 613 | " code_text = CodeWrite.parse_code(rsp)\n", 614 | " return code_text\n", 615 | "\n", 616 | " @staticmethod\n", 617 | " def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码\n", 618 | " pattern = r'```python(.*?)```' # 使用非贪婪匹配\n", 619 | " match = re.search(pattern, rsp, re.DOTALL)\n", 620 | " code_text = match.group(1) if match else rsp\n", 621 | " return code_text\n", 622 | "\n", 623 | "\n", 624 | "# 需求优化Action\n", 625 | "class RequirementsOpt(Action):\n", 626 | " PROMPT_TEMPLATE: str = \"\"\"\n", 627 | " 你要遵守的规范有:\n", 628 | " 1.简要说明 (Brief Description)\n", 629 | "  简要介绍该用例的作用和目的。\n", 630 | "  2.事件流 (Flow of Event)\n", 631 | "  包括基本流和备选流,事件流应该表示出所有的场景。\n", 632 | "  3.用例场景 (Use-Case Scenario)\n", 633 | "  包括成功场景和失败场景,场景主要是由基本流和备选流组合而成的。\n", 634 | "  4.特殊需求 (Special Requirement)\n", 635 | "  描述与该用例相关的非功能性需求(包括性能、可靠性、可用性和可扩展性等)和设计约束(所使用的操作系统、开发工具等)。\n", 636 | "  5.前置条件 (Pre-Condition)\n", 637 | "  执行用例之前系统必须所处的状态。\n", 638 | "  6.后置条件 (Post-Condition)\n", 639 | "  用例执行完毕后系统可能处于的一组状态。\n", 640 | "  请优化以下需求,使其更加明确和全面:\n", 641 | " {requirements}\n", 642 | " \"\"\"\n", 643 | "\n", 644 | " name: str = \"RequirementsOpt\"\n", 645 | "\n", 646 | " async def run(self, requirements: str):\n", 647 | " prompt = self.PROMPT_TEMPLATE.format(requirements=requirements)\n", 648 | " rsp = await self._aask(prompt)\n", 649 | " return rsp.strip() # 返回优化后的需求\n", 650 | "\n", 651 | "\n", 652 | "# 代码运行Action\n", 653 | "class CodeRun(Action):\n", 654 | " name: str = \"CodeRun\"\n", 655 | "\n", 656 | " async def run(self, code_text: str):\n", 657 | " try:\n", 658 | " result = subprocess.run(\n", 659 | " ['python', '-c', code_text],\n", 660 | " text=True,\n", 661 | " capture_output=True,\n", 662 | " check=True\n", 663 | " )\n", 664 | " return result.stdout\n", 665 | " except subprocess.CalledProcessError as e:\n", 666 | " return e.stderr\n", 667 | "\n", 668 | "\n", 669 | "# 设计Programmer Agent人设\n", 670 | "class Programmer(Role):\n", 671 | " \"\"\"\n", 672 | " Programmer 角色类,继承自 Role 基类\n", 673 | " \"\"\"\n", 674 | "\n", 675 | " name: str = \"cheems\"\n", 676 | " profile: str = \"Programmer\"\n", 677 | "\n", 678 | " def __init__(self, **kwargs):\n", 679 | " \"\"\"\n", 680 | " 初始化 Programmer 角色\n", 681 | " \"\"\"\n", 682 | " super().__init__(**kwargs) # 调用基类构造函数\n", 683 | " self.set_actions([RequirementsOpt, CodeWrite, CodeRun]) # 为角色配备三个动作\n", 684 | " self._set_react_mode(react_mode=\"by_order\") # 顺序执行\n", 685 | "\n", 686 | " async def _act(self) -> Message:\n", 687 | " \"\"\"\n", 688 | " 定义角色行动逻辑\n", 689 | " \"\"\"\n", 690 | " logger.info(f\"{self._setting}: 准备 {self.rc.todo}\") # 记录日志\n", 691 | " todo = self.rc.todo # 按照排列顺序获取待执行的动作\n", 692 | "\n", 693 | " msg = self.get_memories(k=1)[0] # 获取最相似的一条记忆 (用户输入)\n", 694 | "\n", 695 | " # 优化需求》编写代码》运行代码\n", 696 | " result = await todo.run(msg.content)\n", 697 | "\n", 698 | " # 构造 Message 对象\n", 699 | " msg = Message(content=result, role=self.profile, cause_by=type(todo))\n", 700 | " self.rc.memory.add(msg) # 将运行结果添加到记忆\n", 701 | "\n", 702 | " return msg # 返回最终的 Message\n", 703 | " \n", 704 | "# 运行我们的Agent\n", 705 | "async def main():\n", 706 | " msg = \"如何用python爬取每日新闻数据?要求不使用API,安装包的代码要直接在python代码中运行,而非手动输入cmd;\"\n", 707 | " role = Programmer() # 实例化 Programmer\n", 708 | " logger.info(msg) # 记录日志信息\n", 709 | " result = await role.run(msg) # 得到运行结果\n", 710 | " logger.info(result) # 记录运行结果\n", 711 | "\n", 712 | "asyncio.run(main()) # 异步运行 main 函数" 713 | ] 714 | } 715 | ], 716 | "metadata": { 717 | "kernelspec": { 718 | "display_name": "Python 3", 719 | "language": "python", 720 | "name": "python3" 721 | }, 722 | "language_info": { 723 | "codemirror_mode": { 724 | "name": "ipython", 725 | "version": 3 726 | }, 727 | "file_extension": ".py", 728 | "mimetype": "text/x-python", 729 | "name": "python", 730 | "nbconvert_exporter": "python", 731 | "pygments_lexer": "ipython3", 732 | "version": "3.10.13" 733 | } 734 | }, 735 | "nbformat": 4, 736 | "nbformat_minor": 2 737 | } 738 | -------------------------------------------------------------------------------- /4.HuggfacePaperOSSAgent.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import smtplib 4 | from typing import Any, AsyncGenerator, Awaitable, Callable, Dict, Optional, List 5 | from email.mime.multipart import MIMEMultipart 6 | from email.mime.text import MIMEText 7 | from github import Github 8 | import aiohttp 9 | import discord 10 | from aiocron import crontab 11 | from bs4 import BeautifulSoup 12 | from pydantic import BaseModel, Field 13 | from pytz import BaseTzInfo 14 | import json 15 | 16 | from metagpt.actions.action import Action 17 | from metagpt.logs import logger 18 | from metagpt.roles import Role 19 | from metagpt.schema import Message 20 | 21 | # 加载环境变量 22 | from dotenv import load_dotenv 23 | load_dotenv() 24 | 25 | # 订阅模块 26 | class SubscriptionRunner(BaseModel): 27 | tasks: Dict[Role, asyncio.Task] = Field(default_factory=dict) 28 | 29 | class Config: 30 | arbitrary_types_allowed = True 31 | 32 | async def subscribe( 33 | self, 34 | role: Role, 35 | trigger: AsyncGenerator[Message, None], 36 | callback: Callable[[Message], Awaitable[None]], 37 | ): 38 | loop = asyncio.get_running_loop() 39 | 40 | async def _start_role(): 41 | async for msg in trigger: 42 | resp = await role.run(msg) 43 | await callback(resp) 44 | 45 | self.tasks[role] = loop.create_task(_start_role(), name=f"Subscription-{role}") 46 | 47 | async def unsubscribe(self, role: Role): 48 | task = self.tasks.pop(role) 49 | task.cancel() 50 | 51 | async def run(self, raise_exception: bool = True): 52 | while True: 53 | for role, task in self.tasks.items(): 54 | if task.done(): 55 | if task.exception(): 56 | if raise_exception: 57 | raise task.exception() 58 | logger.opt(exception=task.exception()).error( 59 | f"Task {task.get_name()} run error" 60 | ) 61 | else: 62 | logger.warning( 63 | f"Task {task.get_name()} has completed. " 64 | "If this is unexpected behavior, please check the trigger function." 65 | ) 66 | self.tasks.pop(role) 67 | break 68 | else: 69 | await asyncio.sleep(1) 70 | 71 | # 定义一个爬虫动作类,继承自Action类 72 | class CrawlAction(Action): 73 | async def run(self, url: str = "https://huggingface.co/papers"): 74 | async with aiohttp.ClientSession() as client: 75 | papers = await self._fetch_papers(url, client) 76 | return json.dumps(papers[:5]) # 获取前5篇Paper信息 77 | 78 | async def _fetch_papers(self, url: str, client: aiohttp.ClientSession): 79 | async with client.get(url) as response: 80 | response.raise_for_status() 81 | html = await response.text() 82 | 83 | soup = BeautifulSoup(html, 'html.parser') 84 | papers = [] 85 | 86 | # 只爬取前5页 87 | for article in soup.select('h3 > a[href^="/papers/"]')[:5]: 88 | paper_info = {} 89 | paper_info['title'] = article.text.strip() 90 | print(article.text.strip()) 91 | paper_info['url'] = "https://huggingface.co" + article['href'].strip() 92 | paper_html = await self._fetch_paper_detail(paper_info['url'], client) 93 | paper_soup = BeautifulSoup(paper_html, 'html.parser') 94 | paper_info['abstract'] = paper_soup.find("section").get_text(separator=' ', strip=True).strip() 95 | papers.append(paper_info) 96 | 97 | return papers 98 | 99 | async def _fetch_paper_detail(self, url: str, client: aiohttp.ClientSession) -> str: 100 | async with client.get(url) as response: 101 | response.raise_for_status() 102 | return await response.text() 103 | 104 | # Actions 的实现 105 | class AnalysisPaper(Action): 106 | def prompt_format(self, paper_info): 107 | question = """# 需求 108 | 您是一名学术论文分析师,旨在为用户提供有见地的、个性化的论文分析。根据上下文,填写以下缺失的信息,生成吸引人并有信息量的标题,确保用户发现与其兴趣相符的论文。 109 | 110 | 关于论文的标题 111 | 论文分析:深入探索 xxx论文的特点和贡献!基于基本内容,如网页链接,了解其背后的研究背景,研究方法,实验结果等信息。 112 | --- 113 | 格式示例 114 | # 论文标题 115 | 116 | ## 论文链接 117 | 118 | xxx 119 | 120 | ## 论文摘要 121 | 122 | xxx 123 | 124 | ## 研究背景 125 | 126 | xxx 127 | 128 | ## 研究方法 129 | 130 | xxx 131 | 132 | ## 实验结果 133 | 134 | xxx 135 | 136 | ## 结论 137 | 138 | xxx 139 | --- 140 | 当前已有信息如下: 141 | 论文标题:{paper_title} 142 | 论文链接:{paper_URL} 143 | 论文摘要:{paper_abstract} 144 | """.format(paper_title=paper_info["title"], paper_URL=paper_info["url"], paper_abstract=paper_info["abstract"]) 145 | return question 146 | 147 | async def run(self, paper_info_list: Any): 148 | paper_summary_list = [] 149 | for paper_info in json.loads(paper_info_list): 150 | paper_info_str = self.prompt_format(paper_info) 151 | summary = await self._aask(paper_info_str) 152 | paper_summary_list.append(summary) 153 | return paper_summary_list 154 | 155 | # 角色设计 156 | class PaperWatcher(Role): 157 | def __init__(self): 158 | super().__init__( 159 | name="cheems", 160 | profile="PaperWatcher", 161 | goal="根据我提供给你的资料生成一个有见地的学术论文分析报告。", 162 | constraints="仅基于提供的论文数据进行分析。", 163 | ) 164 | self.set_actions([CrawlAction(), AnalysisPaper()]) 165 | self._set_react_mode(react_mode="by_order") 166 | 167 | async def _act(self) -> Message: 168 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 169 | todo = self.rc.todo 170 | 171 | msg = self.get_memories(k=1)[0] 172 | result = await todo.run(msg.content) 173 | 174 | new_msg = Message(content=str(result), role=self.profile, cause_by=type(todo)) 175 | self.rc.memory.add(new_msg) 176 | return result 177 | 178 | # 定义一个基于aiocron的定时触发器类 179 | class HuggingfacePapersCronTrigger: 180 | def __init__(self, spec: str, tz: Optional[BaseTzInfo] = None, url: str = "https://huggingface.co/papers") -> None: 181 | self.crontab = crontab(spec, tz=tz) 182 | self.url = url 183 | 184 | def __aiter__(self): 185 | return self 186 | 187 | async def __anext__(self): 188 | await self.crontab.next() 189 | return Message(content=self.url) 190 | 191 | # 邮件回调 192 | async def email_callback(paper_summary_list: List): 193 | gmail_user = os.getenv("QQ_EMAIL_USER") 194 | gmail_password = os.getenv("QQ_EMAIL_PASSWORD") 195 | to = os.getenv("QQ_EMAIL_TO") 196 | 197 | subject = "Huggingface Papers Weekly Digest" 198 | body = "\n\n".join(paper_summary_list) 199 | 200 | msg = MIMEMultipart() 201 | msg['Subject'] = subject 202 | msg['From'] = gmail_user 203 | msg['To'] = to 204 | 205 | msg.attach(MIMEText(body, 'plain')) 206 | 207 | server = smtplib.SMTP('smtp.qq.com', 587) 208 | server.starttls() 209 | server.login(gmail_user, gmail_password) 210 | server.send_message(msg) 211 | server.quit() 212 | print("send success!") 213 | 214 | # 运行入口 215 | async def main(spec: str = "* * * * *", email: bool = True): 216 | callbacks = [] 217 | if email: 218 | callbacks.append(email_callback) 219 | 220 | if not callbacks: 221 | async def _print(msg: Message): 222 | print(msg.content) 223 | 224 | callbacks.append(_print) 225 | 226 | async def callback(msg): 227 | await asyncio.gather(*(call(msg) for call in callbacks)) 228 | 229 | runner = SubscriptionRunner() 230 | await runner.subscribe(PaperWatcher(), HuggingfacePapersCronTrigger(spec), callback) 231 | await runner.run() 232 | 233 | if __name__ == "__main__": 234 | import fire 235 | fire.Fire(main) -------------------------------------------------------------------------------- /4.OSSAgent.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | from typing import Any, AsyncGenerator, Awaitable, Callable, Dict, Optional, List 4 | from github import Github 5 | import aiohttp 6 | import discord 7 | from aiocron import crontab 8 | from bs4 import BeautifulSoup 9 | from pydantic import BaseModel, Field 10 | from pytz import BaseTzInfo 11 | import json 12 | 13 | from metagpt.actions.action import Action 14 | from metagpt.logs import logger 15 | from metagpt.roles import Role 16 | from metagpt.schema import Message 17 | 18 | # 修复 SubscriptionRunner 未完全定义的问题 19 | from metagpt.environment import Environment as _ # noqa: F401 20 | from dotenv import load_dotenv 21 | load_dotenv() # 加载我们配置在.env文件中的环境变量 22 | 23 | # 订阅模块 24 | class SubscriptionRunner(BaseModel): 25 | tasks: Dict[Role, asyncio.Task] = Field(default_factory=dict) 26 | 27 | class Config: 28 | arbitrary_types_allowed = True 29 | 30 | async def subscribe( 31 | self, 32 | role: Role, 33 | trigger: AsyncGenerator[Message, None], 34 | callback: Callable[[Message], Awaitable[None]], 35 | ): 36 | # 异步订阅方法 37 | loop = asyncio.get_running_loop() 38 | 39 | async def _start_role(): 40 | async for msg in trigger: 41 | resp = await role.run(msg) 42 | await callback(resp) 43 | 44 | self.tasks[role] = loop.create_task(_start_role(), name=f"Subscription-{role}") 45 | 46 | async def unsubscribe(self, role: Role): 47 | """取消订阅角色并取消关联的任务""" 48 | task = self.tasks.pop(role) 49 | task.cancel() 50 | 51 | async def run(self, raise_exception: bool = True): 52 | while True: 53 | for role, task in self.tasks.items(): 54 | if task.done(): 55 | if task.exception(): 56 | if raise_exception: 57 | raise task.exception() 58 | logger.opt(exception=task.exception()).error( 59 | f"Task {task.get_name()} run error" 60 | ) 61 | else: 62 | logger.warning( 63 | f"Task {task.get_name()} has completed. " 64 | "If this is unexpected behavior, please check the trigger function." 65 | ) 66 | self.tasks.pop(role) 67 | break 68 | else: 69 | await asyncio.sleep(1) 70 | 71 | # 定义一个爬虫动作类,继承自Action类 72 | class CrawlAction(Action): 73 | async def run(self, url: str = "https://github.com/trending/python?since=weekly"): 74 | # 定义一个异步方法run,用于执行爬虫动作 75 | # URL默认为GitHub上按星标排名的Python项目周榜单 76 | 77 | async with aiohttp.ClientSession() as client: 78 | # 使用aiohttp创建一个会话对象client 79 | async with client.get(url) as response: 80 | # 使用client对象发送GET请求,并使用代理配置 81 | response.raise_for_status() 82 | # 如果响应状态码不是200,则raise_for_status()会抛出HTTPError异常 83 | html = await response.text() 84 | # 获取响应的HTML文本 85 | 86 | soup = BeautifulSoup(html, 'html.parser') 87 | # 使用BeautifulSoup解析HTML文本,生成一个BeautifulSoup对象 88 | 89 | repositories = [] 90 | # 创建一个空列表,用于存储爬取到的仓库信息 91 | g = Github(os.getenv("GITHUB_ACCESS_TOKEN")) 92 | # 使用您的 GitHub 访问令牌创建一个 Github 对象 93 | for article in soup.select('article.Box-row'): 94 | # 使用 CSS 选择器选择所有类名为 Box-row 的 article 标签 95 | repo_info = {} 96 | # 创建一个空字典,用于存储单个仓库的信息 97 | repo_info['name'] = article.select_one('h2 a').text.strip().replace('\n', '').replace(' ', '') 98 | # 获取仓库名称,使用 CSS 选择器选择 h2 标签下的 a 标签,并提取其文本内容 99 | print(repo_info['name']) 100 | repo_info['url'] = "https://github.com"+article.select_one('h2 a')['href'].strip() 101 | # 获取仓库 URL,使用 CSS 选择器选择 h2 标签下的 a 标签,并提取其 href 属性值,并拼接成完整的 GitHub 仓库链接 102 | 103 | # 获取 README.md 文件 104 | try: 105 | # 尝试获取仓库的 README.md 文件 106 | repo = g.get_repo(repo_info['name']) 107 | contents = repo.get_contents("README.md", ref="main") 108 | repo_info['readme'] = contents.decoded_content.decode() 109 | print(repo_info['readme']) 110 | except Exception as e: 111 | # 如果仓库没有 README.md 文件或发生其他错误,则打印错误信息并跳过该仓库 112 | print(f"Error getting README.md file for {repo_info['name'] }: {e}") 113 | repo_info['readme'] = None 114 | continue 115 | 116 | # Description 117 | description_element = article.select_one('p') 118 | repo_info['description'] = description_element.text.strip() if description_element else None 119 | # 获取仓库描述信息,如果不存在则设置为None 120 | 121 | # Language 122 | language_element = article.select_one('span[itemprop="programmingLanguage"]') 123 | repo_info['language'] = language_element.text.strip() if language_element else None 124 | # 获取仓库使用的编程语言,如果不存在则设置为None 125 | 126 | # Stars and Forks 127 | stars_element = article.select('a.Link--muted')[0] 128 | forks_element = article.select('a.Link--muted')[1] 129 | repo_info['stars'] = stars_element.text.strip() 130 | repo_info['forks'] = forks_element.text.strip() 131 | # 获取仓库的星标数和分支数 132 | 133 | # week's Stars 134 | today_stars_element = article.select_one('span.d-inline-block.float-sm-right') 135 | repo_info['week_stars'] = today_stars_element.text.strip() if today_stars_element else None 136 | # 获取仓库在本周新增的星标数,如果不存在则设置为None 137 | 138 | if repo_info.get("readme") != None: 139 | repositories.append(repo_info) 140 | # 将仓库信息添加到列表中 141 | 142 | return json.dumps(repositories)# 使用json.dumps将字典转换为JSON字符串,并存储到字符串中 返回爬取到的仓库信息列表 143 | 144 | # Actions 的实现 145 | class AnalysisOSSRepository(Action): 146 | def prompt_format(self,repo_info): 147 | question = """# 需求 148 | 您是一名 GitHub 仓库分析师,旨在为用户提供有见地的、个性化的仓库分析。根据上下文,填写以下缺失的信息,生成吸引人并有信息量的标题,确保用户发现与其兴趣相符的仓库。 149 | 150 | 关于仓库的标题 151 | 仓库分析:深入探索 xxx项目的特点和优势!基于基本内容,如网页链接,了解其背后的作用,技术栈,实现思路,部署方式等信息。 152 | --- 153 | 格式示例 154 | 155 | ``` 156 | # 项目名称 157 | 158 | ## 项目地址 159 | xxx 160 | ## 仓库介绍 161 | xxx 是一个用于 xxx 的开源项目。它使用 xxx 技术栈实现,采用 xxx 的实现思路。 162 | 163 | ## 特点和优势 164 | - 特点1 165 | - 特点2 166 | 167 | ## 部署和使用 168 | 可以通过 <部署方式,如Docker,本地部署,云服务器> 的方式部署和使用该项目。详细信息可以参考以下链接: 169 | - 项目文档:[name](url) 170 | - 演示页面:[name](url) 171 | - 执行代码: 172 | > pip install ... 173 | ``` 174 | 175 | --- 176 | 当前已有信息如下: 177 | 项目名称:{repository_name} 178 | 项目地址:{repository_URL} 179 | 项目Star:{repository_star} 180 | 项目Fork:{repository_fork} 181 | 项目语言:{repository_language} 182 | 项目readme:{repository_readme} 183 | """.format(repository_name=repo_info["name"], repository_URL=repo_info["url"], repository_star=repo_info["stars"], repository_fork=repo_info["forks"], repository_language=repo_info["language"], repository_readme=repo_info["readme"]) 184 | return question 185 | 186 | async def run(self, repo_info_list: Any): 187 | repo_summary_list = [] 188 | for repo_info in json.loads(repo_info_list): 189 | repository_info = self.prompt_format(repo_info) 190 | summary = await self._aask(repository_info) 191 | repo_summary_list.append(summary) 192 | return repo_summary_list 193 | 194 | # 角色设计 195 | class OssWatcher(Role): 196 | def __init__(self): 197 | super().__init__( 198 | name="cheems", 199 | profile="OssWatcher", 200 | goal="根据我提供给你的资料生成一个有见地的 GitHub 仓库 分析报告。", 201 | constraints="仅基于提供的 GitHub 仓库 数据进行分析。", 202 | ) 203 | self.set_actions([CrawlAction(), AnalysisOSSRepository()]) 204 | self._set_react_mode(react_mode="by_order") 205 | 206 | async def _act(self) -> Message: 207 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 208 | todo = self.rc.todo 209 | 210 | msg = self.get_memories(k=1)[0] 211 | result = await todo.run(msg.content) 212 | 213 | new_msg = Message(content=str(result), role=self.profile, cause_by=type(todo)) 214 | self.rc.memory.add(new_msg) 215 | return result 216 | 217 | # 定义一个基于aiocron的定时触发器类 218 | class GithubTrendingCronTrigger: 219 | def __init__(self, spec: str, tz: Optional[BaseTzInfo] = None, url: str = "https://github.com/trending/python?since=weekly") -> None: 220 | self.crontab = crontab(spec, tz=tz) 221 | self.url = url 222 | 223 | def __aiter__(self): 224 | return self 225 | 226 | async def __anext__(self): 227 | await self.crontab.next() 228 | return Message(content=self.url) 229 | 230 | # discord 回调 231 | async def discord_callback(msg_list: List): 232 | intents = discord.Intents.default() 233 | intents.message_content = True 234 | # client = discord.Client(intents=intents, proxy= os.getenv("GLOBAL_PROXYGLOBAL_PROXY")) # 需要代理 235 | client = discord.Client(intents=intents) # 无需代理 236 | token = os.getenv("DISCORD_TOKEN") 237 | channel_id = int(os.getenv("DISCORD_CHANNEL_ID")) 238 | async with client: 239 | await client.login(token) 240 | channel = await client.fetch_channel(channel_id) 241 | for repo in msg_list: 242 | lines = [] 243 | for line in repo.splitlines(): 244 | if line.startswith(("# ", "## ", "### ")): 245 | if lines: 246 | await channel.send("\n".join(lines)) 247 | lines = [] 248 | lines.append(line) 249 | 250 | if lines: 251 | await channel.send("\n".join(lines)) 252 | 253 | 254 | # 运行入口 255 | async def main(spec: str = "* * * * *", discord: bool = True, wxpusher: bool = True): 256 | callbacks = [] 257 | if discord: 258 | callbacks.append(discord_callback) 259 | 260 | if not callbacks: 261 | async def _print(msg: Message): 262 | print(msg.content) 263 | 264 | callbacks.append(_print) 265 | 266 | async def callback(msg): 267 | await asyncio.gather(*(call(msg) for call in callbacks)) 268 | 269 | runner = SubscriptionRunner() 270 | await runner.subscribe(OssWatcher(), GithubTrendingCronTrigger(spec), callback) # 正式版本 271 | await runner.run() 272 | 273 | if __name__ == "__main__": 274 | import fire 275 | fire.Fire(main) # 使用 fire 库将 main 函数转换为命令行接口的入口点 -------------------------------------------------------------------------------- /4.githubTrending爬取.py: -------------------------------------------------------------------------------- 1 | import aiohttp # 导入 aiohttp 库,用于发送异步 HTTP 请求 2 | import asyncio # 导入 asyncio 库,用于处理异步任务 3 | from bs4 import BeautifulSoup # 导入 BeautifulSoup 库,用于解析 HTML 文档 4 | from github import Github 5 | import os 6 | from dotenv import load_dotenv 7 | load_dotenv() # 加载我们配置在.env文件中的环境变量 8 | 9 | async def fetch_html(url): 10 | # 定义一个异步函数 fetch_html,用于获取 URL 对应的 HTML 内容 11 | async with aiohttp.ClientSession() as session: 12 | # 使用 aiohttp 创建一个会话上下文管理器 13 | async with session.get(url) as response: 14 | # 使用会话对象发送 GET 请求,并在响应对象上使用上下文管理器 15 | return await response.text() 16 | # 返回响应内容的文本格式 17 | 18 | async def parse_github_trending(html): 19 | # 定义一个异步函数 parse_github_trending,用于解析 GitHub Trending 页面的 HTML 内容 20 | soup = BeautifulSoup(html, 'html.parser') 21 | # 使用 BeautifulSoup 解析 HTML 内容,生成一个 BeautifulSoup 对象 22 | 23 | repositories = [] 24 | # 创建一个空列表,用于存储解析后的仓库信息 25 | 26 | g = Github(os.getenv("GITHUB_ACCESS_TOKEN")) 27 | # g = Github("your_access_token") 28 | # 使用您的 GitHub 访问令牌创建一个 Github 对象 29 | for article in soup.select('article.Box-row'): 30 | # 使用 CSS 选择器选择所有类名为 Box-row 的 article 标签 31 | repo_info = {} 32 | # 创建一个空字典,用于存储单个仓库的信息 33 | 34 | repo_info['name'] = article.select_one('h2 a').text.strip().replace('\n', '').replace(' ', '') 35 | # 获取仓库名称,使用 CSS 选择器选择 h2 标签下的 a 标签,并提取其文本内容 36 | print(repo_info['name']) 37 | repo_info['url'] = "https://github.com"+article.select_one('h2 a')['href'].strip() 38 | # 获取仓库 URL,使用 CSS 选择器选择 h2 标签下的 a 标签,并提取其 href 属性值,并拼接成完整的 GitHub 仓库链接 39 | 40 | # 获取 README.md 文件 41 | try: 42 | # 尝试获取仓库的 README.md 文件 43 | repo = g.get_repo(repo_info['name']) 44 | contents = repo.get_contents("README.md", ref="main") 45 | repo_info['readme'] = contents.decoded_content.decode() 46 | print(repo_info['readme']) 47 | except Exception as e: 48 | # 如果仓库没有 README.md 文件或发生其他错误,则打印错误信息并跳过该仓库 49 | print(f"Error getting README.md file for {repo_info['name'] }: {e}") 50 | continue 51 | # Description 52 | description_element = article.select_one('p') 53 | # 使用 CSS 选择器选择 p 标签 54 | repo_info['description'] = description_element.text.strip() if description_element else None 55 | # 获取仓库描述,如果存在 p 标签,则提取其文本内容,否则为 None 56 | 57 | # Language 58 | language_element = article.select_one('span[itemprop="programmingLanguage"]') 59 | # 使用 CSS 选择器选择 itemprop 属性为 programmingLanguage 的 span 标签 60 | repo_info['language'] = language_element.text.strip() if language_element else None 61 | # 获取仓库语言,如果存在该标签,则提取其文本内容,否则为 None 62 | 63 | # Stars and Forks 64 | stars_element = article.select('a.Link--muted')[0] 65 | # 使用 CSS 选择器选择类名为 Link--muted 的 a 标签,并选择第一个元素 66 | forks_element = article.select('a.Link--muted')[1] 67 | # 使用 CSS 选择器选择类名为 Link--muted 的 a 标签,并选择第二个元素 68 | repo_info['stars'] = stars_element.text.strip() 69 | # 获取仓库星标数,提取第一个元素的文本内容 70 | repo_info['forks'] = forks_element.text.strip() 71 | # 获取仓库分支数,提取第二个元素的文本内容 72 | 73 | # week's Stars 74 | today_stars_element = article.select_one('span.d-inline-block.float-sm-right') 75 | # 使用 CSS 选择器选择类名为 d-inline-block 和 float-sm-right 的 span 标签 76 | repo_info['week_stars'] = today_stars_element.text.strip() if today_stars_element else None 77 | # 获取本周星标数,如果存在该标签,则提取其文本内容,否则为 None 78 | 79 | repositories.append(repo_info) 80 | # 将仓库信息添加到列表中 81 | 82 | return repositories 83 | # 返回解析后的仓库信息列表 84 | 85 | 86 | async def main(): 87 | url = "https://github.com/trending/python?since=weekly" 88 | html = await fetch_html(url) 89 | repos = await parse_github_trending(html) 90 | 91 | # 格式化输出仓库信息 92 | format_str = "{:<5} {:<50} {:<10} {:<10} {:<10} {}" 93 | print(format_str.format("Rank", "Name", "Language", "Stars", "Forks", "Description")) 94 | 95 | for i, repo in enumerate(repos, start=1): 96 | print(format_str.format(i, repo["name"], repo["language"], repo["stars"], repo["forks"], repo["description"])) 97 | 98 | if __name__ == "__main__": 99 | asyncio.run(main()) 100 | -------------------------------------------------------------------------------- /5.MetaGPT中Team开发团队.py: -------------------------------------------------------------------------------- 1 | import re 2 | import fire # 新增了招募 3 | from metagpt.actions import Action, UserRequirement 4 | from metagpt.logs import logger 5 | from metagpt.roles import Role 6 | from metagpt.schema import Message 7 | from metagpt.team import Team 8 | import subprocess 9 | # 加载环境变量 10 | from dotenv import load_dotenv 11 | load_dotenv() 12 | 13 | # 需求分析优化Action 14 | class RequirementsOptAction(Action): 15 | PROMPT_TEMPLATE: str = """ 16 | 你要遵守的规范有: 17 | 1.简要说明 (Brief Description) 18 |   简要介绍该用例的作用和目的。 19 |   2.事件流 (Flow of Event) 20 |   包括基本流和备选流,事件流应该表示出所有的场景。 21 |   3.用例场景 (Use-Case Scenario) 22 |   包括成功场景和失败场景,场景主要是由基本流和备选流组合而成的。 23 |   4.特殊需求 (Special Requirement) 24 |   描述与该用例相关的非功能性需求(包括性能、可靠性、可用性和可扩展性等)和设计约束(所使用的操作系统、开发工具等)。 25 |   5.前置条件 (Pre-Condition) 26 |   执行用例之前系统必须所处的状态。 27 |   6.后置条件 (Post-Condition) 28 |   用例执行完毕后系统可能处于的一组状态。 29 |   请优化以下需求,使其更加明确和全面: 30 | {requirements} 31 | """ 32 | 33 | name: str = "RequirementsOpt" 34 | 35 | async def run(self, requirements: str): 36 | prompt = self.PROMPT_TEMPLATE.format(requirements=requirements) 37 | rsp = await self._aask(prompt) 38 | return rsp.strip() # 返回优化后的需求 39 | 40 | # 代码撰写Action 41 | class CodeWriteAction(Action): 42 | PROMPT_TEMPLATE: str = """ 43 | 根据以下需求,编写一个能够实现{requirements}的Python函数,并提供两个可运行的测试用例。 44 | 返回的格式为:```python\n你的代码\n```,请不要包含其他的文本。 45 | ```python 46 | # your code here 47 | ``` 48 | """ 49 | 50 | name: str = "CodeWriter" 51 | 52 | async def run(self, requirements: str): 53 | prompt = self.PROMPT_TEMPLATE.format(requirements=requirements) 54 | rsp = await self._aask(prompt) 55 | code_text = CodeWriteAction.parse_code(rsp) 56 | return code_text 57 | 58 | @staticmethod 59 | def parse_code(rsp): # 从模型生成中字符串匹配提取生成的代码 60 | pattern = r'```python(.*?)```' # 使用非贪婪匹配 61 | match = re.search(pattern, rsp, re.DOTALL) 62 | code_text = match.group(1) if match else rsp 63 | return code_text 64 | 65 | # 代码测试Action 66 | class CodeTestAction(Action): 67 | PROMPT_TEMPLATE: str = """ 68 | 上下文:{context} 69 | 为给定的函数编写 {k} 个单元测试,并且假设你已经导入了该函数。 70 | 返回 ```python 您的测试代码 ```,且不包含其他文本。 71 | your code: 72 | """ 73 | name: str = "CodeTest" 74 | 75 | async def run(self, context: str, k: int = 5): 76 | prompt = self.PROMPT_TEMPLATE.format(context=context, k=k) 77 | 78 | rsp = await self._aask(prompt) 79 | 80 | code_text = CodeWriteAction.parse_code(rsp) 81 | 82 | return code_text 83 | 84 | 85 | 86 | 87 | class CodeReviewAction(Action): 88 | PROMPT_TEMPLATE: str = """ 89 | context:{context} 90 | 审查测试用例并提供一个关键性的review,在评论中,请包括对测试用例覆盖率的评估,以及对测试用例的可维护性和可读性的评估。同时,请提供具体的改进建议。 91 | """ 92 | 93 | name: str = "CodeReview" 94 | 95 | async def run(self, context: str): 96 | prompt = self.PROMPT_TEMPLATE.format(context=context) 97 | 98 | rsp = await self._aask(prompt) 99 | 100 | return rsp 101 | class RA(Role): #需求分析师缩写 102 | name: str = "yake" 103 | profile: str = "Requirement Analysis" 104 | def __init__(self, **kwargs): 105 | super().__init__(**kwargs) 106 | self._watch([UserRequirement]) 107 | self.set_actions([RequirementsOptAction]) 108 | 109 | class Coder(Role): 110 | name: str = "cheems" 111 | profile: str = "Coder" 112 | 113 | def __init__(self, **kwargs): 114 | super().__init__(**kwargs) 115 | self._watch([RequirementsOptAction]) 116 | self.set_actions([CodeWriteAction]) 117 | 118 | class Tester(Role): 119 | name: str = "Bob" 120 | profile: str = "Tester" 121 | 122 | def __init__(self, **kwargs): 123 | super().__init__(**kwargs) 124 | self.set_actions([CodeTestAction]) 125 | # self._watch([SimpleWriteCode]) 126 | self._watch([CodeWriteAction,CodeReviewAction]) # 这里测试一下同时监听两个动作是什么效果 127 | 128 | async def _act(self) -> Message: 129 | logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})") 130 | todo = self.rc.todo 131 | 132 | # context = self.get_memories(k=1)[0].content # use the most recent memory as context 133 | context = self.get_memories() # 获取所有记忆,避免重复检查 134 | 135 | code_text = await todo.run(context, k=5) # specify arguments 136 | msg = Message(content=code_text, role=self.profile, cause_by=type(todo)) 137 | 138 | return msg 139 | 140 | class Reviewer(Role): 141 | name: str = "Charlie" 142 | profile: str = "Reviewer" 143 | 144 | def __init__(self, **kwargs): 145 | super().__init__(**kwargs) 146 | self.set_actions([CodeReviewAction]) 147 | self._watch([CodeTestAction]) 148 | 149 | 150 | 151 | async def main( 152 | idea: str = "撰写一个python自动生成随机人物数据并保存到csv的tkinter程序,用户输入数量,则随机生成人物信息保存csv到当前文件夹下", 153 | investment: float = 3.0, # token限制3美金 154 | n_round: int = 5, # 循环5 轮 155 | add_human: bool = False, # 无需用户参与评审 156 | ): 157 | logger.info(idea) 158 | 159 | team = Team() 160 | team.hire( 161 | [ 162 | RA(), 163 | Coder(), 164 | Tester(), 165 | Reviewer(is_human=add_human), 166 | ] 167 | ) 168 | 169 | team.invest(investment=investment) # 计算成本预算 170 | team.run_project(idea) # 初始化项目 171 | await team.run(n_round=n_round) # 开始循环 172 | 173 | if __name__ == "__main__": 174 | fire.Fire(main) -------------------------------------------------------------------------------- /5.你画我猜.py: -------------------------------------------------------------------------------- 1 | import re 2 | import fire 3 | from metagpt.actions import Action, UserRequirement 4 | from metagpt.logs import logger 5 | from metagpt.roles import Role 6 | from metagpt.schema import Message 7 | from metagpt.team import Team 8 | from dotenv import load_dotenv 9 | from typing import ClassVar 10 | 11 | load_dotenv() 12 | 13 | # 描述Action 14 | class DescribeItem(Action): 15 | PROMPT_TEMPLATE: str = """ 16 | 请根据以下物体词汇生成描述文本: 17 | 可以对物体词汇侧面描写,但是不能直接说明其名称,你的生成内容是让别人猜测的; 18 | 例如: "苹果": "这是一种红色或绿色的水果,圆形,味道甜或酸。" 19 | "桌子": "这是一个家具,有四条腿,用来放置物品。", 20 | 当前如下: 21 | 词汇:{word} 22 | """ 23 | name: str = "DescribeItem" 24 | 25 | async def run(self, word): 26 | prompt = self.PROMPT_TEMPLATE.format(word=word) 27 | res = await self._aask(prompt) 28 | return res 29 | 30 | # 猜测Action 31 | class GuessItem(Action): 32 | PROMPT_TEMPLATE: str = """ 33 | 根据以下描述文本进行猜测物体名称: 34 | 描述:{description} 35 | 例如:描述为:"这是一种红色或绿色的水果,圆形,味道甜或酸。",你需要猜测为: "苹果", 36 | 你的输出格式如下,猜测结果用方括号扩住: 37 | [苹果] 38 | """ 39 | name: str = "Guess" 40 | 41 | async def run(self, description): 42 | prompt = self.PROMPT_TEMPLATE.format(description=description) 43 | result = await self._aask(prompt) 44 | return self.parse_item(result) 45 | 46 | @staticmethod 47 | def parse_item(rsp): 48 | pattern = r'\[(.*?)\]' 49 | match = re.search(pattern, rsp, re.DOTALL) 50 | item = match.group(1) if match else rsp 51 | return item 52 | 53 | class DescriberAgent(Role): 54 | name: str = "Describer" 55 | profile: str = "负责生成物体描述文本的描述者" 56 | def __init__(self, **kwargs): 57 | super().__init__(**kwargs) 58 | self._watch([UserRequirement,GuessItem]) 59 | self.set_actions([DescribeItem]) 60 | 61 | async def _act(self) -> Message: 62 | """ 63 | 描述者动作:根据猜测者的回答修改描述。 64 | """ 65 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 66 | todo = self.rc.todo 67 | 68 | msg = self.get_memories() # 获取所有对话记忆 69 | # logger.info(msg) 70 | prompt = "这是猜测者的返回:{msg},如果这不是正确答案,请修改描述" 71 | describe = await DescribeItem().run(prompt) 72 | logger.info(f'DescriberAgent : {describe}') 73 | msg = Message(content=describe, role=self.profile, cause_by=type(todo)) 74 | 75 | return msg 76 | 77 | class GuesserAgent(Role): 78 | name: str = "Guesser" 79 | profile: str = "负责猜测物体名称的猜测者" 80 | def __init__(self, **kwargs): 81 | super().__init__(**kwargs) 82 | self._watch([DescribeItem]) 83 | self.set_actions([GuessItem]) 84 | async def _act(self) -> Message: 85 | """ 86 | 猜测者动作:根据描述者的描述修改猜测结果。 87 | """ 88 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 89 | todo = self.rc.todo 90 | 91 | msg = self.get_memories() # 获取所有对话记忆 92 | # logger.info(msg) 93 | prompt = "这是描述者的返回:{msg},如何这不是正确答案,请修改结果重新回答" 94 | guess = await GuessItem().run(msg) 95 | logger.info(f'GuesserAgent : {guess}') 96 | msg = Message(content=guess, role=self.profile, cause_by=type(todo)) 97 | 98 | return msg 99 | 100 | async def main(word: str = "猫", idea: str = "鸡你太美", investment: float = 3.0, add_human: bool = False, n_round=5): 101 | logger.info(idea) 102 | team = Team() 103 | team.hire([DescriberAgent(), GuesserAgent()]) 104 | team.invest(investment=investment) 105 | team.run_project(idea) # 初始化项目 106 | 107 | await team.run(n_round=n_round) # 开始循环 108 | 109 | 110 | if __name__ == "__main__": 111 | fire.Fire(main) -------------------------------------------------------------------------------- /5.师生交互多Agent系统.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from metagpt.actions import Action, UserRequirement 4 | from metagpt.logs import logger 5 | from metagpt.roles import Role 6 | from metagpt.schema import Message 7 | from metagpt.environment import Environment 8 | 9 | from metagpt.const import MESSAGE_ROUTE_TO_ALL 10 | # 加载环境变量 11 | from dotenv import load_dotenv 12 | load_dotenv() 13 | 14 | classroom = Environment() 15 | 16 | 17 | class WriteAction(Action): 18 | """ 19 | 学生Agent的撰写作文Action。 20 | """ 21 | name: str = "WriteEssay" 22 | 23 | PROMPT_TEMPLATE: str = """ 24 | 这里是历史对话记录:{msg}。 25 | 请你根据用户提供的主题撰写一篇作文,只返回生成的作文内容,不包含其他文本。 26 | 如果老师提供了关于作文的建议,请根据建议修改你的历史作文并返回。 27 | 你的作文如下: 28 | """ 29 | 30 | async def run(self, msg: str): 31 | """ 32 | 根据用户提供的主题撰写一篇作文,并在收到老师的修改建议后进行修改。 33 | """ 34 | prompt = self.PROMPT_TEMPLATE.format(msg=msg) 35 | 36 | rsp = await self._aask(prompt) 37 | 38 | return rsp 39 | 40 | class ReviewAction(Action): 41 | """ 42 | 老师Agent的审阅作文Action。 43 | """ 44 | name: str = "ReviewEssay" 45 | 46 | PROMPT_TEMPLATE: str = """ 47 | 这里是历史对话记录:{msg}。 48 | 你是一名老师,现在请检查学生创作的关于用户提供的主题的作文,并给出你的修改建议。你更喜欢逻辑清晰的结构和有趣的口吻。 49 | 只返回你的修改建议,不要包含其他文本。 50 | 你的修改建议如下: 51 | """ 52 | 53 | async def run(self, msg: str): 54 | """ 55 | 审阅学生的作文,并给出修改建议。 56 | """ 57 | prompt = self.PROMPT_TEMPLATE.format(msg=msg) 58 | 59 | rsp = await self._aask(prompt) 60 | 61 | return rsp 62 | 63 | 64 | class Student(Role): 65 | """ 66 | 学生角色。 67 | """ 68 | name: str = "cheems" 69 | profile: str = "Student" 70 | 71 | def __init__(self, **kwargs): 72 | super().__init__(**kwargs) 73 | self.set_actions([WriteAction]) # 设置学生的动作为撰写作文 74 | self._watch([UserRequirement, ReviewAction]) # 监听用户要求和老师的审阅动作 75 | 76 | async def _act(self) -> Message: 77 | """ 78 | 学生动作:根据用户要求撰写作文或根据老师的修改建议修改作文。 79 | """ 80 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 81 | todo = self.rc.todo 82 | 83 | msg = self.get_memories() # 获取所有对话记忆 84 | # logger.info(msg) 85 | essay_text = await WriteAction().run(msg) 86 | logger.info(f'student : {essay_text}') 87 | msg = Message(content=essay_text, role=self.profile, cause_by=type(todo)) 88 | 89 | return msg 90 | 91 | class Teacher(Role): 92 | """ 93 | 老师角色。 94 | """ 95 | name: str = "laobai" 96 | profile: str = "Teacher" 97 | 98 | def __init__(self, **kwargs): 99 | super().__init__(**kwargs) 100 | self.set_actions([ReviewAction]) # 设置老师的动作为审阅作文 101 | self._watch([WriteAction]) # 监听学生的撰写作文动作 102 | 103 | async def _act(self) -> Message: 104 | """ 105 | 老师动作:审阅学生的作文并给出修改建议。 106 | """ 107 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 108 | todo = self.rc.todo 109 | 110 | msg = self.get_memories() # 获取所有对话记忆 111 | review_text = await ReviewAction().run(msg) 112 | logger.info(f'teacher : {review_text}') 113 | msg = Message(content=review_text, role=self.profile, cause_by=type(todo)) 114 | 115 | return msg 116 | 117 | class Student(Role): 118 | """ 119 | 学生角色。 120 | """ 121 | name: str = "cheems" 122 | profile: str = "Student" 123 | 124 | def __init__(self, **kwargs): 125 | super().__init__(**kwargs) 126 | self.set_actions([WriteAction]) # 设置学生的动作为撰写作文 127 | self._watch([UserRequirement, ReviewAction]) # 监听用户要求和老师的审阅动作 128 | 129 | async def _act(self) -> Message: 130 | """ 131 | 学生动作:根据用户要求撰写作文或根据老师的修改建议修改作文。 132 | """ 133 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 134 | todo = self.rc.todo 135 | 136 | msg = self.get_memories() # 获取所有对话记忆 137 | # logger.info(msg) 138 | essay_text = await WriteAction().run(msg) 139 | logger.info(f'student : {essay_text}') 140 | msg = Message(content=essay_text, role=self.profile, cause_by=type(todo)) 141 | 142 | return msg 143 | 144 | class Teacher(Role): 145 | """ 146 | 老师角色。 147 | """ 148 | name: str = "laobai" 149 | profile: str = "Teacher" 150 | 151 | def __init__(self, **kwargs): 152 | super().__init__(**kwargs) 153 | self.set_actions([ReviewAction]) # 设置老师的动作为审阅作文 154 | self._watch([WriteAction]) # 监听学生的撰写作文动作 155 | 156 | async def _act(self) -> Message: 157 | """ 158 | 老师动作:审阅学生的作文并给出修改建议。 159 | """ 160 | logger.info(f"{self._setting}: ready to {self.rc.todo}") 161 | todo = self.rc.todo 162 | 163 | msg = self.get_memories() # 获取所有对话记忆 164 | review_text = await ReviewAction().run(msg) 165 | logger.info(f'teacher : {review_text}') 166 | msg = Message(content=review_text, role=self.profile, cause_by=type(todo)) 167 | 168 | return msg 169 | 170 | async def main(topic: str, n_round=5): 171 | """ 172 | 运行函数,用户输入一个主题,并将主题发布在环境中,然后运行环境。 173 | """ 174 | classroom.add_roles([Student(), Teacher()]) # 向环境中添加学生和老师角色 175 | 176 | classroom.publish_message( 177 | Message(role="Human", content=topic, cause_by=UserRequirement, 178 | send_to='' or MESSAGE_ROUTE_TO_ALL), 179 | peekable=False, 180 | ) 181 | # 发布一条消息,包含用户输入的主题,并将其发送给所有角色 182 | 183 | while n_round > 0: 184 | # self._save() 185 | n_round -= 1 186 | logger.debug(f"max {n_round=} left.") # 输出剩余对话轮数 187 | 188 | await classroom.run() # 运行环境 189 | return classroom.history # 返回对话历史记录 190 | 191 | asyncio.run(main(topic='关于道德和法律的限制范围')) # 运行主函数,输入主题为 "道德和法律的限制范围" -------------------------------------------------------------------------------- /DeepSeek调用测试.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | " Hello! How can I assist you today? If you have any questions or need information on a particular topic, feel free to ask.\n" 13 | ] 14 | } 15 | ], 16 | "source": [ 17 | "from openai import OpenAI\n", 18 | "\n", 19 | "client = OpenAI(api_key=\"sk-6cxxxxxxxxxxxxxxxxxxxxxxxxxxxx74\", base_url=\"https://api.deepseek.com\")\n", 20 | "\n", 21 | "response = client.chat.completions.create(\n", 22 | " model=\"deepseek-chat\",\n", 23 | " messages=[\n", 24 | " {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n", 25 | " {\"role\": \"user\", \"content\": \"Hello\"},\n", 26 | " ],\n", 27 | " stream=False\n", 28 | ")\n", 29 | "\n", 30 | "print(response.choices[0].message.content)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "temperature 参数默认为 1.0。\n", 38 | "\n", 39 | "对于 deepseek-coder,我们建议您使用默认 temperature 值(1.0)。\n", 40 | "对于 deepseek-chat,我们建议您根据如下表格,按使用场景设置 temperature。\n", 41 | "\n", 42 | "场景\t温度\n", 43 | "\n", 44 | "代码生成/数学解题   \t0.0\n", 45 | "\n", 46 | "数据抽取/分析\t0.7\n", 47 | "\n", 48 | "通用对话\t1.0\n", 49 | "\n", 50 | "翻译\t1.1\n", 51 | "\n", 52 | "创意类写作/诗歌创作\t1.25" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [] 61 | } 62 | ], 63 | "metadata": { 64 | "kernelspec": { 65 | "display_name": "Python 3", 66 | "language": "python", 67 | "name": "python3" 68 | }, 69 | "language_info": { 70 | "codemirror_mode": { 71 | "name": "ipython", 72 | "version": 3 73 | }, 74 | "file_extension": ".py", 75 | "mimetype": "text/x-python", 76 | "name": "python", 77 | "nbconvert_exporter": "python", 78 | "pygments_lexer": "ipython3", 79 | "version": "3.10.13" 80 | } 81 | }, 82 | "nbformat": 4, 83 | "nbformat_minor": 2 84 | } 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MetaGPT-Learn 2 | 这个仓库主要用于记录以MetaGPT为基础的Agent开发理论学习记录 3 | -------------------------------------------------------------------------------- /data/tutorial_docx/2024-05-16_18-22-02/.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qianyouliang/MetaGPT-Learn/1598cc97f435542f18d4bb29a4f35160fceb1d33/data/tutorial_docx/2024-05-16_18-22-02/.md -------------------------------------------------------------------------------- /requirement.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | discord 3 | aiocron 4 | beautifulsoup4 5 | pydantic 6 | pytz 7 | PyGithub 8 | fire 9 | metagpt -------------------------------------------------------------------------------- /test.md: -------------------------------------------------------------------------------- 1 | # Git 工作流 2 | 3 | Git 提供了多种工作流来适应不同的开发环境和团队规模。以下是四种常见的 Git 工作流: 4 | 5 | ## 集中式工作流 6 | 7 | 集中式工作流是一种简单的工作流,它使用一个中央仓库作为所有开发者的交互点。这种工作流适合小型团队或项目,它类似于传统的集中式版本控制系统。 8 | 9 | ### 工作原理 10 | 11 | 1. 开发者克隆中央仓库并进行开发。 12 | 2. 定期将更改推送到中央仓库。 13 | 3. 如果有冲突,开发者需要解决冲突后再推送。 14 | 15 | ## 功能分支工作流 16 | 17 | 功能分支工作流通过为每个新功能创建独立的分支来管理开发。这种工作流鼓励频繁的代码审查和协作。 18 | 19 | ### 工作原理 20 | 21 | 1. 从主分支创建一个新的功能分支。 22 | 2. 在功能分支上进行开发。 23 | 3. 完成后,发起一个拉取请求(Pull Request)。 24 | 4. 团队成员审查代码并提供反馈。 25 | 5. 合并功能分支到主分支。 26 | 27 | ## Gitflow 工作流 28 | 29 | Gitflow 工作流是一种更复杂的工作流,它定义了严格的分支模型来支持复杂的发布流程。这种工作流适合需要频繁发布和维护多个版本的项目。 30 | 31 | ### 工作原理 32 | 33 | 1. 主分支(master)用于存储生产环境的代码。 34 | 2. 开发分支(develop)用于集成所有新功能。 35 | 3. 为每个新功能或修复创建一个短期分支。 36 | 4. 完成开发后,将短期分支合并到开发分支。 37 | 5. 准备发布时,从开发分支创建一个发布分支。 38 | 6. 发布分支完成后,合并到主分支和开发分支。 39 | 7. 为紧急修复创建一个热修复分支,完成后合并到主分支和开发分支。 --------------------------------------------------------------------------------