2025年4月30日水曜日

OpenWebUI に Pipeline を追加する方法

OpenWebUI に Pipeline を追加する方法

概要

Pipeline は簡単に言えば Web アプリで Web アプリ経由で好きな Python スクリプトを実行できるという機能です
今回は Pipeline の初期設定とスクリプトの追加まで紹介します

環境

  • docker 27.3.1
  • Ubuntu 24.04
  • open-webui 0.6.5

open-webui 起動

  • vim compose.yaml
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    ports:
      - "3000:8080"
    environment:
      - WEBUI_AUTH=False
    volumes:
      - open-webui:/app/backend/data
      - ./pipelines:/app/backend/storage/pipelines
    restart: unless-stopped

volumes:
  open-webui:

Pipeline 起動

  • docker run -d -p 9099:9099 -v pipelines:/app/pipelines --name pipelines --restart always ghcr.io/open-webui/pipelines:main

open-webui の画面から pipeline の追加

管理者パネル -> 設定 -> 接続 -> OpenAI API

で起動した Pipeline を追加します
UI から見えるエンドポイントでなければいけないので docker で動かしている場合はホスト側の IP などを指定しましょう

Pipeline のエンドポイントにはデフォルトで認証がありパスワードは 0p3n-w3bu! です

open-webui の画面から pipeline の設定

管理者パネル -> 設定 -> パイプライン

を表示し先ほど追加してエンドポイントがあることを確認します

open-webui の画面から pipeline のスクリプト追加

あとは Github やローカルから Python スクリプトを追加するだけです
例えば Gemini であれば https://github.com/open-webui/pipelines/blob/main/examples/pipelines/providers/google_manifold_pipeline.py を追加します

追加できるスクリプトにはルールがあるので詳細は上記のスクリプトなどを参照してください
入力などは Pydantic 形式で記載したりしなければいけないなどのルールがあります

最後に

open-webui に Pipeline を追加する方法を紹介しました
ここで追加した Pipeline を使ってチャット経由で質問したりすることができます

参考サイト

2025年4月28日月曜日

LiteLLM Proxy を Gemini のカスタムエンドポイントで使用する方法

LiteLLM Proxy を Gemini のカスタムエンドポイントで使用する方法

概要

前回 Azure のカスタムエンドポイントを設定する方法を紹介しました
今回は Gemini flash の設定方法を紹介します

環境

  • docker 27.3.1
  • Ubuntu 24.04
  • litellm-proxy v1.67.0-stable

litellm_config.yaml

model_list:
  - model_name: gemini/gemini-flash
    litellm_params:
      model: gemini/gemini-flash
      api_base: os.environ/GEMINI_API_BASE # runs os.getenv("GEMINI_API_BASE")
      api_key: os.environ/GEMINI_API_KEY # runs os.getenv("GEMINI_API_KEY")
      api_version: ""

docker 起動

docker run --rm \
    -v $(pwd)/litellm_config.yaml:/app/config.yaml \
    -e GEMINI_API_KEY=b4xxx \
    -e GEMINI_API_BASE=https://your-api-endpoint/ai/chat-ai/gemini/flash \
    -p 4000:4000 \
    ghcr.io/berriai/litellm:main-latest \
    --config /app/config.yaml --detailed_debug

カスタムメソッド部の :streamGenerateContent は不要です

動作確認

リクエスト LiteLLM Proxy が互換にしてくれるので Azure のときと同じです

curl --location 'http://0.0.0.0:4000/chat/completions' \
    --header 'Content-Type: application/json' \
    --data '{
    "model": "gemini/gemini-flash",
    "messages": [
        {
        "role": "user",
        "content": "what llm are you"
        }
    ]
}'

レスポンスは以下です

{
  "id": "chatcmpl-2062ec16-2314-4772-a264-6f987407689d",
  "created": 1745811058,
  "model": "gemini-flash",
  "object": "chat.completion",
  "system_fingerprint": null,
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "I am a large language model, trained by Google.\n",
        "role": "assistant",
        "tool_calls": null,
        "function_call": null
      }
    }
  ],
  "usage": {
    "completion_tokens": 12,
    "prompt_tokens": 5,
    "total_tokens": 17,
    "completion_tokens_details": null,
    "prompt_tokens_details": {
      "audio_tokens": null,
      "cached_tokens": null
    }
  },
  "vertex_ai_grounding_metadata": [],
  "vertex_ai_safety_results": [],
  "vertex_ai_citation_metadata": []
}

最後に

LiteLLM Proxy で Gemini flash を動作させる方法を紹介しました
これで Open WebUI のモデルを簡単に変更することができます

2025年4月27日日曜日

ollama で huggingface にあるモデルを動かす方法

ollama で huggingface にあるモデルを動かす方法

概要

GGUF 形式のモデルであれば ollama run で直接使えるようです
自分で Modelfile などを用意してビルドする必要はないようです

環境

  • macOS 15.4.1
  • ollama 0.6.6

コマンド

  • ollama run hf.co/elyza/Llama-3-ELYZA-JP-8B-GGUF

quantization (量子化) 情報を指定したい場合はタグとして指定します

  • ollama run hf.co/bartowski/Llama-3.2-3B-Instruct-GGUF:IQ3_M

最後に

簡単にモデルの切り替えができるので便利です

参考サイト

2025年4月25日金曜日

OpenSora を M2 Mac 上で動作させる方法

OpenSora を M2 Mac 上で動作させる方法

概要

OpenSora はテキスト -> 動画が生成できるオープンソースのモデルです
内部的に xformers を使っているためデフォルトの状態で Mac で使うのはかなり大変です

今回はMLX を使って動作させる方法があるのでその方法を紹介します

環境

  • macOS 15.4.1
  • OpenSora 1.2
  • Python 3.10.12
    • mlx 0.25.0

注意点

今回紹介する記事では OpenSora のバージョンが 1.2 になっています
最新バージョンは 2.0 でまだ MLX では 2.0 に対応していないので注意しましょう
頑張れば 2.0 に対応することもできると思います

OpenSora のサンプルコードのクローン

  • git clone https://github.com/awni/mlx-examples.git
  • cd mlx-examples
  • git switch open_sora

プロジェクト初期化

  • pyenv local 3.10.12
  • python -m venv .venv
  • source .venv/bin/activate
  • pip install -r requirements.txt
  • pip install protobuf sentencepiece

コード修正

