1 line
16 KiB
JSON
1 line
16 KiB
JSON
{"repo": "bakersean168/python", "files": {"ai-agent/day1-cli-chatbot/main.py": {"503962c2860ddbb8d999dfd6228f934733c66aba": {"t": 1785747381.3460095, "n": 4681, "h": "3a118de43af06ac7", "c": "\"\"\"\nDay 1: CLI Chatbot — OpenRouter 版本\n\n核心思想: Agent = LLM + system instruction + conversation history + loop\n\n这次用 OpenRouter 作为 AI 提供商,格式兼容 OpenAI Chat Completions API。\n好处:一个 API key 访问几百个模型(GPT、Claude、Gemini、Llama...)\n\nSetup:\n 1. 注册 https://openrouter.ai → 获取 API key\n 2. uv add requests python-dotenv\n 3. 在 .env 文件中添加: OPENROUTER_API_KEY=your-key-here\n 4. uv run python main.py\n\"\"\"\n\nimport os\nimport json\nimport requests\nfrom dotenv import load_dotenv\n\n# --- Step 1: 加载 .env 中的 API key ---\nload_dotenv()\n\napi_key = os.environ.get(\"OPENROUTER_API_KEY\")\nif not api_key:\n print(\"Error: 在 .env 文件中设置 OPENROUTER_API_KEY\")\n print(\" 示例: OPENROUTER_API_KEY=sk-or-v1-xxxxxxxx\")\n exit(1)\n\n# --- Step 2: API 配置 ---\n# OpenRouter 兼容 OpenAI 的 Chat Completions 格式\nAPI_URL = \"https://openrouter.ai/api/v1/chat/completions\"\n\n# 选择模型 — 去 https://openrouter.ai/models 查看所有可用模型\n# 免费模型以 \":free\" 结尾,例如:\n# google/gemini-2.0-flash-exp:free\n# meta-llama/llama-3.3-8b-instruct:free\n# deepseek/deepseek-chat-v3-0324:free\nMODEL = \"openai/gpt-oss-120b:free\"\n\n# --- Step 3: System instruction ---\n# 这是 Agent 的\"人格\"和\"规则\"\nSYSTEM_INSTRUCTION = {\n \"role\": \"system\",\n \"content\": (\n \"You are a friendly Python tutor. \"\n \"Keep answers short and clear. \"\n \"Use simple code examples when helpful. \"\n \"Respond in the same language the user uses.\"\n ),\n}\n\n# --- Step 4: 对话历史 ---\n# 列表里每一条都是一个 dict: {\"role\": \"...\", \"content\": \"...\"}\n# role 只有三种: system / user / assistant\nhistory = [SYSTEM_INSTRUCTION]\n\n\ndef chat_stream(messages: list[dict]) -> str:\n \"\"\"\n 调用 OpenRouter API,流式返回响应。\n\n 参数:\n messages: 对话历史列表\n\n 返回:\n 完整的响应文本\n \"\"\"\n headers = {\n \"Authorization\": f\"Bearer {api_key}\",\n \"Content-Type\": \"application/json\",\n }\n\n payload = {\n \"model\": MODEL,\n \"messages\": messages,\n \"stream\": True, # 流式输出\n }\n\n full_response = \"\"\n\n try:\n with requests.post(API_URL, headers=headers, json=payload, stream=True, timeout=(10,30)) as r:\n r.encoding = \"utf-8\"\n # 检查 HTTP 状态码\n if r.status_code != 200:\n print(f\"\\nAPI 错误 (HTTP {r.status_code}): {r.text}\")\n return \"\"\n\n # 处理 SSE (Server-Sent Events) 流式数据\n buffer = \"\"\n done = False\n for chunk in r.iter_content(chunk_size=1024, decode_unicode=True):\n if done:\n break\n buffer += chunk\n\n while True:\n line_end = buffer.find(\"\\n\")\n if line_end == -1:\n break\n line = buffer[:line_end].strip()\n buffer = buffer[line_end + 1 :]\n\n if line.startswith(\"data: \"):\n data = line[6:]\n\n if data == \"[DONE]\":\n done = True\n break\n\n try:\n data_obj = json.loads(data)\n content = data_obj[\"choices\"][0][\"delta\"].get(\"content\")\n if content:\n print(content, end=\"\", flush=True)\n full_response += content\n except json.JSONDecodeError:\n pass\n\n print() # 换行\n return full_response\n except requests.exceptions.RequestException as e:\n print(f\"\\n网络请求失败: {e}\")\n return \"\"\n\n# --- Step 5: 主循环 ---\nprint(f\"Python Tutor Agent (model: {MODEL})\")\nprint(\"输入 'quit' 退出 | 输入 'history' 查看历史 | 输入 'clear' 清空历史\")\nprint(\"-\" * 60)\n\nwhile True:\n user_input = input(\"\\nYou: \").strip()\n\n # 特殊命令\n if user_input.lower() in (\"quit\", \"exit\", \"q\"):\n print(\"Goodbye!\")\n break\n\n if user_input.lower() == \"history\":\n for msg in history:\n if msg[\"role\"] == \"system\":\n continue\n role = \"You\" if msg[\"role\"] == \"user\" else \"Agent\"\n if len(msg[\"content\"]) > 80:\n print(f\" [{role}] {msg['content'][:80]}...\")\n else: \n print(f\" [{role}] {msg['content']}\")\n continue\n\n if user_input.lower() == \"clear\":\n history = [SYSTEM_INSTRUCTION]\n print(\"历史已清空。\")\n continue\n\n if not user_input:\n continue\n\n # 添加用户消息到历史\n history.append({\"role\": \"user\", \"content\": user_input})\n\n # 调用 API,流式输出\n print(\"\\nAgent: \", end=\"\")\n reply = chat_stream(history)\n\n # 添加助手回复到历史\n if reply:\n history.append({\"role\": \"assistant\", \"content\": reply})\n else:\n print(\"(没有收到回复,请重试)\")\n"}, "ffed2d358ced21771290ab7838ba415643afbd83": {"t": 1785772938.079353, "n": 4681, "h": "3a118de43af06ac7", "c": "\"\"\"\nDay 1: CLI Chatbot — OpenRouter 版本\n\n核心思想: Agent = LLM + system instruction + conversation history + loop\n\n这次用 OpenRouter 作为 AI 提供商,格式兼容 OpenAI Chat Completions API。\n好处:一个 API key 访问几百个模型(GPT、Claude、Gemini、Llama...)\n\nSetup:\n 1. 注册 https://openrouter.ai → 获取 API key\n 2. uv add requests python-dotenv\n 3. 在 .env 文件中添加: OPENROUTER_API_KEY=your-key-here\n 4. uv run python main.py\n\"\"\"\n\nimport os\nimport json\nimport requests\nfrom dotenv import load_dotenv\n\n# --- Step 1: 加载 .env 中的 API key ---\nload_dotenv()\n\napi_key = os.environ.get(\"OPENROUTER_API_KEY\")\nif not api_key:\n print(\"Error: 在 .env 文件中设置 OPENROUTER_API_KEY\")\n print(\" 示例: OPENROUTER_API_KEY=sk-or-v1-xxxxxxxx\")\n exit(1)\n\n# --- Step 2: API 配置 ---\n# OpenRouter 兼容 OpenAI 的 Chat Completions 格式\nAPI_URL = \"https://openrouter.ai/api/v1/chat/completions\"\n\n# 选择模型 — 去 https://openrouter.ai/models 查看所有可用模型\n# 免费模型以 \":free\" 结尾,例如:\n# google/gemini-2.0-flash-exp:free\n# meta-llama/llama-3.3-8b-instruct:free\n# deepseek/deepseek-chat-v3-0324:free\nMODEL = \"openai/gpt-oss-120b:free\"\n\n# --- Step 3: System instruction ---\n# 这是 Agent 的\"人格\"和\"规则\"\nSYSTEM_INSTRUCTION = {\n \"role\": \"system\",\n \"content\": (\n \"You are a friendly Python tutor. \"\n \"Keep answers short and clear. \"\n \"Use simple code examples when helpful. \"\n \"Respond in the same language the user uses.\"\n ),\n}\n\n# --- Step 4: 对话历史 ---\n# 列表里每一条都是一个 dict: {\"role\": \"...\", \"content\": \"...\"}\n# role 只有三种: system / user / assistant\nhistory = [SYSTEM_INSTRUCTION]\n\n\ndef chat_stream(messages: list[dict]) -> str:\n \"\"\"\n 调用 OpenRouter API,流式返回响应。\n\n 参数:\n messages: 对话历史列表\n\n 返回:\n 完整的响应文本\n \"\"\"\n headers = {\n \"Authorization\": f\"Bearer {api_key}\",\n \"Content-Type\": \"application/json\",\n }\n\n payload = {\n \"model\": MODEL,\n \"messages\": messages,\n \"stream\": True, # 流式输出\n }\n\n full_response = \"\"\n\n try:\n with requests.post(API_URL, headers=headers, json=payload, stream=True, timeout=(10,30)) as r:\n r.encoding = \"utf-8\"\n # 检查 HTTP 状态码\n if r.status_code != 200:\n print(f\"\\nAPI 错误 (HTTP {r.status_code}): {r.text}\")\n return \"\"\n\n # 处理 SSE (Server-Sent Events) 流式数据\n buffer = \"\"\n done = False\n for chunk in r.iter_content(chunk_size=1024, decode_unicode=True):\n if done:\n break\n buffer += chunk\n\n while True:\n line_end = buffer.find(\"\\n\")\n if line_end == -1:\n break\n line = buffer[:line_end].strip()\n buffer = buffer[line_end + 1 :]\n\n if line.startswith(\"data: \"):\n data = line[6:]\n\n if data == \"[DONE]\":\n done = True\n break\n\n try:\n data_obj = json.loads(data)\n content = data_obj[\"choices\"][0][\"delta\"].get(\"content\")\n if content:\n print(content, end=\"\", flush=True)\n full_response += content\n except json.JSONDecodeError:\n pass\n\n print() # 换行\n return full_response\n except requests.exceptions.RequestException as e:\n print(f\"\\n网络请求失败: {e}\")\n return \"\"\n\n# --- Step 5: 主循环 ---\nprint(f\"Python Tutor Agent (model: {MODEL})\")\nprint(\"输入 'quit' 退出 | 输入 'history' 查看历史 | 输入 'clear' 清空历史\")\nprint(\"-\" * 60)\n\nwhile True:\n user_input = input(\"\\nYou: \").strip()\n\n # 特殊命令\n if user_input.lower() in (\"quit\", \"exit\", \"q\"):\n print(\"Goodbye!\")\n break\n\n if user_input.lower() == \"history\":\n for msg in history:\n if msg[\"role\"] == \"system\":\n continue\n role = \"You\" if msg[\"role\"] == \"user\" else \"Agent\"\n if len(msg[\"content\"]) > 80:\n print(f\" [{role}] {msg['content'][:80]}...\")\n else: \n print(f\" [{role}] {msg['content']}\")\n continue\n\n if user_input.lower() == \"clear\":\n history = [SYSTEM_INSTRUCTION]\n print(\"历史已清空。\")\n continue\n\n if not user_input:\n continue\n\n # 添加用户消息到历史\n history.append({\"role\": \"user\", \"content\": user_input})\n\n # 调用 API,流式输出\n print(\"\\nAgent: \", end=\"\")\n reply = chat_stream(history)\n\n # 添加助手回复到历史\n if reply:\n history.append({\"role\": \"assistant\", \"content\": reply})\n else:\n print(\"(没有收到回复,请重试)\")\n"}, "44eca08827639317c7a96a4b77e21ad2b134559d": {"t": 1785772939.2715352, "n": 4154, "h": "c730495942ecca6b", "c": "\"\"\"\nDay 1: CLI Chatbot — OpenRouter 版本\n\n核心思想: Agent = LLM + system instruction + conversation history + loop\n\n这次用 OpenRouter 作为 AI 提供商,格式兼容 OpenAI Chat Completions API。\n好处:一个 API key 访问几百个模型(GPT、Claude、Gemini、Llama...)\n\nSetup:\n 1. 注册 https://openrouter.ai → 获取 API key\n 2. uv add requests python-dotenv\n 3. 在 .env 文件中添加: OPENROUTER_API_KEY=your-key-here\n 4. uv run python main.py\n\"\"\"\n\nimport os\nimport json\nimport requests\nfrom dotenv import load_dotenv\n\n# --- Step 1: 加载 .env 中的 API key ---\nload_dotenv()\n\napi_key = os.environ.get(\"OPENROUTER_API_KEY\")\nif not api_key:\n print(\"Error: 在 .env 文件中设置 OPENROUTER_API_KEY\")\n print(\" 示例: OPENROUTER_API_KEY=sk-or-v1-xxxxxxxx\")\n exit(1)\n\n# --- Step 2: API 配置 ---\n# OpenRouter 兼容 OpenAI 的 Chat Completions 格式\nAPI_URL = \"https://openrouter.ai/api/v1/chat/completions\"\n\n# 选择模型 — 去 https://openrouter.ai/models 查看所有可用模型\n# 免费模型以 \":free\" 结尾,例如:\n# google/gemini-2.0-flash-exp:free\n# meta-llama/llama-3.3-8b-instruct:free\n# deepseek/deepseek-chat-v3-0324:free\nMODEL = \"openai/gpt-oss-120b:free\"\n\n# --- Step 3: System instruction ---\n# 这是 Agent 的\"人格\"和\"规则\"\nSYSTEM_INSTRUCTION = {\n \"role\": \"system\",\n \"content\": (\n \"You are a friendly Python tutor. \"\n \"Keep answers short and clear. \"\n \"Use simple code examples when helpful. \"\n \"Respond in the same language the user uses.\"\n ),\n}\n\n# --- Step 4: 对话历史 ---\n# 列表里每一条都是一个 dict: {\"role\": \"...\", \"content\": \"...\"}\n# role 只有三种: system / user / assistant\nhistory = [SYSTEM_INSTRUCTION]\n\n\ndef chat_stream(messages: list[str]) -> str:\n \"\"\"\n 调用 OpenRouter API,流式返回响应。\n\n 参数:\n messages: 对话历史列表\n\n 返回:\n 完整的响应文本\n \"\"\"\n headers = {\n \"Authorization\": f\"Bearer {api_key}\",\n \"Content-Type\": \"application/json\",\n }\n\n payload = {\n \"model\": MODEL,\n \"messages\": messages,\n \"stream\": True, # 流式输出\n }\n\n full_response = \"\"\n\n with requests.post(API_URL, headers=headers, json=payload, stream=True) as r:\n # 检查 HTTP 状态码\n if r.status_code != 200:\n print(f\"\\nAPI 错误 (HTTP {r.status_code}): {r.text}\")\n return \"\"\n\n # 处理 SSE (Server-Sent Events) 流式数据\n buffer = \"\"\n for chunk in r.iter_content(chunk_size=1024, decode_unicode=True):\n buffer += chunk\n\n while True:\n line_end = buffer.find(\"\\n\")\n if line_end == -1:\n break\n\n line = buffer[:line_end].strip()\n buffer = buffer[line_end + 1 :]\n\n if line.startswith(\"data: \"):\n data = line[6:]\n\n if data == \"[DONE]\":\n break\n\n try:\n data_obj = json.loads(data)\n content = data_obj[\"choices\"][0][\"delta\"].get(\"content\")\n if content:\n print(content, end=\"\", flush=True)\n full_response += content\n except json.JSONDecodeError:\n pass\n\n print() # 换行\n return full_response\n\n\n# --- Step 5: 主循环 ---\nprint(f\"Python Tutor Agent (model: {MODEL})\")\nprint(\"输入 'quit' 退出 | 输入 'history' 查看历史 | 输入 'clear' 清空历史\")\nprint(\"-\" * 60)\n\nwhile True:\n user_input = input(\"\\nYou: \").strip()\n\n # 特殊命令\n if user_input.lower() in (\"quit\", \"exit\", \"q\"):\n print(\"Goodbye!\")\n break\n\n if user_input.lower() == \"history\":\n for msg in history:\n if msg[\"role\"] == \"system\":\n continue\n role = \"You\" if msg[\"role\"] == \"user\" else \"Agent\"\n print(f\" [{role}] {msg['content'][:80]}...\")\n continue\n\n if user_input.lower() == \"clear\":\n history = [SYSTEM_INSTRUCTION]\n print(\"历史已清空。\")\n continue\n\n if not user_input:\n continue\n\n # 添加用户消息到历史\n history.append({\"role\": \"user\", \"content\": user_input})\n\n # 调用 API,流式输出\n print(\"\\nAgent: \", end=\"\")\n reply = chat_stream(history)\n\n # 添加助手回复到历史\n if reply:\n history.append({\"role\": \"assistant\", \"content\": reply})\n else:\n print(\"(没有收到回复,请重试)\")\n"}}}} |