{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 🌤️ Weather Assistant with openJiuwen (ReAct Agent)\n",
    "本 notebook 展示如何基于 **openJiuwen** 框架,用不到 100 行代码构建一个会调用外部天气 API 的对话助手。\n",
    "整体流程:\n",
    "1. 定义工具(RESTful 天气查询)\n",
    "2. 定义模型、提示词与 Agent 配置\n",
    "3. 创建 ReActAgent\n",
    "4. 单次查询 & 流式对话演示"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0. 环境准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "import os, sys\n",
    "from datetime import datetime\n",
    "\n",
    "# 如需把项目根目录加入 PYTHONPATH\n",
    "sys.path.insert(0, os.path.dirname(os.path.abspath('__file__')))\n",
    "os.environ.setdefault(\"LLM_SSL_VERIFY\", \"false\")\n",
    "\n",
    "# ===== 按需修改 =====\n",
    "# API_BASE = os.getenv(\"API_BASE\", \"\")\n",
    "# API_KEY = os.getenv(\"API_KEY\", \"\")\n",
    "# MODEL_NAME = os.getenv(\"MODEL_NAME\", \"\")\n",
    "# MODEL_PROVIDER = os.getenv(\"MODEL_PROVIDER\", \"\")\n",
    "\n",
    "API_BASE = os.getenv(\"API_BASE\", \"your api base\")\n",
    "API_KEY = os.getenv(\"API_KEY\", \"your api key\")\n",
    "MODEL_NAME = os.getenv(\"MODEL_NAME\", \"your model name\")\n",
    "MODEL_PROVIDER = os.getenv(\"MODEL_PROVIDER\", \"your model provider\")\n",
    "\n",
    "WEATHER_URL = \"your weather service url\"  # 本地 mock 或真实地址"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 定义工具(RESTful 天气查询)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from openjiuwen.core.foundation.tool import RestfulApiCard, RestfulApi\n",
    "\n",
    "def create_tool():\n",
    "    weather_card = RestfulApiCard(\n",
    "            id=\"weather_tool\",\n",
    "            name=\"WeatherReporter\",\n",
    "            description=\"天气查询插件\",\n",
    "            input_params={\n",
    "                \"type\": \"object\",\n",
    "                \"properties\": {\n",
    "                    \"location\": {\"description\": \"地点\", \"type\": \"string\"},\n",
    "                    \"date\": {\"description\": \"日期\", \"type\": \"string\"},\n",
    "                },\n",
    "                \"required\": [\"location\", \"date\"],\n",
    "            },\n",
    "            url=WEATHER_URL,\n",
    "            headers={},\n",
    "            method=\"GET\",\n",
    "        )\n",
    "    weather_tool = RestfulApi(\n",
    "        card=weather_card,\n",
    "    )\n",
    "\n",
    "    return weather_tool"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 定义模型配置"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from openjiuwen.core.foundation.llm import ModelRequestConfig, ModelClientConfig\n",
    "\n",
    "model_config = ModelRequestConfig(\n",
    "    model=MODEL_NAME,\n",
    "    temperature=0.6,\n",
    "    top_p=0.8,\n",
    ")\n",
    "model_client = ModelClientConfig(\n",
    "    client_provider=MODEL_PROVIDER,\n",
    "    api_base=API_BASE,\n",
    "    api_key=API_KEY,\n",
    "    verify_ssl=False\n",
    ")"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 3. 定义提示词"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "def create_prompt_template():\n",
    "    system_prompt = \"你是一个AI助手,在适当的时候调用合适的工作流,帮助我完成任务!注意:只需要调用一次工作流后就进行总结,不要重复调用!\"\n",
    "    return [\n",
    "        dict(role=\"system\", content=system_prompt)\n",
    "    ]"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 4. 创建 ReActAgent"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "from openjiuwen.core.single_agent import AgentCard, ReActAgentConfig, ReActAgent\n",
    "from openjiuwen.core.runner import Runner\n",
    "\n",
    "agent_card = AgentCard(\n",
    "        id=\"react_agent_1234\",\n",
    "        description=\"天气查询助手\",\n",
    "    )\n",
    "prompt_template = create_prompt_template()\n",
    "react_agent_config = ReActAgentConfig(\n",
    "    model_client_config=model_client,\n",
    "    model_config_obj=model_config,\n",
    "    prompt_template=prompt_template\n",
    ")\n",
    "react_agent = ReActAgent(card=agent_card).configure(react_agent_config)\n",
    "tool = create_tool()\n",
    "Runner.resource_mgr.add_tool(tool)\n",
    "react_agent.ability_manager.add(tool.card)"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 单次查询"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "import asyncio\n",
    "\n",
    "async def main():\n",
    "    result = await Runner.run_agent(agent=react_agent,\n",
    "                                    inputs={\"query\": \"查询杭州天气\", \"conversation_id\": \"013\"})\n",
    "    print(result)\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    asyncio.run(main())"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 保存 / 加载 Agent(可选)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "# 保存配置到 json\n",
    "with open(\"weather_agent.json\", \"w\", encoding=\"utf-8\") as f:\n",
    "    f.write(react_agent_config.model_dump_json(indent=2))\n",
    "\n",
    "# 下次直接读取\n",
    "# from openjiuwen.agent.react_agent import load_react_agent_config\n",
    "# agent_config = load_react_agent_config(\"weather_agent.json\")"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7. 小结 & 下一步\n",
    "- ✅ 已演示 **工具定义 → Agent 创建 → 单次/流式调用** 完整闭环\n",
    "- 🚀 下一步可尝试:  \n",
    "  - 把天气服务换成真实 API(如 OpenWeather、和风)  \n",
    "  - 增加记忆(MemoryStore)让 Agent 能追问  \n",
    "  - 用 `@tool` 注解快速叠加更多本地函数 "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}