一部動作しないので手動で書き換えます

  • vim utils/video_io.py
diff --git a/open_sora/utils/video_io.py b/open_sora/utils/video_io.py
index e18635c..cceb725 100644
--- a/open_sora/utils/video_io.py
+++ b/open_sora/utils/video_io.py
@@ -28,7 +28,7 @@ def save_video(x, save_path=None, fps=8):
 
         for img in x:
             frame = av.VideoFrame.from_ndarray(img, format="rgb24")
-            frame.pict_type = "NONE"
+            frame.pict_type = 0
             for packet in stream.encode(frame):
                 container.mux(packet)

生成

  • python generate.py --prompt "A beautiful smile girl" --resolution 240p

初回はモデルのダウンロードがあるので時間がかかります
全部で 10GB ほどあるので注意しましょう

  • cd .cache/huggingface/hub/models--mlx-community--OpenSora-VAE-v1.2

できたもの

やはり人間は苦手なのかもです
マシンスペックがそもそも低いのもありますが各種チューニング (フレームレートやプロンプトなど) をしっかりやれば OpenSora1.2 でもいい動画が作れるのかもです

最後に

MLX を使って M2 Mac 上で OpenSora を動作させてみました
バージョンが古いので精度的には微妙な感じはします
そのうち本体にマージされて 2.0 対応されれば精度も上がるかもしれません

参考サイト

2025年4月24日木曜日

stable-diffusion-webui-forge を Mac にインストールする

stable-diffusion-webui-forge を Mac にインストールする

概要

前回 SVD を generative-models で試そうとしましたが CUDA 環境が必須だったので動作させることができませんでした
今回は stable-diffusion-webui-forge をインストールしてみます forge の場合 SVD を動かせる環境があるようなので試してみます

環境

  • macOS 15.4.1 (M2 Pro Mac mini)
  • Python 3.10.12
  • stable-diffusion-webui-forge f2.0.1v1.10.1-previous-659-gc055f2d4

stable-diffusion-webui-forge のインストール

  • git clone https://github.com/lllyasviel/stable-diffusion-webui-forge.git
  • cd stable-diffusion-webui-forge
  • pyenv local 3.10.12
  • ./webui.sh

これで必要なライブラリのインストールが始まり UI が起動します

http://127.0.0.1:7860/

画像生成をしたい場合は

モデルをダウンロードし配置すれば普通に画像生成 (txt2img) もできます
以下は SDXL モデルをダウンロードし配置する手順です

モデルが配置できたら UI をリロードしてトップにあるモデルを選択するプルダウンからモデルを選択すれば OK です
あとは適当にプロンプトに入れて Generate しましょう

SVD を使うための準備

どうやら stable-diffusion-webui-forge の最新バージョンには SVD がないようなので手動でインストールします
Python ファイルをダウンロードし所定のパスに配置します

  • wget 'https://github.com/user-attachments/files/16835270/svd.zip'
  • unzip svd.zip
  • cp ~/Downloads/svd/forge_util.py ~/Documents/work/stable-diffusion-webui-forge/modules_forge
  • cp ~/Downloads/svd/stream.py ~/Documents/work/stable-diffusion-webui-forge/modules_forge
  • cp -ipr ~/Downloads/svd/sd_forge_svd ~/Documents/work/stable-diffusion-webui-forge/extensions/
  • ./webui.sh

これで再度起動すると SVD タブが表示されているのが確認できると思います

モデルのダウンロード

https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt/blob/main/svd_xt.safetensors をダウンロードし models/svd に配置しましょう

  • mv ~/Downloads/svd_xt.safetensors ~/Documents/work/stable-diffusion-webui-forge/models/svd

SVD 実行

準備完了です
あとは動画にしたい画像を配置してモデルを選択し一番下にある Generate をクリックします

ちなみにできあがった2秒動画は以下です

これが

上下にしか動いてないですが一応動きました
ところどころブロックノイズっぽいのはパラメータをチューニングすれば変わるのかもしれません

生成までにかかる時間

自分は約2秒の動画作るのに約1時間かかりました
M2 Pro の力でそれくらいなので GPU がいい CUDA 環境であればもっとサクサク作成できるのではと思います

デフォルトだと 1024x576 と解像度が大きいのでこれをもっと下げれば速くなると思います
(512x288 にすれば数分で終わるのでそっちのほうがオススメかもです)
このあたりのパラメータチューニングでも速度をあげられると思います

ただ元画像のサイズと出力動画のサイズが変わるとうまく動画にならないケースがあるのでできれば入力と出力のサイズは同じがいいのかもしれません

トラブルシューティング

RuntimeError: MPS backend out of memory (MPS allocated: 14.61 GB, other allocations: 3.03 GB, max allowed: 18.13 GB). Tried to allocate 630.00 MB on private pool. Use PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.0 to disable upper limit for memory allocations (may cause system failure).

デフォルトだと使用するメモリに制限があるのでメモリの制限をしないようにして起動すれば OK です

  • PYTORCH_MPS_HIGH_WATERMARK_RATIO=0 ./webui.sh

最後に

stable-diffusion-webui-forge で SVD をしてみました
SVD は image -> video はできますが text -> video はまだできないようです

1つの動画を作成するのにかなりの時間がかかるのでもっと長い動画や解像度の高い動画、複数の動画を作成したい場合はかなりのマシンスペックと時間が必要かなと思います

参考サイト

2025年4月23日水曜日

SVD generative-models を M2 Mac にインストールする

SVD generative-models を M2 Mac にインストールする

概要

ただし generative-models が提供しているサンプルコードは CUDA 環境必須なので M2 では動作しません
このページではインストールする方法を紹介します

環境

  • macOS 15.4.1 (M2 Pro Mac mini)
  • Python 3.10.12
  • rust 1.86.0

リポジトリクローン

リポジトリを取得環境を構築します

  • git clone https://github.com/Stability-AI/generative-models.git
  • cd generative-models
  • pyenv local 3.10.12
  • python -m venv .pt2
  • source .pt2/bin/activate

パッケージインストール

そのままだとインストールできないので修正しインストールします

vim requirements/pt2.txt

