{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "id": "instructions",
      "metadata": {},
      "source": [
        "# Kaggle + Ollama + Chatbox\n",
        "先选择 GPU T4 x2、开启 Internet，再运行下面的单元格。此临时隧道没有访问认证，不要分享地址。整理版增加了失败检查，未在新会话复跑。"
      ]
    },
    {
      "cell_type": "code",
      "id": "deploy",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "%%bash\n",
        "set -Eeuo pipefail\n",
        "trap 'echo \"运行失败：请查看上方错误，以及 /kaggle/working/ollama.log 和 cf.log。\" >&2' ERR\n",
        "cd /kaggle/working\n",
        "\n",
        "# 先确认当前会话已分配 GPU，并开启 Internet。\n",
        "nvidia-smi\n",
        "apt-get update -qq\n",
        "apt-get install -y -qq zstd pciutils lshw\n",
        "curl -fsSL https://ollama.com/install.sh -o /tmp/install-ollama.sh\n",
        "sh /tmp/install-ollama.sh\n",
        "\n",
        "export CUDA_VISIBLE_DEVICES=0,1\n",
        "export OLLAMA_HOST=127.0.0.1:11434\n",
        "export OLLAMA_ORIGINS=\"*\"\n",
        "export LD_LIBRARY_PATH=\"/usr/lib64-nvidia:/usr/local/cuda/lib64:${LD_LIBRARY_PATH:-}\"\n",
        "\n",
        "if ! curl -fsS http://127.0.0.1:11434/api/version >/dev/null; then\n",
        "  nohup ollama serve > /kaggle/working/ollama.log 2>&1 &\n",
        "fi\n",
        "READY=0\n",
        "for i in {1..60}; do\n",
        "  if curl -fsS http://127.0.0.1:11434/api/version >/dev/null 2>&1; then\n",
        "    READY=1; break\n",
        "  fi\n",
        "  sleep 2\n",
        "done\n",
        "if [ \"$READY\" -ne 1 ]; then\n",
        "  tail -n 30 /kaggle/working/ollama.log\n",
        "  exit 1\n",
        "fi\n",
        "\n",
        "# 与视频一致，先生成临时隧道地址，再下载模型。\n",
        "# 此演示接口没有访问认证，不要公开或分享地址；用完停止会话。\n",
        "curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared\n",
        "chmod +x /usr/local/bin/cloudflared\n",
        "nohup cloudflared tunnel --url http://localhost:11434 --http-host-header=\"localhost:11434\" > /kaggle/working/cf.log 2>&1 &\n",
        "URL=\"\"\n",
        "for i in {1..30}; do\n",
        "  URL=$(grep -o 'https://[-a-z0-9]*\\.trycloudflare\\.com' /kaggle/working/cf.log | head -n 1 || true)\n",
        "  [ -n \"$URL\" ] && break\n",
        "  sleep 2\n",
        "done\n",
        "if [ -z \"$URL\" ]; then\n",
        "  echo \"未取得隧道地址，请查看日志：\"\n",
        "  tail -n 30 /kaggle/working/cf.log\n",
        "  exit 1\n",
        "fi\n",
        "echo \"临时 API 地址：$URL\"\n",
        "echo \"先等下面的模型下载完成，再到 Chatbox 获取模型列表。\"\n",
        "\n",
        "# 保留一条下载命令：不用的行以 # 开头。\n",
        "ollama pull deepseek-r1:32b\n",
        "# ollama pull qwen2.5:7b\n",
        "\n",
        "ollama list\n",
        "echo \"模型下载完成。可以在 Chatbox 中选择模型并提问。\"\n"
      ]
    },
    {
      "cell_type": "code",
      "id": "check",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": [
        "!ollama ps\n",
        "!nvidia-smi\n"
      ]
    }
  ]
}