{ "cells": [ { "cell_type": "code", "execution_count": 16, "id": "18e71e02", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "北京今天是晴天,气温 32°C,湿度 45%,天气不错,很适合出行哦!\n", "\n", "另外帮你算好啦,356 × 128 的结果是 **45568**。\n" ] } ], "source": [ "import os\n", "from langchain_openai import ChatOpenAI\n", "from langchain_core.tools import tool\n", "from langchain.agents import create_agent\n", "from dotenv import load_dotenv\n", "\n", "load_dotenv()\n", "\n", "\n", "model = ChatOpenAI(\n", " model=os.getenv('QWEN_MODEL'),\n", " api_key=os.getenv('QWEN_API_KEY'),\n", " base_url=os.getenv('QWEN_API_BASE')\n", ")\n", "\n", "# 第二步。定义工具 (只有两个,一清二楚)\n", "\n", "@tool\n", "def get_weather(city: str) -> str:\n", " \"\"\"查询指定城市的实时天气。\n", "\n", " 当用户问\"某地天气怎么样\"、\"热不热\"、\"要不要带伞\"时调用。\n", "\n", " Args:\n", " city: 城市名称,例如\"北京\"、\"上海\"、\"深圳\"\n", " \"\"\"\n", " # 模拟天气数据(实际项目中对接真实天气API)\n", " weather_db = {\n", " \"北京\": \"☀️ 晴天,32°C,湿度 45%,适合出行\",\n", " \"上海\": \"🌧️ 小雨,28°C,湿度 80%,建议带伞\",\n", " \"深圳\": \"⛅ 多云,30°C,湿度 65%\",\n", " } \n", " return weather_db.get(city, f\"抱歉,我无法查询到 {city} 的天气信息\")\n", "\n", "@tool\n", "def calculator(expression: str) -> str:\n", " \"\"\"执行数学计算,支持加减乘除和括号。\n", "\n", " 当用户说\"帮我算\"、\"等于多少\"、\"计算一下\"时调用。\n", "\n", " Args:\n", " expression: 数学表达式,例如 \"128 * 456\"、\"2 ** 10\"、\"(88 + 12) / 5\"\n", " \"\"\"\n", " try:\n", " result = eval(expression)\n", " return f\"🧮 {expression} = {result}\"\n", " except Exception as e:\n", " return f\"❌ 计算出错:{e}\"\n", "\n", "# 第三步:组装 Agent\n", "# create_agent 内部自动构建了 Think→Act→Observe 循环\n", "\n", "tools = [get_weather, calculator]\n", "\n", "agent = create_agent(\n", " model=model,\n", " tools=tools,\n", " system_prompt=(\n", " \"你是一个热心肠的生活助手,会查天气、会做算术。\\n\"\n", " \"规则:\\n\"\n", " \"1. 用户问天气 → 调用 get_weather。\\n\"\n", " \"2. 用户要计算 → 调用 calculator。\\n\"\n", " \"3. 一个请求涉及多个工具时,逐个调用,每次观察结果后再决定下一步。\\n\"\n", " \"4. 闲聊类的问候直接回答,不用调工具。\"\n", " ),\n", ")\n", "\n", "# 第四步:测试 Agent\n", "\n", "response = agent.invoke({\n", " \"messages\": [\n", " {\"role\": \"user\", \"content\": \"北京今天天气怎么样?顺便帮我算一下 356 × 128\"}\n", " ]\n", "})\n", "\n", "print(response[\"messages\"][-1].content)\n", "\n" ] }, { "cell_type": "code", "execution_count": 17, "id": "dc9c17e9", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAANgAAAD5CAIAAADKsmwpAAAQAElEQVR4nOydCXwT1fbHz2Tvku57S3fKUmRRFhWVpUX/CjzgIasgwgMUFBQFBXmIFkRUwAqyqIgIPkEW2RFE2WS3IMVaKFRauoWW7kmapEkm/5OElgBpAWXSO8n90k+YuffOtJn8cu65524ik8kEFEpTIwAKhQCoEClEQIVIIQIqRAoRUCFSiIAKkUIEIqDcTEle7bljlcoyg7bGaDSwxtqbcgUiYA03X8AAw4CJBRNj/nc9TQgmo+VAYDKxtyaaAJOumwBGYL7WkogX31oSGEty/a+ypJvL3Rxzk7ozQpFA5ikMjXXrmOQDPIShcUQrhRd1BzeXVJXqjKxJIGQ85CKRRCAQgkHH2hYTiASsEUVnk2QWImPCqwQMy5rqijGswXxcrzPLsbkYHtgqqT7RfM86yeEfwBpvvbz+trckglmIQoPepNeyOg2rN7BSmTA0xr3P2GDgD1SIUHyldvdXCk2NwTtA0rar9wOPewGvMcKBTaU5mSqNyhgSJRs4ORz4gKsLcWNqYXGeJjpR3uc/fLIfd0NZkX7nqiJNtaHboOBWnTyBbFxaiJ/PuCyVCl94Nwqcl8zjqsNbipu19Ow9huhvmusK8atZOeGx7v832tkMoV2+mpXbsZdvuye8gVRcVIifT78c106ePCwQXIYv/5sTFCHr91IoEIkrxhFXzc5tluDuUipExs2NKcnX/rqlDIjE5YS4/XMFhj+eGRMCrse4lJhzRyuBSFxMiEbIv1gzenY0uCZCiExwX/1eLpCHawlxzQd5AREycGH6jg+tURqzTquBMFxLiKoK/ZAp/AjwckdYnNvRHdeAMFxIiNtXKKRuQnAs06dP37ZtG9w7vXr1KiwsBA7o/Z+wmmoDEIYLCbE4TxuV6A6OJTMzE+4dhUJRUVEB3CCWgFgq+HkdWUbRhYRYW8t26ukP3HD06NEXX3zxscce69+//+zZs0tLSzGxY8eORUVFc+bM6d69O56qVKoVK1aMGjXKWuyTTz7RarXWy5OSktatWzdu3Di85NChQ3379sXEfv36vfHGG8ABgWHSq1e0QBKuIsS/zmkEAvAO5qRqvnDhwquvvtqpU6dNmza9+eabFy9efPfdd8GiTnydNWvWwYMH8WD9+vWrV68eOXJkamoqlt+3b98XX3xhvYNYLN6yZUuLFi2WLl3atWtXLICJWKcvXLgQOMAvVKqp1gNJuMp4REVOjVDEADecPXtWJpONGTNGIBCEhIS0bt06Ozv79mIjRoxAyxcTE2M9TU9PP3bs2OTJk/GYYRhvb++pU6eCQwiNlp0/VQUk4SpC1KiMjIArIbZv3x4r2ddee61Lly5PPPFEs2bNsIa9vRiavePHj2PFjSbTYDA3F/z8/OpzUb7gKPwCJSaWrK5dV6mazUNWOetVb9my5eLFiwMDA5csWTJgwICJEyeitbu9GOZiXYwFtm7dmpaWNnr0aNtciUQCDkMkvDEKlwxcRYgyTxGnozseffRR9AV37NiB3mFVVRVaR6vNq8dkMm3evHnIkCEoRKy+MUWpVEITUVmsRWcASMJVhBgSIeWuMjp9+jR6e3iARrFPnz7Y1EWRYQjGtoxer9doNEFBQdbT2traw4cPQxNRnK9jHB1RvQOuIsQWnTxrdWythhMtYkWMjeUffvgBg38ZGRnYOkZFhoaGSqVSVN6JEyewIsZ2THR09Pbt2wsKCiorK1NSUtCzrK6uVqvt9LZhSXzFZjXeDTigOFcjcydLiS4UR8Qo7skfy4EDsDmMFe6CBQuwO2T8+PEeHh7oC4pE5oYgNqV/++03tJFoDufNm4eN62effRaDiJ07d37llVfwNDk5GWONt9wwIiICQ4kYdES3Ejigqkwf3IysPncXGhi76dMCVZXhhXeiweVZMuXS2JQ4NzlBZsiFLGLS0GBlBVlR3CZh1yoFVg5EqRBcaoK9b7BY5i7auqyo/8QwuwWMRiMGnO1mYdsCo4B2W5qxsbGrVq0CblhtwW6Wp6cn9hnazUpMTMQeGmiAvAs1D/XwBcJwrTkrRdnazUsLJn0S32CB29w1K/iR4wdvNwt9wfq28H1HacFuFobQ0cW0m4XfGWwt2c3au7YkJ0P50odxQBguN3lq3cf5JhaGv9UMXJKlb2QPmBAVFi8GwnC5OSvDpjVTVtSe3EPo1A1OWTU7NyLenUAVgmvO4ntxftzpn8uUJS5WFXxYgG2UfhPCgEhcd4L9sql/JQ8JSejkAS7Amjl5fmGSPv8hd+6iSy85glqMiHX/10RC55zfL76alYNd7c+R7Ra7+iJMq9+7olUbuvxfQIee5C7H8bfZ8llRYU5NQnuvJ0dy1a6/X9Bl6eDo9rJzv1YyQiayhftTz4UIHTgaiyMunVWf2V9RVqT18BKPmhkFhI1vsAsV4nUObbp28XeltsYoEDBucqGHt1guFwvErL72xvMRisDIAtgskikWC/T6G+fWJTQFAmDZW+9vvrZuXJh5hVnLXcUSgb6WvSnJfAxCoXk5UGtC/d2wiEBoXtUTT+vX6rReh3+GwQBapUFVbdSoDZjlEyh5YkBARIIb8AQqxFv5dWtpYbZGU21EzbGsyWi48XwEQhNrvKlzRSgGo02voVUWAgZuH3FWv+Yxy7ICxrLcMQbDxWCw1+lo+4tsJYrpJhY/MvOgVtvfgM1h1KvMTSD3lyZ08GjRkfTVEG+HCtHRTJo0afjw4Y888ghQbKCLuTsag8FgHSFGsYU+EUdDhWgX+kQcDRWiXegTcTR6vV4sJrG3t2mhQnQ01CLahT4RR0OFaBf6RBwNFaJd6BNxNChE6iPeDhWio6EW0S70iTgaKkS70CfiaKgQ7UKfiKOhQrQLfSKOBgPaVIi3Q5+IQzGZTCzLCoV8GKrqWKgQHQqtlxuCPhSHQoXYEPShOBQ64qEhqBAdCrWIDUEfikOhQmwI+lAcChViQ9CH4lCoEBuCPhSHQhsrDUGF6FCoRWwI+lAcCvascLe8LK+hQnQoKETrDrqUW3DFhTopBEKFSCECKkQKEVAhUoiACpFCBFSIFCKgQqQQARUihQioEClEQIVIIQIqRAoRUCFSiIAKkUIEVIgUIqBCpBAB3fDHEQwdOlStVgsEAp1OV1lZGRgYiMcajeann34CigVqER1Bnz59iouLCwsLS0tLDQaDQqHAYy8vL6DUQYXoCAYPHhwVFWWbwjBMt27dgFIHFaIjkEgk/fr1s10ELDIycsiQIUCpgwrRQaDsIiIirMdoDnv27ElnUdlCheggxGLxs88+azWKzZo1GzRoEFBsoEJ0HCi+8PBwNIdJSUnUHN4CnU56E1Wl+oriWoOBq5BW357jDh482KVNv+x0FXCDm4cwIFwqdeOZiaFxxOtczdWe3FNeWapv1sKjpsoAvMVoNBVf0cQkevR6Lhj4AxWimTJF7Z41V/9vVISEb4akIf5KV14+Vz1gYjjDkzdEfURQVxm3rSj810uRTqNCJK6dvGVnnx1fFgFPoEKEUz+VP9KHT7XYXYI+htRdlJelAT5AhQgFF2u8/J1zqTipm/BagRb4gKsLET1kRsjIfZ1TiD6B4hqVEfiAqwuRYTBkU+us7TWMQxl58uZo1UwhAipEChFQIVKIgAqRQgRUiBQioEKkEAEVIoUIqBApRECFSCECKkQKEVAhUoiACpEIRv9ncOqn8xsvs/mH9clPdgEnhQqRQgRUiBQioLP47pktWzes/XblR/M/mzlrSllZaVRUzBtTZlZWVnww/x2D0dCp4yOvT3nbx8cXS9bU1CxKnXf2bJpSWR0dFfv00/3697s+nTk39/L8D2dfyctp377j8yPG2t6/vLxs2fJFGX+ma7XaTp0ewdxmzaLA2aEW8Z4Ri8UqlXL1ms8XfLRsx7aDer1+3vx3ftyzfeWX6/+3dtsfGWe/37DWWnL625OLigrmpCzcsH73E08kfbr4w/MX/gTL9uFvzZgUGBi8etWmF8dNXv/9GhS09RKj0TjljRfPpp+e8trbq1Z+7+vjN/HlUYVFBeDsUCH+HVBJo54fj4bKzc2tS+euCkXhlNdmBAeH+Pn5t2/30F9/XcQyJ04e/eOPs9PemNWqZaK3t89zw0c/8ED7b9Z8gVmHf91fUlL88sQ38JLo6NjJk95EZVvvjJfk5eW+PWNOl86P4t0mvPSal7fP5s3fgbNDhfg3warWeuDu7u7r64eisZ66ubmr1ObJ8zk52TKZLCYmrv6ShOatsrIy8aCwMB+zQkJCren+/gFBQddnb6FBRYv7YIdO1lOGYVDZ6efOgLNDfcS/CUrE7nE9WNvKZG62KShZjaYGD6qrq1CvtllSqcx6gKYRzW2PpI62uVaP07mhQuQKDw8PrfamqZzqGnWAfyAeeHl5WxVZT02N2nqA1hGr+/fnfmKbKxQIwdmhQuSKFgmtsdl7KTureXwLa8r58xnRlpo6JDgUsy5fzo6NjcfT7OyLpaXXrGXi4hI0Gk1QUEh42PU17IoUhT7ezm8RqY/IFZ07PxoWFrFo0fsXsjIxIvPVqmUoxCGDRmLWo492k0gkCxbNRTmiBFPmzkAbab3qoQc744ULFswpLr5aVVW5ddvGlyaM3LNnOzg71CJyhUgkmpuycMXnqRh/QdnFxjafk7IAG86Y5enpOe/91C++WNznX92w1TJ+3OSff/mx/sIP3k/dvmMzqjMz8w9smCcnP/3vfw8FZ4cuwgRLp2aPmBkvcMa6ISutSlVe231QIBAPrZopRECFSCECKkQKEVAhUoiACpFCBFSIFCKgQqQQARUihQioEClEQIVIIQIqRAoRUCFSiIAKkUIEVIgQHOVmMjrnECSBkHGT82N0NxUiMGAqLdKBM1J8RePNk72MqBAhvr2cL9sz3SvqKn1UKw/gA1SI0O5x79JCTdbpanAu9q9XtH3Mx82THx8xHaFtpry8/NA6TVCUm9xX4hcmA5bHz6RWw5YptOdPVT7ePzAm0R14AhUiLFmy5IEHHujevXvmier8izVGFsoVXLmMRoOxRqORyz2BG65dKzUwSpFMF9ZK37pdVHx8vJubG/ABlxai0Wi8cOFCWlraqFGjwCGcP39+3rx5a9euBW6YOXPmrl27BAKBUCj08fGRy+XBwcEJCQlTpkwBsnFdIa5atWrgwIFSqVQmk4GjqK6uzszMfPjhh4EbMjIy3n777aKiG/uFsyzLMExgYOCePXuAYFy0sbJu3TqdTuft7e1IFYJ5jQcv7lSItGnTBqtjFF99ClpHrJ0JVyG4oBB//vlnfE1KSpowYQI4nMLCwmXLlgGXDB48OCAgoP4UhXjkyBEgHtcSYkpKirXaCgoKgqYAq+bjx48Dl6DFjY6OthpFdIIHDBhw4MABIB5XEeLFi+Y1C/FTef7556HpCA8Pf/nll4FjBg0a5OFhjmNHRUXNmDHD+t4JxyUaK9OmTevduzcGaMBlGDp0aGVlpa1riI2zMWPGAKk4uRCVSmVVy7ho+gAAEABJREFUVdWlS5d69OgBBIA+4rZt2yZOnAgOB30SVOfhw4eBSJy5ap49ezaqMCIighAVgkN8xIYICwuzqjArKwvIw2mFuH79+s6dO6MKgSQc4yM2DlbZ7777LhCGE1bNy5cvx9CMwWAQieiie/bZuXPn448/jv0uAmIWQXM2izh9+nSsg8CyPCGQhwPiiHdDnz59PD099+/fn56eDmTgPEI8ePAgvr711lv9+vUDUmlCH/EWsDM6OTl5yZIlZWVlQADOIET0LoYMGSIWm4ci+/oSvdw0CT6iLStXrqytrc3Pz4emhvc+YkFBAfZoYZUXFxcHlL8FxhZGjx69YcOGJvRneGwRdTrdCy+8gI0SmUzGFxUS4iPegre3d2pqKvYE4sOEJoLHQjxx4sTUqVOxXxX4Azk+4i1ERkb26tULv9vffPMNNAX8EyJ+aydNmoQH3bp1a9OmDfAK0nzEW8AeavyqYGsaHA7/fMSUlBT87j7yyCNA4Ybc3FysZ9BxxCobHAWfLOLq1avx9Z133uGvCsn0EW/B6u2MGDHi8uXL4Ch4I0SsiDt06AA8h1gf8XZ27NiBXjg4Ch5UzadPn37ooYfAKeB6zgoXLFiwABuFwDFEW0SlUtmzZ09/f39wFries8IFSUlJb775JnAMuRZRpVIVFRWFhITghwfOQhOOR/wnWBsuCoUiNDQUuIFQi7hu3bozZ84kJCQ4kwoRuVyO7wv4hrX5/OmnnxYXFwM3EDpQCns/yRmhdB/B79WKFSuwe5dlWQfPZP2HYPj26tWrwcHBwA2EVs1YL6MQ3d15s3TLvfL1118//fTT6HgAxQJd+6bJGD58+HfffQc8oaysDA25y/mI2OO5YcMGcGqsKszLywM+sHjx4t9//x04g1AhajQaDLmBC3Dw4EEMlALxiEQiTqO5hFbNarUaLH3w4AJ88MEHM2bMANeG+oikgF1/xPahYxzxypUrbdu2Bc4gtGpGB3HNmjXgSmDE6qeffgIi2bVrl3XxKu4gVIharRa/heBKDB48GLs0gUjEYjH2tQKXEFo119TUYMjX05OrJX5JBlvTGNkBF4NQi4ihbNdUIeLv7799+3YgBqPR6IB1PgkVIjoly5cvB5fkqaeeCg8PB2I4e/bsli1bgGMIFaJOp6uoqABXxRqxmzVrFhAA+kjDhg0DjiHUR8TGCnYoOdnQm3vl1KlTGDQZNGgQuAA0jkg0RUVF1qV8mhB0WLt37861USC0asaOr48//hhcHqsKm3A1H+ziWrRokQOqJkKFqNfry8vLgWJh2bJlGzdutE1JTk4Gh1BZWTlt2jTgHkKrZnQQsb0il8uBYgGfhkqlwpCWVCrt3bu3QqF45pln5s6dC84CoSO0JRaAUofUQteuXb29vUtKSgQCAUZV0Fz5+PgAl+zduzcuLi4+Ph44htCqGRuMhAQviMLPzw9VaD0uKytzwE4+GM11zJQGQoWIsStXjiPaBZssWCPXn2JlvW/fPuAS9NRHjRrlmHXICfUR8RFoNBoXjyPaMnDgwJycHLBsaVafGBwcvHTpUn6th9YQhFpEsVhMVWjL5s2bhw4d2rx5cwzoMAyD/b9g3p35Gqfbmx0/fvyXX34Bh0CoRczMzFy5ciVGsIByMxkZGWlpaSgR9BGry3WhIZGpqanADQsWLMDm0T8crusbJL6bYmQJcezYsRikwD8JXzGOiFUPOos1NTVcj8rkHcd3lWccr3T3YnQ1Ruvi4VxgZFn0BBj4+/iGSK9kquLay7v28Zf7NhaiISt807p162+//bbeDSooKMDXwMBAoNiwc6UiKNK9/8QomYcQiMfEQsW12o2pBc9OjvDyb1BvZPmII0aMuL2N1rlzZ6DUsePLoojmnq26ePNChQgjAL9gyaDXozem5qurjQ0VI0uIQUFB2G1gm+Lv7//cc88BxcJf59RyPwnWdMBDegwNPb6zwT1diGs1Dxs2zNYotm/fPiEhASgWivO0Ehk/DOHteAdILmeoGsolTogYtenbt691ww/sSBg5ciRQ6tBpWL8QPi3dZItEJghq5lbTQO1MYhyx3ii2sQCUOjRKg9FgBN5SrtA2lPWPWs21Gji261pxrk5ZpTfUmhgBwxpNjDkixKDCGYwNsSb8D8wBInMuNqAEQmDrniS6sZhy/dhyFWP+D5OY7tHz9BFGiVC8YnqO+Sa24H0Zxpp48x0sd7EWvv5L694kvksBI5YK3DwFUS08Hn7GDyiE8TeFuOeb4rwLar2OFYiEQqFAIBFK5SgKxgQmpk5TeIz/UB8m8ytj2TPv+ikWZMxF4EYQ03LCQL0kpVZF1l9+I95pTTPduKr+BpZfeGu6+U2KhCwLxlpjRbHhWkH5b/vKZB6i1p28uvZznkWR+c49C/HHr4sv/6kSChl5oGd4Ii8/SFRkfkZZ+tGq9COVD/bwe/gZoveRdBHuTYifz8CKEqIeCPUMkgJvEUqE0Q8G4UHJX1VnDpRnnqgakxINlCblbhsrBZc0S6ZkywM9WnaP5LUKbQmK827dM5oRiZa/5bidbSh2uSshVl0zbFtR1DopJqyVEzpVMZ1CQ5oHLZv6F1CajjsLMTu95n8fXUlMjhbyNZJ6Z3zD3WI6Ry6lWmw67izEvWsUzbtEgrPjJhcERPmuoHV0E3EHIX7+dg76hWIPJ9xp4naC472xHbPu4wKgOJzGFHZwUylrMEW2c6FRWM0fjSgt0ipyaoHiWBoTYsaxyoBobmcrEojc333PGgVQHEuDQjy6vQw75QJjHLd19D1x9o+fp87qolLf/5l+0Q8Fqyr1ynIWKBb6/zt5zdqVwDENCvFCmtLdh68DPf4hYqnIaYzieynTd/+4DYinQSFqVIaQeBftivUMdL9WqAWnICsrE/iA/S6+8ydVwICbN1ezcnLzzv10YGV+Qaanh2+rFo892WOsTGbeUuXoiY37Dq2aMGb5mvUziksuhwbHP/HosE4P9rFetXPPkrT03VKJe4e2TwUFcBhRCov3rSx0hu2GeiR1xNePF8xZvuKTHdsO4vHRo4e+WfPFlbwcb2+f+PgWr056Kzj4+n6AjWRZMZlMm39Yt3fvzvyCK1GRMR07Pjxm9AThfQov27eIuefVQjFX86pKy/I/Xz1Jr9e9Mn7lqOEfKoovLV81wWg0YJZQJNZolFt3LRjc/+2PU060bdNzw9a5FZVXMevYqc3HTm36d+9pr774tb9v2L4DXwFnCCTmyWtZaWrgOXt2H8XXaVNnWVWYdvrkO+9Oe/LJ3hvW7549a35xsSJ18XxryUay6vnhh/Xf/m/VswOHr/9uZ9++A3ft3rr++/u2BYl9ISrL9ULO5vedSd8jEopfGPZhcGB0SFDsoH4zCxVZGecPWXONRn2vHmOjmj3AMEzH9r3xW1iouIjpR45vaJuYhNJ0d/dCGxkf2xG4hBEISvI14Fys+nr5E4/3RCWhzUtMbDtxwusnThy5YKm7G8mqJ/3cmRYtWj/1VB8fH98+vQcs/Wx1l85d4T5hX4gGA8twNngb6+VmEa09PK4Hhvx8Q/39InKunK0vEBmeaD1wdzMv9qDRKlGOpeX5wUEx9WUiwloCpzCmGrUBnIvLly+1bJlYf9oioTW+XrjwZ+NZ9bRp0+706ZMffZyyZ++Oquqq8LCI+Pj7Np3Ivt0zj3QGrtBoVfmFmRh8sU2sVpbZ/PZb53RrdWqWNUqlN7ZvlkjcgEsYYISMU/UnqVQqnU4nld6IhFi3w66pUTeSZXsHtJfu7h5Hjx368KP3RCJR9+69Xhw3OSDg/vR32BeiWCoWAFf2QC73j4lq/1TP8baJHh6NBSxlUg+BQKjX32jJ6mprgEvQBvNl4vBdYl1dTqu94W+oLTrz9wtoJMv2Dug4Y42MP7m5l8+cObV6zRdqtWre3E/gfmBfiF5+otIiHXBDWHDz0+m7Y6M71K/ocLXkcqB/Y61gtJG+PqG5eX90q/NJzmcdBS5hWVNIDLdG18GgDWuR0OrPP8/Vp1iPY+OaN5JlewdsLycktIqJiYuOjsUfpUq5a/d923/Ffu0T387TaOCqcsaIDMuy23/8pLZWW3Ltys69ny38bLiiOLvxq9q1Sf4j8wB2qODx/l/XXCnIAM6oVRmBNcW3cweeI5VKAwOD0tJO/H42zWAwDOg/5MjRg5s3r6tWVmPKsuWLHuzQqXl8CyzZSFY9v+zfgy3rY8cOo4OITZlfj+xvk9gO7hP2LWLsA+5YOSmvaeWB979zBZu9U1/57sCva1NXjCq5lhsZkTio/8w7Nj6Su41Wqyu27l747YaZWLP/6+nXvtv4DkcrSBXnVIikTlIvPzd8zNerV5z67di673ZidOZaacn3G9d+tmwhxgg7PvTwuLGvWIs1klXPG6//97OlC2bOeh3MU879sY4e9OwIuE80uBrY6veuGE3CuC6h4HpkHcoPiZL2m0Dce9+9ShGVKI9sydddCjcuzBk6NdLdy86XvMGGYbvHfbRKJ+nmuldqdfp+L7niN7AJaTBs3aGn98m9ZYoLFaEt7c+2rKwqXvCZ/d1c3aSeGp39VU5CAmNfGf8l3D/++35SQ1nYWyO0F5ePjmw7dmSDbb3skwovPwn8k1UBKfdOY/0nHXv5ndxT1pAQ5Z7+r09cazcLWyESiX3nUiC4zz02Df0N5j9Dr5OI7Uw4FAkb2zhDW60dM5/z3Rwot9CoEJN9Mk9W5Zwpjnkw+PZcNDZ+vk28TRyYO2bu599w8XB+eHN3Ad3hxeHcofPg+ZlR2ipNpYLb6DEhFJ4rE4iYAROa/tvlgty5F2vCB3EFf5aAs1N8oUJZrho7JwooTcFddKcKYcJHcRn7csqLnNYuFpwrrSpVvvRhLFCaiLvq1xcK4ZVF8YrM4pzfroLTkXUkX12hHv9+DFCajnsYYPLyQmxLGjL3517NcpINbK+kX0NL7+MjenE+tYVNzL0FU0a/E3Vyb8XZQ5XlhdVucllQcz8PH/61MCsKVGV51Vq1TuYpGvBSs/AEJ1lTitfcc1Svy1O++JP2c+W5I5W5pwstY5kZRmhe7BVfb1q/1ab/8OaFM80Lagow97ab1y/0Wne15X/LUp3Xr7PmWM5sbng93fK/iWEElqU+LZdb7igQYoaQNbCGWgNrZBkB4x0gTR4SHt3GqcbX8Jq/GV7GECP+4EH2WXV2urLqml5TYzQP4qsXornOv/nUZLs+rMkszfrxPXUCNEuIZeouh+vrEAtMYClp1pXpegrqmGXryjN1qrRom2FYE2td1dhkdj1YEIkZsYwRS0TeAW6tOnuFx7voNFmS+af9HPHtPfAHKJR/BqE72FPs4uktFgp53AseEC69fR6IFZdY5stpkLoLuBs5zzVatbGkQOcmty85KkQ+ERor09XwdVGe8qu18e0aHElJhcgnIlu4Y+Pr9/38i+Ni83Hf/wq7DWxwyh+hG4dTGuHwllKDAaJbefqHyQTEz2ioLtNXl6tgVEEAAABhSURBVNbu/14x7v04iaxBB5cKkZdknqj+82R1rZbFjxkIJiTKTVWlj0n0fOxOeytRIfIZExgNRH98GC4W3V1ghgqRQgS0sUIhAipEChFQIVKIgAqRQgRUiBQioEKkEMH/AwAA//8TtfHWAAAABklEQVQDAL9/76s0PI+MAAAAAElFTkSuQmCC", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import Image, display\n", "\n", "# draw_mermaid_png() 生成 Mermaid 格式的流程图 PNG\n", "display(Image(agent.get_graph().draw_mermaid_png()))" ] }, { "cell_type": "code", "execution_count": 18, "id": "5f56431f", "metadata": {}, "outputs": [], "source": [ "import os\n", "import operator\n", "from typing import Annotated, List, Tuple, TypedDict, Union, Literal\n", "\n", "from langchain_community.tools.tavily_search import TavilySearchResults\n", "from langchain_community.chat_models import ChatTongyi\n", "from langchain_core.prompts import ChatPromptTemplate\n", "from langchain.agents import create_agent\n", "from pydantic import BaseModel, Field\n", "\n", "#https://tavily.com/\n", "#uv pip install tavily-python -i https://pypi.tuna.tsinghua.edu.cn/simple\n", "\n", "# ---- 配置区:请替换为你自己的 Key ----\n", "os.environ[\"TAVILY_API_KEY\"] = os.getenv('TAVILY_API_KEY')\n", "DASHSCOPE_API_KEY = os.getenv('QWEN_API_KEY')" ] }, { "cell_type": "code", "execution_count": 19, "id": "5f1f924c", "metadata": {}, "outputs": [], "source": [ "# 初始化搜索工具,max_results 控制每次搜索返回的条数\n", "search_tool = TavilySearchResults(max_results=3)\n", "tools = [search_tool]\n", "\n", "# 规划阶段用推理能力强的 Qwen-Max\n", "planner_llm = ChatTongyi(\n", " model=\"qwen-max\",\n", " temperature=0.1, # 低温度保证规划稳定\n", " api_key=DASHSCOPE_API_KEY,\n", ")\n", "\n", "# 执行阶段可以用更经济的模型,这里用 Qwen-Plus\n", "executor_llm = ChatTongyi(\n", " model=\"qwen-plus\",\n", " temperature=0.01,\n", " api_key=DASHSCOPE_API_KEY,\n", ")\n", "\n", "# 创建执行 Agent—— 它就是一个标准的 ReAct Agent\n", "executor_agent = create_agent(\n", " model=executor_llm,\n", " tools=tools,\n", " system_prompt=\"你是一个执行力很强的助手。请根据给定的任务步骤,准确完成并给出结果。\",\n", ")" ] }, { "cell_type": "code", "execution_count": 20, "id": "3333d5a8", "metadata": {}, "outputs": [], "source": [ "class PlanExecute(TypedDict):\n", " \"\"\"贯穿整个工作流的状态对象\"\"\"\n", " input: str # 用户原始输入\n", " plan: List[str] # 当前计划步骤列表\n", " # past_steps 用 operator.add 做累加——每次节点返回新步骤时自动追加到历史\n", " past_steps: Annotated[List[Tuple[str, str]], operator.add]\n", " response: str # 最终回复(非空时流程结束)\n", "\n", "\n", "class Plan(BaseModel):\n", " \"\"\"规划器输出的结构化计划\"\"\"\n", " steps: List[str] = Field(\n", " description=\"需要顺序执行的步骤列表,每一步必须独立且包含完整上下文\"\n", " )\n", "\n", "\n", "class Response(BaseModel):\n", " \"\"\"直接回复用户的内容\"\"\"\n", " response: str\n", "\n", "\n", "class Act(BaseModel):\n", " \"\"\"\n", " 重规划器的决策输出——要么回复用户,要么给出更新后的计划。\n", " 用 Union 类型确保一次只走一条分支。\n", " \"\"\"\n", " action: Union[Response, Plan] = Field(\n", " description=\"如果任务已完成,返回 Response;如果还需要继续,返回 Plan\"\n", " )" ] }, { "cell_type": "code", "execution_count": 21, "id": "bb88d898", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Step 1: 首先,访问通义灵码、文心快码、CodeGeeX的官方网站或权威评测网站来收集关于这三个代码助手工具在2025年的最新信息。\n", " Step 2: 记录每个工具支持的编程语言种类,并制作一份列表以便后续比较。\n", " Step 3: 查找有关这三个工具在2025年时对于不同编程语言的代码补全准确率的数据或用户反馈,整理成对比表。\n", " Step 4: 调查并记录这些工具的价格策略,包括但不限于订阅费用、是否有免费试用版等,并将其汇总到价格比较表中。\n", " Step 5: 基于收集到的支持语言范围、代码补全准确率以及价格三个维度的信息,分析每个工具的优势与劣势,并据此提出针对不同需求场景下的选型建议。\n" ] } ], "source": [ "# 规划器的系统提示——核心是\"拆得合理、不越界\"\n", "planner_prompt = ChatPromptTemplate.from_messages([\n", " (\n", " \"system\",\n", " \"\"\"你是一个擅长任务分解的规划专家。对于用户提出的目标,请将其拆解为顺序执行的步骤列表。\n", "\n", "规则:\n", "1. 每一步必须自包含——执行者不需要上下文就能理解这步要做什么\n", "2. 不要添加无关步骤,最后一步的结果应该直接导向最终答案\n", "3. 优先使用中文描述步骤\n", "4. 步骤数量控制在 3~6 步,过少说明拆分不到位,过多说明混入了无关操作\"\"\",\n", " ),\n", " (\"placeholder\", \"{messages}\"),\n", "])\n", "\n", "# 将提示词模板和 LLM 拼成一条链,with_structured_output 让 LLM 直接输出 Plan 对象\n", "planner_chain = planner_prompt | planner_llm.with_structured_output(Plan)\n", "\n", "\n", "def plan_step(state: PlanExecute) -> dict:\n", " \"\"\"规划节点:分析用户原始输入,生成执行计划\"\"\"\n", " result = planner_chain.invoke({\"messages\": [(\"user\", state[\"input\"])]})\n", " return {\"plan\": result.steps}\n", "result = planner_chain.invoke({\n", " \"messages\": [(\n", " \"user\",\n", " \"帮我调研一下2025年国内主流代码助手工具(通义灵码、文心快码、CodeGeeX),\"\n", " \"从代码补全准确率、支持语言、价格三个维度做对比,最后给出选型建议。\"\n", " )]\n", "})\n", "\n", "for i, step in enumerate(result.steps, 1):\n", " print(f\" Step {i}: {step}\")" ] }, { "cell_type": "code", "execution_count": 22, "id": "8079dc6f", "metadata": {}, "outputs": [], "source": [ "def execute_step(state: PlanExecute) -> dict:\n", " \"\"\"\n", " 从当前计划中取出第一步,交给执行 Agent 去跑。\n", " 执行完后把 (步骤描述, 执行结果) 追加到 past_steps。\n", " \"\"\"\n", " plan = state[\"plan\"]\n", "\n", " # 把完整计划格式化,让 Agent 知道\"我在做什么、后面还有什么\"\n", " plan_overview = \"\\n\".join(f\" {i+1}. {step}\" for i, step in enumerate(plan))\n", " current_task = plan[0] # 只取第一步\n", "\n", " # 拼装给 Agent 的指令:先展示全貌,再指定当前任务\n", " task_prompt = f\"\"\"以下是完整的执行计划:\n", "{plan_overview}\n", "\n", "现在请你只执行第 1 步,不要做后续步骤:\n", " → {current_task}\n", "\n", "请直接给出这一步的执行结果,不要啰嗦。\"\"\"\n", "\n", " agent_result = executor_agent.invoke({\n", " \"messages\": [(\"user\", task_prompt)]\n", " })\n", "\n", " # 取 Agent 最后一条消息的内容作为这一步的产出\n", " step_output = agent_result[\"messages\"][-1].content\n", "\n", " return {\n", " # 这一步走完后,计划需要弹出已执行的第一项——这个逻辑在 replan_step 里\n", " \"past_steps\": [(current_task, step_output)],\n", " }" ] }, { "cell_type": "code", "execution_count": 23, "id": "d1b0c1c3", "metadata": {}, "outputs": [], "source": [ "replanner_prompt = ChatPromptTemplate.from_template(\"\"\"\n", "你是一个项目进度管控专家。根据以下信息,判断当前任务的状态并做出决策。\n", "\n", "## 用户原始目标\n", "{input}\n", "\n", "## 原始计划\n", "{plan}\n", "\n", "## 已完成的步骤及结果\n", "{past_steps}\n", "\n", "## 决策规则\n", "1. 如果所有步骤已完成且结果充分,直接给出最终答案(使用 Response)\n", "2. 如果还有步骤未执行,返回更新后的计划(使用 Plan),注意:\n", " - 只保留尚未执行的步骤\n", " - 如果已完成步骤的结果表明原计划的后续步骤需要调整,直接修改\n", " - 不要返回已经做过的步骤\n", "3. 如果某个步骤执行失败了,请在计划中补充重试或替代方案\n", "\"\"\")\n", "\n", "replanner_chain = replanner_prompt | planner_llm.with_structured_output(Act)\n", "\n", "\n", "def replan_step(state: PlanExecute) -> dict:\n", " \"\"\"审视执行进度,决定下一步走向\"\"\"\n", " try:\n", " output = replanner_chain.invoke(state)\n", " except Exception:\n", " # structured output 解析失败时的兜底方案:\n", " # 用普通 LLM 调用直接生成最终回复,避免 JSON 格式问题导致整个流程崩溃\n", " fallback_prompt = ChatPromptTemplate.from_template(\"\"\"\n", "## 用户原始目标\n", "{input}\n", "\n", "## 已完成的步骤及结果\n", "{past_steps}\n", "\n", "所有步骤已完成,请根据以上收集到的信息,用中文为用户输出一份完整的调研对比报告和选型建议。\n", "\"\"\")\n", " fallback_chain = fallback_prompt | planner_llm\n", " fallback_result = fallback_chain.invoke({\n", " \"input\": state[\"input\"],\n", " \"past_steps\": state[\"past_steps\"],\n", " })\n", " return {\"response\": fallback_result.content}\n", "\n", " if isinstance(output.action, Response):\n", " # 任务完成,直接返回给用户\n", " return {\"response\": output.action.response}\n", " else:\n", " # 还有步骤要执行,更新计划列表\n", " return {\"plan\": output.action.steps}" ] }, { "cell_type": "code", "execution_count": 24, "id": "eaf11437", "metadata": {}, "outputs": [], "source": [ "from langgraph.graph import StateGraph, START, END\n", "\n", "# ---- 第一步:创建状态图,绑定状态类型 ----\n", "workflow = StateGraph(PlanExecute)\n", "\n", "# ---- 第二步:注册三个核心节点 ----\n", "workflow.add_node(\"planner\", plan_step) # 规划节点\n", "workflow.add_node(\"executor\", execute_step) # 执行节点\n", "workflow.add_node(\"replanner\", replan_step) # 重规划节点\n", "\n", "# ---- 第三步:编排边的流向 ----\n", "workflow.add_edge(START, \"planner\") # 入口 → 规划\n", "workflow.add_edge(\"planner\", \"executor\") # 规划 → 执行\n", "workflow.add_edge(\"executor\", \"replanner\") # 执行 → 重规划\n", "\n", "# ---- 第四步:条件分支——重规划后走哪条路 ----\n", "def should_continue(state: PlanExecute) -> Literal[\"executor\", \"__end__\"]:\n", " \"\"\"如果 response 字段非空,说明重规划器认为任务完成,结束流程\"\"\"\n", " if state.get(\"response\"):\n", " return END\n", " return \"executor\"\n", "\n", "workflow.add_conditional_edges(\"replanner\", should_continue, {\n", " \"executor\": \"executor\",\n", " \"__end__\": END,\n", "})\n", "\n", "# ---- 编译 ----\n", "app = workflow.compile()" ] }, { "cell_type": "code", "execution_count": 25, "id": "27d36ada", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import Image, display\n", "\n", "# xray=True 会展示更多内部细节\n", "display(Image(app.get_graph(xray=True).draw_mermaid_png()))" ] }, { "cell_type": "code", "execution_count": 26, "id": "9addf53e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "==================================================\n", "📍 当前节点: planner\n", " plan: ['调查通义灵码在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '调查文心快码在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '调查CodeGeeX在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比这三个工具。', '基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('调查通义灵码在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '根据最新公开信息(截至2025年),通义灵码:\\n\\n- **代码补全准确率**:未公布具体百分比数值;但官方强调其基于Qwen3-Coder模型(235B总参,22B激活),在SecCodeBench安全基准测试中生成代码安全性全球第一,Java万行漏洞数降低61%,且在主流编程语言AI代码生成占比超30%,表明其上下文理解与生成准确性处于行业领先水平。\\n\\n- **支持的编程语言种类**:官方明确支持**超过130种编程语言**,涵盖Java、Python、Go、TypeScript、JavaScript、C/C++、Rust、SQL、Shell等主流及小众语言,并采用AST感知编码、跨语言对齐等技术增强多语言适配能力。\\n\\n- **使用价格**: \\n - **个人免费版**:基础功能(含行/函数级补全、智能问答、单元测试生成等)完全免费,支持阿里云国际站账号登录; \\n - **企业版**:提供标准版与专属版(支持VPC私有部署、多模型配置、MCP工具集成等),按席位/算力/地域订阅计费,具体定价需联系阿里云销售; \\n - 无公开统一标价,但2025年4月更新强调Qwen3模型“成本大幅下降”,暗示企业版性价比提升。')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " plan: ['调查文心快码在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '调查CodeGeeX在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比这三个工具。', '基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('调查文心快码在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '根据搜索结果,截至2025年:\\n\\n- **代码补全准确率**:未在公开资料中披露具体数值(如百分比或基准测试得分),但IDC评测指出其“位居国内代码生成产品评估第一”,且实测显示其在中文语境、跨文件/工程级上下文理解(RAG)、业务逻辑调用(如自动识别并调用 `UserScoreService`)等方面显著优于竞品,表明实际补全准确率处于行业领先水平。\\n\\n- **支持的编程语言种类**:明确支持 **100+ 种主流语言**,并对国内高频使用的 **Java(Spring Cloud)、C/C++、Go** 进行了深度微调;特别强调对中文注释、中文需求文档及拼音缩写变量的原生理解能力。\\n\\n- **使用价格**:官网(comate.baidu.com)仅展示“企业版”与“个人旗舰版”入口,未公开具体定价;搜索结果中无权威来源披露2025年标准报价(如按用户/月、私有化部署License费等),亦无免费版或基础版价格说明。需联系销售获取定制报价。\\n\\n综上:准确率无量化数据但综合能力获IDC认证第一;语言支持超100种,侧重中文生态与主流企业语言;价格未公开,属商业询价模式。')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " plan: ['调查CodeGeeX在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比这三个工具。', '基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('调查CodeGeeX在2025年的代码补全准确率、支持的编程语言种类以及使用价格。', '- **代码补全准确率**:CodeGeeX在2025年公开报告的HumanEval基准测试得分为**82.3%**(来源:Augment Code对比报告,2025年9月更新)。 \\n- **支持的编程语言种类**:明确支持Python、Java、C++、JavaScript、Go、Rust等主流语言,以及**14+种额外语言**(共超20种),具备跨语言翻译能力(来源:CheckThat.ai产品页)。 \\n- **使用价格**:**完全免费且开源**,支持本地/私有化部署;无官方商业订阅计划,亦无面向个人或企业的付费版本披露(多个信源均未提及收费模式,强调“open-source release”和“self-hosting options”)。')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " plan: ['根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比这三个工具。', '基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比这三个工具。', '| 维度 | GitHub Copilot | Tabnine | Amazon CodeWhisperer |\\n|------|----------------|---------|------------------------|\\n| **代码补全准确率** | 最高,整体准确率优秀,覆盖多样化编程场景;在AWS相关代码上略逊于CodeWhisperer | 良好,随团队训练持续提升;企业版支持私有模型微调 | 优秀,尤其在AWS生态内(如Lambda、CloudFormation)准确率突出;通用场景略低于Copilot |\\n| **支持的语言范围** | 40+ 种语言(含Python、JS/TS、Java、Go、Ruby、C#等主流及小众语言) | 30+ 种语言(覆盖主流语言,对新兴语言支持较快) | 15+ 种语言(聚焦Python、Java、JavaScript、TypeScript、C#、Go等核心语言,AWS SDK深度优化) |\\n| **价格** | 个人版:$10/月 或 $100/年;商业版:$19/用户/月 | 免费基础版;Pro版:$12/用户/月;企业版:按需报价 | 个人版:免费;专业版:$19/用户/月;企业版:定制报价 |')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " plan: ['基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('基于对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。', '由于缺少具体的对比结果(如技术栈、工具、框架或平台的详细对比数据),无法基于实际对比得出针对个人开发者、小型团队和大型企业的选型建议。请提供相关对比结果,以便执行第 1 步。')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " plan: ['根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比通义灵码、文心快码和CodeGeeX这三个工具。', '基于更新后的对比结果,提出对于不同需求用户(如个人开发者、小型团队、大型企业)的选型建议。']\n", "\n", "==================================================\n", "📍 当前节点: executor\n", " past_steps: [('根据收集到的信息,从代码补全准确率、支持的语言范围和价格三个维度对比通义灵码、文心快码和CodeGeeX这三个工具。', '| 维度 | 通义灵码 | 文心快码(Comate) | CodeGeeX |\\n|------------------|----------------------------------------------|---------------------------------------------|-------------------------------------------|\\n| **代码补全准确率** | 高(9/10),上下文理解好,支持类型注解推断 | 中(7/10),算法正确但细节处理略逊于通义灵码 | 中高(7.5/10),算法正确但代码风格一致性一般 |\\n| **支持的语言范围** | Java、Python、Go、C#、C/C++、JavaScript、TypeScript、PHP、Ruby、Rust、Scala、Kotlin 等主流语言(300+语言提及) | 支持主流语言(具体列表未详列,但明确支持Java、Python、JS/TS等) | 支持300+语言,开源、学术背景强,覆盖广泛 |\\n| **价格** | 59元/月(基础版免费) | 59元/月(标准版免费) | 完全免费,无限制 |')]\n", "\n", "==================================================\n", "📍 当前节点: replanner\n", " response: ### 2025年国内三大代码助手工具调研报告\n", "\n", "#### 1. 调研背景\n", "随着AI技术的发展,代码助手工具在提高开发效率、减少错误方面发挥了重要作用。本次调研针对2025年的通义灵码、文心快码(Comate)和CodeGeeX三款代码助手工具,从代码补全准确率、支持语言种类及价格三个维度进行对比分析,并基于此给出选型建议。\n", "\n", "#### 2. 工具概览\n", "\n", "- **通义灵码**:由阿里云推出,基于Q...\n" ] } ], "source": [ "inputs = {\n", " \"input\": (\n", " \"帮我调研2025年国内三大代码助手工具(通义灵码、文心快码、CodeGeeX),\"\n", " \"从代码补全准确率、支持语言、价格三个维度做对比,最后给出选型建议。\"\n", " \"请用中文输出最终结果。\"\n", " )\n", "}\n", "\n", "# stream 模式可以看到每一步的中间输出\n", "for event in app.stream(inputs):\n", " for node_name, node_output in event.items():\n", " print(f\"\\n{'='*50}\")\n", " print(f\"📍 当前节点: {node_name}\")\n", " # 避免打印太长的内容\n", " for key, value in node_output.items():\n", " if isinstance(value, str) and len(value) > 200:\n", " print(f\" {key}: {value[:200]}...\")\n", " else:\n", " print(f\" {key}: {value}\")" ] }, { "cell_type": "code", "execution_count": 29, "id": "9f3414d9", "metadata": {}, "outputs": [], "source": [ "from langchain_core.messages import ToolMessage, AIMessage\n", "from langgraph.prebuilt import ToolNode, tools_condition\n", "from typing import Annotated\n", "from operator import add\n", "from langgraph.checkpoint.memory import MemorySaver\n", "\n", "\n", "# ============================================================\n", "# 定义工具:模拟向外部系统发送消息\n", "# ============================================================\n", "@tool\n", "def send_message(channel: str, content: str) -> str:\n", " \"\"\"向指定渠道发送消息。\n", "\n", " Args:\n", " channel: 发送渠道,\"wechat\"(企业微信)、\"email\"(邮件)、\"sms\"(短信)\n", " content: 消息正文内容\n", " \"\"\"\n", " # 实际生产环境这里会调飞书/钉钉/企微的 API\n", " return f\"📨 已通过 {channel} 发送:{content}\"\n", "\n", "\n", "tools = [send_message]\n", "\n", "# 模型绑定工具\n", "model_with_tools = ChatOpenAI(\n", " model=os.getenv('QWEN_MODEL'),\n", " api_key=os.getenv('QWEN_API_KEY'),\n", " base_url=os.getenv('QWEN_API_BASE'),\n", ").bind_tools(tools)\n", "\n", "\n", "# ============================================================\n", "# 定义状态\n", "# ============================================================\n", "class MsgState(TypedDict):\n", " messages: Annotated[list, add] # add 表示追加而非覆盖\n", "\n", "\n", "# ============================================================\n", "# 定义节点\n", "# ============================================================\n", "def chatbot_node(state: MsgState) -> dict:\n", " \"\"\"LLM 推理节点:决定是否调工具、调哪个工具\"\"\"\n", " response = model_with_tools.invoke(state[\"messages\"])\n", " return {\"messages\": [response]}\n", "\n", "\n", "# 工具执行节点(LangGraph 内置)\n", "tool_node = ToolNode(tools=tools)\n", "\n", "\n", "# ============================================================\n", "# 构建图:chatbot → 条件判断 → tools → chatbot(循环)\n", "# ============================================================\n", "builder = StateGraph(MsgState)\n", "builder.add_node(\"chatbot\", chatbot_node)\n", "builder.add_node(\"tools\", tool_node)\n", "\n", "builder.set_entry_point(\"chatbot\")\n", "builder.add_conditional_edges(\n", " \"chatbot\",\n", " tools_condition, # 内置函数:有 tool_calls → \"tools\",否则 → END\n", " {\"tools\": \"tools\", \"__end__\": END},\n", ")\n", "builder.add_edge(\"tools\", \"chatbot\")\n", "\n", "# 编译 + 断点:在工具节点执行前暂停\n", "memory = MemorySaver()\n", "graph = builder.compile(\n", " checkpointer=memory,\n", " interrupt_before=[\"tools\"], # 👈 工具实际调用前拦截\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.11 (shuheAI)", "language": "python", "name": "shuheai" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.14" } }, "nbformat": 4, "nbformat_minor": 5 }