black==23.7.0
chardet==5.1.0
clip @ git+https://github.com/openai/CLIP.git
einops>=0.6.1
fairscale>=0.4.13
fire>=0.5.0
fsspec>=2023.6.0
invisible-watermark>=0.2.0
kornia==0.6.9
matplotlib>=3.7.2
natsort>=8.4.0
ninja>=1.11.1
numpy>=1.24.4
omegaconf>=2.3.0
open-clip-torch>=2.20.0
opencv-python==4.6.0.66
pandas>=2.0.3
pillow>=9.5.0
pudb>=2022.1.3
pytorch-lightning==2.0.1
pyyaml>=6.0.1
rembg
scipy>=1.10.1
streamlit>=0.73.1
tensorboardx==2.6
timm>=0.9.2
tokenizers==0.11.6
torch==2.0.1
torchaudio>=2.0.2
torchdata==0.6.1
torchmetrics>=1.0.1
torchvision>=0.15.2
tqdm>=4.65.0
transformers==4.19.1
urllib3<1.27,>=1.25.4
wandb>=0.15.6
webdataset>=0.2.33
wheel>=0.41.0
--extra-index-url https://download.pytorch.org/whl/cu118
xformers==0.0.20
gradio
streamlit-keyup==0.2.0
numpy<2.0

内部的に rust もコンパイルで使うのでインストールします
また pytorch だけ先にインストールしないと xformers がインストールできないのでインストールしておきます

  • brew install rust
  • pip install torch==2.0.1
  • pip install -r requirements/pt2.txt

sgm のインストール

おそらく sgm (Stability-AI/generative-models) の略だと思います
これで generative-models が python で使えるようになります
一応学習することもできるので学習データもダウンロードしておきます

  • pip install .
  • pip install -e git+https://github.com/Stability-AI/datapipelines.git@main#egg=sdata

サンプルコード実行

どちらも AssertionError: Torch not compiled with CUDA enabled で動作はしませんが generative-models では主に 2 通りのサンプルコードの実行方法があるので紹介します

gradio を使う

先に https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt-1-1/tree/main のページに移動しログインし利用規約に同意しましょう

  • huggingface-cli login
  • pip install onnxruntime
  • python -m scripts.demo.gradio_app

これでサンプルを動作させる用の UI が起動します
gradio の方法だと自動的に svd のモデルも huggingface からダウンロードしてくれるので先にログインや同意を済ませておく必要があります

streamlit を使う

https://huggingface.co/stabilityai/stable-video-diffusion-img2vid/blob/main/svd.safetensors をダウンロードし checkpoints ディレクトリに配置します

  • mkdir checkpoints
  • ls -1 checkpoints
svd.safetensors
  • streamlit run scripts/demo/video_sampling.py --server.address 0.0.0.0 --server.port 7862

これでサンプル用の UI が起動します
ただ Load Model をクリックすると先程同様 CUDA のエラーとなり動作はしません

最後に

generative-models を Mac 環境にインストールする方法を紹介しました
残念ながらまだ Mac では動作しないようです
モデル自体は huggingface で公開されているので別のクライアントを使えば動作するかもしれません

次回は stable-diffusion-webui-forge を試してみます

参考サイト

2025年4月22日火曜日

Open WebUI を Azure のカスタムエンドポイントで使用する方法

Open WebUI を Azure のカスタムエンドポイントで使用する方法

概要

前回 LiteLLM を使って Azure OpenAI のカスタムエンドポイントを指定する方法を紹介しました
今回は Open-WebUI を起動して独自の Web Chat コンソールを構築します

環境

  • docker 27.3.1
  • Ubuntu 24.04
  • litellm-proxy v1.67.0-stable
  • open-webui 0.6.5

litellm_config.yaml

前回の内容と同じです
https://hawksnowlog.blogspot.com/2025/04/run-litellm-proxy-on-docker-via-azure-custom-endpoint.html#litellm_config.yaml

.env

キー情報を記載します

AZURE_API_KEY=b4xxx

compose.yaml

OpenWebUI -> LiteLLM は内部的に通信します
サービス経由でも問題ないかもです

services:
  openwebui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    ports:
      - "3000:8080"
    volumes:
      - open-webui:/app/backend/data
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      - WEBUI_AUTH=False
      - OPENAI_API_BASE_URL=http://host.docker.internal:4000/v1
    restart: always

  litellm:
    image: ghcr.io/berriai/litellm:main-latest
    container_name: litellm
    ports:
        - "4000:4000"
    volumes:
        - ./litellm_config.yaml:/app/config.yaml
    environment:
      - AZURE_API_BASE=https://your-custom-azure-endpoint/chat-ai/gpt4
      - AZURE_API_KEY=${AZURE_API_KEY}
    command: --config /app/config.yaml --port 4000
    restart: always

volumes:
  open-webui:

動作確認

  • docker compose up -d

で起動し :3000 ポートにアクセスすると Open WebUI にアクセスできます
チャットの履歴は今回コンテナボリュームを使っていますが必要であればデータベースなどに保存しても OK です

最後に

OpenWebUI + LiteLLM Proxy を使って Azure のカスタムエンドポイント用に専用の Chat UI を構築してみました
OpenAI API 以外のエンドポイントでは基本的に LiteLLM Proxy を使うのが主流のようです

参考サイト

2025年4月21日月曜日

LiteLLM Proxy を Azure のカスタムエンドポイントで使用する方法

LiteLLM Proxy を Azure のカスタムエンドポイントで使用する方法

概要

過去に dspy で使用したエンドポイントを LiteLLM Proxy で使用する方法を紹介します
ちなみに LiteLLM Proxy は簡単に言うと OpenAI API 互換に変換してくれるプロキシです

環境

  • docker 27.3.1
  • Ubuntu 24.04
  • litellm-proxy v1.67.0-stable

litellm_config.yaml

model_list:
  - model_name: azure-gpt-4-32k
    litellm_params:
      model: azure/gpt-4-32k
      api_base: os.environ/AZURE_API_BASE # runs os.getenv("AZURE_API_BASE")
      api_key: os.environ/AZURE_API_KEY # runs os.getenv("AZURE_API_KEY")
      api_version: ""

docker 起動

docker run \
    -v $(pwd)/litellm_config.yaml:/app/config.yaml \
    -e AZURE_API_KEY=b4xxx \
    -e AZURE_API_BASE=https://your-api-endpoint/ai/chat-ai/gpt4 \
    -p 4000:4000 \
    ghcr.io/berriai/litellm:main-latest \
    --config /app/config.yaml --detailed_debug

動作確認

curl で動作確認します
model 名は litellm_config.yaml で指定した model_name を指定します

curl --location 'http://0.0.0.0:4000/chat/completions' \
    --header 'Content-Type: application/json' \
    --data '{
    "model": "azure-gpt-4-32k",
    "messages": [
        {
        "role": "user",
        "content": "what llm are you"
        }
    ]
}'

レスポンスは以下です

{
  "id": "chatcmpl-BOZAENZRJ1j3WErgssAmUj41gcl16",
  "created": 1745194742,
  "model": "gpt-4o-2024-08-06",
  "object": "chat.completion",
  "system_fingerprint": "fp_ee1d74bde0",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "I am based on OpenAI's GPT-4 architecture, which is a type of large language model (LLM) designed for understanding and generating human-like text.",
        "role": "assistant",
        "tool_calls": null,
        "function_call": null
      }
    }
  ],
  "usage": {
    "completion_tokens": 34,
    "prompt_tokens": 12,
    "total_tokens": 46,
    "completion_tokens_details": {
      "accepted_prediction_tokens": 0,
      "audio_tokens": 0,
      "reasoning_tokens": 0,
      "rejected_prediction_tokens": 0
    },
    "prompt_tokens_details": {
      "audio_tokens": 0,
      "cached_tokens": 0
    }
  },
  "service_tier": null,
  "prompt_filter_results": [
    {
      "prompt_index": 0,
      "content_filter_results": {
        "hate": {
          "filtered": false,
          "severity": "safe"
        },
        "self_harm": {
          "filtered": false,
          "severity": "safe"
        },
        "sexual": {
          "filtered": false,
          "severity": "safe"
        },
        "violence": {
          "filtered": false,
          "severity": "safe"
        }
      }
    }
  ]
}

最後に

次回はこれと Open WebUI を組み合わせて自分専用の Chat 用 UI を構築します

参考サイト

2025年4月18日金曜日

firefox で userChrome.css を使う方法

firefox で userChrome.css を使う方法

概要

最新バージョンではデフォルト無効ですが有効にすることで使えます
今回はブックマークバーの間隔を調整する方法を紹介します

環境

  • Firefox Developer Edition 138.0b8

userChrome.css の有効化

  • about:config をアドレスバーに入力
  • toolkit.legacyUserProfileCustomizations.stylesheets の設定を検索
  • true に設定

userChrome.css の作成

プロファイル配下に chrome ディレクトリを作成しそこに userChrome.css を作成します

  • mkdir "/Users/username/Library/Application Support/Firefox/Profiles/uxiqfej5.dev-edition-default-1744936099514/chrome"
  • vim "/Users/username/Library/Application Support/Firefox/Profiles/uxiqfej5.dev-edition-default-1744936099514/chrome/userChrome.css"
/* ブックマークバーのアイコン間隔を狭くする */
toolbarbutton.bookmark-item {
  padding: 0px 4px !important; /* 左右のパディングを少なくする(デフォルトは6px前後) */
  margin: 0 !important;
}

プロファイルのパスは about:support からでも確認できます

Firefox の再起動

設定を反映させます

動作確認

ブックマークバーの間隔が狭くなっていることを確認します

最後に

有効にすれば userChrome.css はまだ使えるようです

2025年4月17日木曜日

dspy.LM で会話形式で質問する方法

dspy.LM で会話形式で質問する方法

概要

前の質問と回答を次回の質問時にも渡すことで前の会話もコンテキストに含めることができます

環境

  • Ubuntu 24.04
  • Python 3.12.9
  • dspy 2.6.17

サンプルコード

  • vim app.py
import json
import os
import sys

import dspy

# モデル設定
lm = dspy.LM(
    "azure/gpt-4-32k",
    api_key="xxx",
    api_version="",
    api_base="https://your-llm-endpont/chat-ai/gpt4",
)
dspy.configure(lm=lm)

# チャット履歴ファイルパス
HISTORY_FILE = "chat_history.json"

class ProjectChat(dspy.Module):
    def __init__(self):
        super().__init__()
        self.chat_history = self.load_history()

    def load_history(self):
        if os.path.exists(HISTORY_FILE):
            with open(HISTORY_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        # 初期 system メッセージ(なければ context なしでもOK)
        return [{"role": "system", "content": "あなたは優秀なソフトウェアエンジニアとして、コードに関する質問に日本語で答えてください。"}]

    def save_history(self):
        with open(HISTORY_FILE, "w", encoding="utf-8") as f:
            json.dump(self.chat_history, f, ensure_ascii=False, indent=2)

    def ask(self, user_question):
        self.chat_history.append({"role": "user", "content": user_question})
        response = dspy.settings.lm(messages=self.chat_history)
        # LLM からのレスポンスが配列なので文字列に変換して保存する
        self.chat_history.append({"role": "assistant", "content": ",".join(response)})
        self.save_history()
        return response


if __name__ == "__main__":
    chat = ProjectChat()

    print("会話を開始します(Ctrl+Dで入力完了 / Ctrl+C or 'exit' のみの入力で終了)\n")

    while True:
        print("質問をどうぞ(複数行ペースト対応):")
        user_input = ""
        try:
            user_input = sys.stdin.read()
        except KeyboardInterrupt:
            print("終了します")
            break
        if user_input.strip().lower() in {"exit", "quit"}:
            print("終了します")
            break
        print("\n入力が終了しました")
        if not user_input.strip():
            print("質問が入力されていません。再度入力してください。")
            continue

        res = chat.ask(user_input.strip())
        print(f"\n回答: {res}\n")

動作確認

  • pipenv run python app.py

で会話を開始します

会話を開始します(Ctrl+Dで入力完了 / Ctrl+C or 'exit' のみの入力で終了)

質問をどうぞ(複数行ペースト対応):
以下のコードについて説明してください
import time


class Message:
    def say(self, **kwargs):
        print("Start say")
        print(kwargs)
        time.sleep(10)
        raise ValueError()
        # print("End say")

入力が終了しました
[{'role': 'system', 'content': 'あなたは優秀なソフトウェアエンジニアとして、コードに関する質問に日本語で答えてください。'}, {'role': 'user', 'content': '以下のコードについて説明してください\nimport time\n\n\nclass Message:\n    def say(self, **kwargs):\n        print("Start say")\n        print(kwargs)\n        time.sleep(10)\n        raise ValueError()\n        # print("End say")'}]

回答: ['このコードは、Pythonのクラスと例外処理に関する基本的な例です。以下にコードの各部分について説明します。\n\n1. **`import time`**:\n   - Pythonの標準ライブラリである`time`モジュールをインポートしています。このモジュールは、時間に関連する機能を提供します。\n\n2. **`class Message:`**:\n   - `Message`という名前のクラスを定義しています。クラスはオブジェクト指向プログラミングの基本単位で、データとメソッドを持つことができます。\n\n3. **`def say(self, **kwargs):`**:\n   - `say`という名前のメソッドを定義しています。このメソッドは、キーワード引数を受け取ることができます。`**kwargs`は、任意の数のキーワード引数を辞書として受け取ることを意味します。\n\n4. **`print("Start say")`**:\n   - メソッドの実行が開始されたことを示すメッセージをコンソールに出力します。\n\n5. **`print(kwargs)`**:\n   - 受け取ったキーワード引数をコンソールに出力します。`kwargs`は辞書として渡されるので、その内容が表示されます。\n\n6. **`time.sleep(10)`**:\n   - プログラムの実行を10秒間停止します。これは、`time`モジュールの`sleep`関数を使用して行われます。\n\n7. **`raise ValueError()`**:\n   - `ValueError`という例外を発生させます。これは、プログラムの実行を中断し、エラーメッセージを表示するために使用されます。\n\n8. **`# print("End say")`**:\n   - この行はコメントアウトされています。もしコメントアウトが解除されていた場合、メソッドの終了を示すメッセージをコンソールに出力することになります。しかし、現在のコードではこの行は実行されません。\n\nこのコードを実行すると、`say`メソッドが呼び出された際に、開始メッセージとキーワード引数が表示され、10秒間の待機の後に`ValueError`が発生します。例外が発生するため、コメントアウトされた行は実行されません。']

一度プロセスを終了して再度実行します
その場合でも前の会話をちゃんと LLM 側が把握していることが確認できます

質問をどうぞ(複数行ペースト対応):
time.sleep(10)をランダムな時間sleepするように修正してください

入力が終了しました
[{'role': 'system', 'content': 'あなたは優秀なソフトウェアエンジニアとして、コードに関する質問に日本語で答えてください。'}, {'role': 'user', 'content': '以下のコードについて説明してください\nimport time\n\n\nclass Message:\n    def say(self, **kwargs):\n        print("Start say")\n        print(kwargs)\n        time.sleep(10)\n        raise ValueError()\n        # print("End say")'}, {'role': 'assistant', 'content': 'このコードは、Pythonのクラスと例外処理に関する基本的な例です。以下にコードの各部分について説明します。\n\n1. **`import time`**:\n   - Pythonの標準ライブラリである`time`モジュールをインポートしています。このモジュールは、時間に関連する機能を提供します。\n\n2. **`class Message:`**:\n   - `Message`という名前のクラスを定義しています。クラスはオブジェクト指向プログラミングの基本単位で、データとメソッドを持つことができます。\n\n3. **`def say(self, **kwargs):`**:\n   - `say`という名前のメソッドを定義しています。このメソッドは、キーワード引数を受け取ることができます。`**kwargs`は、任意の数のキーワード引数を辞書として受け取ることを意味します。\n\n4. **`print("Start say")`**:\n   - メソッドの実行が開始されたことを示すメッセージをコンソールに出力します。\n\n5. **`print(kwargs)`**:\n   - 受け取ったキーワード引数をコンソールに出力します。`kwargs`は辞書として渡されるので、その内容が表示されます。\n\n6. **`time.sleep(10)`**:\n   - プログラムの実行を10秒間停止します。これは、`time`モジュールの`sleep`関数を使用して行われます。\n\n7. **`raise ValueError()`**:\n   - `ValueError`という例外を発生させます。これは、プログラムの実行を中断し、エラーメッセージを表示するために使用されます。\n\n8. **`# print("End say")`**:\n   - この行はコメントアウトされています。もしコメントアウトが解除されていた場合、メソッドの終了を示すメッセージをコンソールに出力することになります。しかし、現在のコードではこの行は実行されません。\n\nこのコードを実行すると、`say`メソッドが呼び出された際に、開始メッセージとキーワード引数が表示され、10秒間の待機の後に`ValueError`が発生します。例外が発生するため、コメントアウトされた行は実行されません。'}, {'role': 'user', 'content': 'time.sleep(10)をランダムな時間sleepするように修正してください'}]

回答: ['`time.sleep(10)`をランダムな時間だけスリープするように修正するには、Pythonの`random`モジュールを使用します。このモジュールを使うことで、指定した範囲内でランダムな数値を生成することができます。以下に修正したコードを示します。\n\n python\nimport time\nimport random\n\nclass Message:\n    def say(self, **kwargs):\n        print("Start say")\n        print(kwargs)\n        \n        # 1秒から10秒の間でランダムな時間だけスリープする\n        sleep_time = random.uniform(1, 10)\n        print(f"Sleeping for {sleep_time:.2f} seconds")\n        time.sleep(sleep_time)\n        \n        raise ValueError()\n        # print("End say")\n \n\n### 修正点の説明\n\n1. **`import random`**:\n   - `random`モジュールをインポートしました。このモジュールは、ランダムな数値を生成するための機能を提供します。\n\n2. **`sleep_time = random.uniform(1, 10)`**:\n   - `random.uniform(a, b)`関数を使用して、1秒から10秒の間でランダムな浮動小数点数を生成しています。この数値がスリープする時間になります。\n\n3. **`print(f"Sleeping for {sleep_time:.2f} seconds")`**:\n   - スリープする時間をコン
ソールに出力しています。`:.2f`は、浮動小数点数を小数点以下2桁まで表示するためのフォーマット指定子です。\n\nこの修正により、`say`メソッドは1秒から10秒の間でランダムな時間だけスリープするようになります。']

質問をどうぞ(複数行ペースト対応):

トラブルシューティング

litellm.exceptions.APIError: litellm.APIError: AzureException APIError - Error code: 500 - {'fault': {'faultstring': 'Execution of ServiceCallout SC-Count-Token failed. Reason: ResponseCode 500 is treated as error', 'detail': {'errorcode': 'steps.servicecallout.ExecutionFailed'}}}

LLM によっては質問時にフォーマットが決まっていることがあるようです
自分の場合は履歴を渡すときに content が配列だと上記エラーに遭遇しました
なので会話の履歴を保存する際に配列ではなく文字列で保存するようにしています

最後に

この方法で一番気をつけなければいけないことは会話が長くなることでトークン制限引っかかることです
トークン制限に引っかかった場合には会話の履歴ファイルを直接編集し前の会話を削除するなりしてください
もちろん Module 内で会話のファイルが一定サイズより大きくなったら削除するなどしても OK です

この方法は chatgpt の WebUI などでも行っています
ただ完全に同じではなく chatgpt WebUI などでは古い会話の自動削除や前の会話をそのまま渡さす要約化したりしています
このあたりもまだまだプロンプト最適化できるかなと思います

会話方式でコンテキストを渡す方法とコード全体の要約を毎回質問時に渡す方法はどちらが効率的かつ精度がいいのか気になります

2025年4月15日火曜日

emacs の copilot-chat で選択した部分をコンテキストに追加して質問する方法

emacs の copilot-chat で選択した部分をコンテキストに追加して質問する方法

概要

前回選択中のバッファをコンテキストに追加する方法を紹介しました
今回は選択した部分をコンテキストとして追加し質問する方法を紹介します

環境

  • macOS 15.4
  • emacs 30.1

copilot-chat-custom-prompt-selection

  • 質問したい部分を選択
  • M-x copilot-chat-custom-prompt-selection
  • ミニバッファで質問する

すると Copilot chat 用のバッファで質問が返ってくるので確認します
ちゃんと選択した部分が質問のコンテキストに追加されていることを確認しましょう

* *[16:28:35]* You                 :you:
Create another Message instance and call the say method.

#+BEGIN_SRC python
from my_libs.util import Message


def main():
    # Create an instance of the Message class
    msg = Message()
    
    # Call the say method with keyword arguments
    try:
        msg.say(text="Hello, World!", sender="user@example.com", recipient="recipient@example.com")
    except ValueError:
        print("An error occurred while executing the say method.")

if __name__ == "__main__":
    main()

#+END_SRC


** *[16:28:39]* Copilot(gpt-4o)                 :copilot:
*** Create another Message instance and call the ~say~ method
To create another instance of the ~Message~ class and call the ~say~ method, you can follow the example below:

#+BEGIN_SRC python
from my_libs.util import Message


def main():
    # Create the first instance of the Message class
    msg1 = Message()
    
    # Call the say method for the first instance
    try:
        msg1.say(text="Hello, World!", sender="user@example.com", recipient="recipient@example.com")
    except ValueError:
        print("An error occurred while executing the say method for msg1.")
    
    # Create another instance of the Message class
    msg2 = Message()
    
    # Call the say method for the second instance
    try:
        msg2.say(text="Goodbye, World!", sender="admin@example.com", recipient="user@example.com")
    except ValueError:
        print("An error occurred while executing the say method for msg2.")

if __name__ == "__main__":
    main()
#+END_SRC

*** Explanation
+ The code creates two separate instances of the ~Message~ class: ~msg1~ and ~msg2~.
+ The ~say~ method is called on each instance with different arguments.
+ Error handling is included using ~try~ and ~except~ blocks to catch any ~ValueError~ exceptions that may occur during the execution of the ~say~ method.


* ╭──── Chat Input ────╮ :copilotChatInput:

最後に

コンテキストをうまく追加して自分のコードを LLM 側に認識させましょう

2025年4月14日月曜日

git rm で削除したファイルを復元する方法

git rm で削除したファイルを復元する方法

概要

すでにリモート側にも push している状態から復元する方法を紹介します

環境

  • git 2.47.0

ファイルとコミットハッシュの確認

  • git log -- src/utils/logger.js

復元

  • git checkout fe3c7b64cd81ae68b797a7804960accaae2fbfd4 – src/utils/logger.js

最後に

過去の実装を戻したい場合に使えます

2025年4月13日日曜日

emacs の copilot-chat で copilot-chat-add-current-buffer を使うと現在のバッファを質問のコンテクストとして加えることができる

emacs の copilot-chat で copilot-chat-add-current-buffer を使うと現在のバッファを質問のコンテクストとして加えることができる

概要

タイトルの通りです
手元のコードを学習させたりコンテキストとして持たせたりするベストプラクティスは何がいいのでしょうか

環境

  • emacs 30.1
  • copilot-chat 2.0.1

チャット履歴

まずはコンテキストを与えないで質問します

* *[11:06:32]* You                 :you:
Please provide a sample python code that uses the Message class.

** *[11:06:34]* Copilot(gpt-4o)                 :copilot:
*** Sample Python Code Using the Message Class

Here is a sample Python code that demonstrates the use of the `Message` class from the `email.message` module. This example creates an email message, sets its headers, and adds content.

#+BEGIN_SRC python
from email.message import EmailMessage

def create_email():
    # Create an instance of the EmailMessage class
    msg = EmailMessage()
    
    # Set the email headers
    msg['From'] = 'sender@example.com'
    msg['To'] = 'recipient@example.com'
    msg['Subject'] = 'Sample Email Subject'
    
    # Add the email content
    msg.set_content('This is the plain text content of the email.')
    
    # Add an HTML version of the content
    msg.add_alternative("""
    <html>
        <body>
            <h1>This is the HTML content of the email.</h1>
            <p>It includes <b>bold</b> and <i>italic</i> text.</p>
        </body>
    </html>
    """, subtype='html')
    
    return msg

# Example usage
if __name__ == "__main__":
    email_message = create_email()
    print(email_message)
#+END_SRC

*** Key Points
+ The `EmailMessage` class is part of Python's built-in `email` module.
+ The `set_content` method is used to add plain text content.
+ The `add_alternative` method is used to add an HTML version of the email content.
+ Headers like ~From~, ~To~, and ~Subject~ are set using dictionary-like syntax.

次に以下のファイルを開いて copilot-chat-add-current-buffer で開いたファイルをコンテキストに追加します

  • vim my_lib/utils.py
import time


class Message:
    def say(self, **kwargs):
        print("Start say")
        print(kwargs)
        time.sleep(10)
        raise ValueError()
        # print("End say")

そして更に質問します
するとコンテキストとして追加したクラスをちゃんと使って修正してくれます

* *[11:07:47]* You                 :you:
Use the Message class in my_libs/utils.py

** *[11:07:48]* Copilot(gpt-4o)                 :copilot:
*** Sample Code Using the ~Message~ Class in ~my_libs/utils.py~

Below is an example of how to use the ~Message~ class from your provided code in ~my_libs/utils.py~.

#+BEGIN_SRC python
from my_libs.utils import Message

def main():
    # Create an instance of the Message class
    msg = Message()
    
    # Call the say method with keyword arguments
    try:
        msg.say(text="Hello, World!", sender="user@example.com", recipient="recipient@example.com")
    except ValueError:
        print("An error occurred while executing the say method.")

if __name__ == "__main__":
    main()
#+END_SRC

*** Explanation
+ The ~Message~ class is imported from ~my_libs/utils.py~.
+ An instance of the ~Message~ class is created using ~msg = Message()~.
+ The ~say~ method is called with keyword arguments like ~text~, ~sender~, and ~recipient~.
+ A ~try-except~ block is used to handle the ~ValueError~ raised by the ~say~ method.

更に Message クラスに機能を追加する依頼をしてみます
ちゃんと元の Message クラスの構成をキープしつつ追加してくれました

* *[11:11:04]* You                 :you:
Add a field to the Message class to manage the message body.


** *[11:11:06]* Copilot(gpt-4o)                 :copilot:
*** Updated ~Message~ Class with a Field for the Message Body

Below is the updated ~Message~ class with a new field to manage the message body.

#+BEGIN_SRC python
import time

class Message:
    def __init__(self, body=""):
        """
        Initialize the Message class with an optional body field.
        """
        self.body = body

    def say(self, **kwargs):
        """
        Print the message body and additional keyword arguments.
        """
        print("Start say")
        print("Message Body:", self.body)
        print("Additional Arguments:", kwargs)
        time.sleep(10)
        raise ValueError()
        # print("End say")
#+END_SRC

*** Explanation of Changes
+ A new field ~body~ is added to the ~Message~ class, initialized in the constructor (~__init__~).
+ The ~say~ method now prints the value of the ~body~ field along with the additional keyword arguments.

*** Example Usage
Here is an example of how to use the updated ~Message~ class:

#+BEGIN_SRC python
from my_libs.utils import Message

def main():
    # Create an instance of the Message class with a custom body
    msg = Message(body="This is the message body.")
    
    # Call the say method with keyword arguments
    try:
        msg.say(sender="user@example.com", recipient="recipient@example.com")
    except ValueError:
        print("An error occurred while executing the say method.")

if __name__ == "__main__":
    main()
#+END_SRC

*** Key Points
+ The ~body~ field allows you to store and manage the message content directly within the ~Message~ class.
+ The ~say~ method now includes the ~body~ field in its output for better context.


* ╭──── Chat Input ────╮ :copilotChatInput:

最後に

emacs の copilot-chat でコンテキストを追加する方法を紹介しました
こんな感じで公開されていないコードや手元にあるライブラリ情報をコンテキストとして追加すればそれを考慮したコードを書いてくれるようです

以下懸念点です

  • 複数のバッファをコンテキストとして追加するにはどうすればいいのか
  • 一度コンテキストとして追加したバッファを復元するにはどうすればいいのか
    • chat を開くたびに追加しなければならない

参考サイト

2025年4月12日土曜日

Claude Desktop を使って MCP Server に入門してみる

Claude Desktop を使って MCP Server に入門してみる

概要

前回 Claude を Mac にインストールしてみました
今回は Claude Desktop の MCP クライアントとしての機能を使ってみます
サーバ側は https://github.com/github/github-mcp-server を使います
この MCP サーバは Github にある自身のリポジトリや Issue などを検索するのに役立ちます

環境

  • macOS 15.4
  • Claude desktop 0.9.2
  • docker 28.0.4

MCP サーバの追加

Claude desktop に MCP サーバを追加します
設定ファイルがあるのでそれに MCP サーバの定義を追加します

claude_desktop_config.json 自体は初回にはないので作成すれば OK です

  • vim ~/Library/Application\ Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      }
    }
  }
}

YOUR_TOKEN の部分には Github から取得したトークンを入力してください
MCP サーバはほぼすべての Github API を使用するので権限は多めに設定するのがいいかなと思います
MCP サーバに呼び出させたい API だけ権限を付与するのもありです

このように記載すると Claude 起動時に docker を使って自動で MCP サーバを起動してくれます

動作確認

初回起動時は Claude から docker へのアクセス権限がなく失敗するので許可してから再起動しましょう

MCP サーバが docker で起動していれば OK です

docker ps 
CONTAINER ID   IMAGE                              COMMAND                   CREATED        STATUS        PORTS     NAMES
3b725ec0e9a8   ghcr.io/github/github-mcp-server   "./github-mcp-server…"   1 second ago   Up 1 second             amazing_lumiere

これで Github に関する質問をすると MCP サーバを介して検索してくれます
最初に get_me という命令を使って自分の Github の情報を Claude が取得してもいいか聞かれるので許可します

こんな感じで Claude が MCP サーバを介して Github から必要な情報を取得してくれます

最後に

他にも公開されている MCP サーバはたくさんあるので助けてほしい項目のサーバがあれば追加してみるといいかなと思います

基本的には RAG に近い機能ではありますが MCP サーバを構築/追加するだけであるコンテキストに特化した情報が簡単に検索できるようになるので便利です
また MCP サーバというかアプリケーションなので例えば Github であれば Issue を作成したり Pull-Request の操作なども Claude desktop からできるようにもなります

起動した MCP サーバは Claude desktop を閉じれば自動的に停止します

参考サイト

2025年4月11日金曜日

git で管理してるファイルから拡張子の一覧を取得する方法

git で管理してるファイルから拡張子の一覧を取得する方法

概要

git ls-files を使って取得する方法を紹介します

環境

  • macOS 15.4
  • git 2.49.0

コマンド

  • git ls-files | grep -oE '\.[^.\/]+$' | sort | uniq
.el
.gitignore
.lock
.md
.rb
.ruby-version
.sh
.yasnippet
.yml

カウント数付き

  • git ls-files | grep -oE '\.[^.\/]+$' | sort | uniq -c | sort -nr
  15 .yasnippet
  13 .el
   8 .rb
   2 .yml
   2 .md
   1 .sh
   1 .ruby-version
   1 .lock
   1 .gitignore

カウントの多い順に csv にして出力する

  • git ls-files | grep -oE '\.([^.\/]+)$' | sed 's/^\.//' | sort | uniq -c | sort -nr | awk '{print $2}' | paste -sd, -

最後に

拡張子のないファイルは取得されません

Claude クライアントを MacOS にインストールする

Claude クライアントを MacOS にインストールする

概要

Claude はマルチプラットフォームな AI クライアントツールです
今回は Mac にインストールして使ってみました

環境

  • macOS 15.4
  • Claude desktop 0.9.2

インストール

  • brew install claude --cask

サインイン

メールアドレスで登録できます

無料プランを選択しましょう

会話する

あとはチャットすれば OK です

最後に

次回は MCP Server と連携してみます

2025年4月10日木曜日

emacs で copilot に質問する

emacs で copilot に質問する

概要

過去に紹介した copilot.el だと補完はしてくれますがチャットはできないので別途拡張をインストールする必要があります

環境

  • Ubuntu 24.04
  • emacs 29.1

インストール

  • package-list-packages
  • copilot-chat
  • i -> x -> y

チャットする

  • M-x copilot-chat-display

初回はログインが必要

チャット用のバッファが起動したら質者を入力し送信します
送信する場合はエンターではなく C-c C-c で送信できます

するとワンタイムコードが発行されるので copilot を使うユーザでブラウザの https://github.com/login/device にアクセスし表示されているワンタイムコードを入力します
これで copilot-chat が使えるようになります

結果を確認する

C-c C-c でチャットを送信すると以下のように結果が返ってきます

結果を別のバッファに反映させるには copilot-chat-yank を実行します

キーバインドで行いたい場合は以下の設定が良いようです

(use-package copilot-chat
  :bind (:map global-map
            ("C-c C-y" . copilot-chat-yank)
            ("C-c M-y" . copilot-chat-yank-pop)
            ("C-c C-M-y" . (lambda () (interactive) (copilot-chat-yank-pop -1))))
)

最後に

emacs から copilot にチャットを送信してみました
Symbol's function definition is void: json-parse-buffer になる場合はそもそも copilot のチャット機能が無効化されている可能性があります

もしくは emacs のバージョンが古いと出るので 30 台にバージョンアップしてください

参考サイト

2025年4月9日水曜日

Github Copilot を CLI から使う

Github Copilot を CLI から使う

概要

コマンドの説明とコマンドの推論だけできるようです

環境

  • gh 2.69.0
  • Ubuntu 24.04

インストール

(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
	&& sudo mkdir -p -m 755 /etc/apt/keyrings \
        && out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
        && cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
	&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
	&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
	&& sudo apt update \
	&& sudo apt install gh -y

ログイン

  • gh auth login

https://github.com/login/device にアクセスしてコードを入力する方法でログインします

? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations on this host? HTTPS
? Authenticate Git with your GitHub credentials? Yes
? How would you like to authenticate GitHub CLI? Login with a web browser

! First copy your one-time code: xxxx-xxxx
Press Enter to open github.com in your browser...
! Failed opening a web browser at https://github.com/login/device
  exec: "xdg-open,x-www-browser,www-browser,wslview": executable file not found in $PATH
  Please try entering the URL in your browser manually
? Authentication complete.
- gh config set -h github.com git_protocol https
? Configured git protocol
! Authentication credentials saved in plain text
? Logged in as username

使う

  • gh copilot explain "ls"

最後に

あとは suggest コマンドなどが使えます

参考サイト

2025年4月8日火曜日

Google フォトで画像を回転させるショートカット

Google フォトで画像を回転させるショートカット

概要

忘れるのでメモ

環境

  • Google Photo ブラウザ版 (2025/04/08 時点)

方法

  • Shift + r

2025年4月7日月曜日

no such file or directory _brew_services の対処方法

no such file or directory _brew_services の対処方法

概要

compinit:527: no such file or directory: /opt/homebrew/share/zsh/site-functions/_brew_services

の対応

環境

  • macOS 15.3.2
  • zsh 5.9

対応方法

  • brew cleanup && rm -f $ZSH_COMPDUMP

最後に

いつも忘れるのでメモ

参考サイト

2025年4月4日金曜日

nvm で管理している nodejs をアップグレードする方法

nvm で管理している nodejs をアップグレードする方法

概要

忘れるのでメモ

環境

  • macOS 15.3.2
  • nvm 0.40.2

nvm 自体のバージョンアップ

https://hawksnowlog.blogspot.com/2024/11/self-update-nvm.html

更新可能なバージョンの確認

  • nvm ls-remote

バージョンアップ

  • nvm install v20.19.0

バージョンアップしたバージョンをデフォルトに設定

基本的には同系列のバージョンアップであれば自動的にデフォルトで新しいバージョンを使うようになります
明示的に指定したいのであれば use を使います

  • nvm use 20.19.0

プロジェクトごとに指定する場合は

  • nvm use --save 20.19.0

2025年4月3日木曜日

Gitlab で renovate を試す

Gitlab で renovate を試す

概要

gitlab のリポジトリに対して renovate を実行してみました
CLI で直接実行する方法と CI を使う方法を紹介します

環境

  • Gitlab 17.8

CLI

  • LOG_LEVEL=debug renovate --platform=gitlab --endpoint=https://your-gitlab-endpoint/api/v4 --username=oauth2 --token=glpat-xxx user/repo

CI

renovate/renovate-runnerを自身の Gitlab にミラーして使います
fork なりミラーしたリポジトリ名を yaml に記載します
Gitlab.com であれば以下のままで OK です

スキャン対象のリポジトリを RENOVATE_EXTRA_FLAGS に追加することで管理するようです

stages:
  - test

include:
  - project: 'renovate/renovate-runner'
    file: '/templates/renovate.gitlab-ci.yml'

renovate:
  stage: test
  variables:
    RENOVATE_EXTRA_FLAGS: "--platform=gitlab --endpoint=https://your-gitlab-endpoint/api/v4 --username=oauth2 user/repo"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
    - if: '$CI_PIPELINE_SOURCE == "push"'

CI 変数

RENOVATE_TOKEN は必須なので CI の変数に設定しましょう
設定する値は Gitlab の Personal Access Token で OK です

GITHUB_COM_TOKEN はあったほうがいいです
Github アカウントがある場合は Github の Personal Access Token を取得して設定しましょう

最後に

基本は CI を使って定期的に MR を作る感じになるかなと思います
ただ更新対象が自動で決まるのとデフォルトだと2MRしか作成してくれないのでそこは変数による調整が必要かもです

また当然ですがバージョンを固定しているケースは renovate でもバージョンを上げられないのでそこは手動によるバージョン管理になります

参考サイト