💭

Copilot で雑多な c++ コードをいい感じに書いてくれることがわかったメモ

に公開

背景

C++ コードで雑多なコード書く(エラーハンドリングやパース処理とか)のめんどい...
この生成 AI 時代, Copilot(LLM) でええ感じにやってほしい.

2025/04 時点で gpt-4o でいい感じになることがわかりました!

Copilot の使い方とかは ChatGPT なりに聞いてください

プロンプト

そこそこ雑なプロンプトでもいけます.

https://github.com/ggml-org/ggml/blob/master/docs/gguf.md

gguf のローダー書いてみましょう.

bool load_gguf_from_memory(const uint8_t *addr, const size_t length, const std::string &gguf_filename,
                         const GGUFModelLoadOption &option,
                         const GGUFModel *model, std::string *err) {

  gguf::StreamReader sr(addr, length, /* TODO: swap_endian*/false);

とりまこんな感じの枠組み用意して...
(StreamReader は ifstream みたいなやつ)

### [load-gguf.cc](vscode-remote://wsl/home/syoyo/work/vision-language.cpp/src/load-gguf.cc)

Implement GGUF header reading using the `StreamReader` instance `sr`.

と指示出すと...

// ...existing code...

bool load_gguf_from_memory(const uint8_t *addr, const size_t length, const std::string &gguf_filename,
                         const GGUFModelLoadOption &option,
                         const GGUFModel *model, std::string *err) {

  gguf::StreamReader sr(addr, length, /* TODO: swap_endian*/false);

  // Read GGUF header
  uint32_t magic = 0;
  if (!sr.read4(&magic)) {
    if (err) {
      (*err) += "Failed to read GGUF magic number.\n";
    }
    return false;
  }

  if (magic != 0x46554747) { // "GGUF" in little-endian
    if (err) {
      (*err) += "Invalid GGUF magic number.\n";
    }
    return false;
  }

  uint32_t version = 0;
  if (!sr.read4(&version)) {
    if (err) {
      (*err) += "Failed to read GGUF version.\n";
    }
    return false;
  }

  if (version != 1) { // Assuming version 1 for now
    if (err) {
      (*err) += "Unsupported GGUF version: " + std::to_string(version) + "\n";
    }
    return false;
  }

  // Successfully read GGUF header
  (void)gguf_filename;
  (void)option;
  (void)model;

  return true;
}

// ...existing code...

Voala~!

GGUF フォーマットの仕様の URL は与えませんでしたが, すでに gpt-4o では学習して取り込んでいるようです.

以下のように解説もしてくれます.

Explanation:

  1. Magic Number: The first 4 bytes are read to verify the GGUF file format using the magic number 0x46554747 ("GGUF" in little-endian).
  2. Version: The next 4 bytes are read to determine the GGUF version. Only version 1 is supported in this implementation.
  3. Error Handling: If reading fails or the values are invalid, appropriate error messages are appended to the err string.
  4. StreamReader: The StreamReader instance sr is used to read the header fields efficiently.

さらなる高みへ

さらに metadata の読み込みもやらせてみます.

then implement reading metadata, adding gguf_metadata_kv_t  struct

struct gguf_metadata_kv_t {
    std::string key;
    std::string value;
};

  // Read metadata count
  uint32_t metadata_count = 0;
  if (!sr.read4(&metadata_count)) {
    if (err) {
      (*err) += "Failed to read metadata count.\n";
    }
    return false;
  }

  std::vector<gguf_metadata_kv_t> metadata;
  for (uint32_t i = 0; i < metadata_count; ++i) {
    uint32_t key_len = 0;
    if (!sr.read4(&key_len)) {
      if (err) {
        (*err) += "Failed to read metadata key length.\n";
      }
      return false;
    }

    std::string key(key_len, '\0');
    if (sr.read(key_len, key_len, reinterpret_cast<uint8_t *>(&key[0])) != key_len) {
      if (err) {
        (*err) += "Failed to read metadata key.\n";
      }
      return false;
    }

    uint32_t value_len = 0;
    if (!sr.read4(&value_len)) {
      if (err) {
        (*err) += "Failed to read metadata value length.\n";
      }
      return false;
    }

    std::string value(value_len, '\0');
    if (sr.read(value_len, value_len, reinterpret_cast<uint8_t *>(&value[0])) != value_len) {
      if (err) {
        (*err) += "Failed to read metadata value.\n";
      }
      return false;
    }

    metadata.push_back({key, value});
  }

Voila~

コンパイルの修正

コンパイルエラーになっても,

  • vscode なら chat window にエラーメッセージ貼り付けで修正してくれる
  • VS2022 なら quick fix っぽく修正してくれる

である程度自動で良しなに直してくれます!

最近の LLM では C++ コードもそれなりに十分いい感じに生成や修正してくれることがわかりました.

今後さらに LLM が進化してくれたら, ちょこっと指示だすだけでほとんどの C++ コードを生成してくれそうです!

ちょっと不満なところ

GPT-4o だとまず最初にコード生成はじまるまで ~10 秒くらい, コード生成全体は ~ 1 分くらいかかります.
数行で終わるようなものだと手書きのほうが早いです.

free プランだと使いまくってると数日で rate limit になります.

Responses are limited to 2,000 code completions and 50 chat messages per month.

OSS developer&maintainer だと Pro アクセス権付与されるようですが, C++ 系は人気がないためか, C++ の OSS をそれなりに公開している私には Pro アクセス権はありませんでした.

課金するか, ローカルで LLM 動かすで対応でしょうか.
つよつよ GPU あればローカルで LLM 動かすのも手ではそうです.

Pro 版も $10/month なので, お時給 1 時間ぶんくらいと考えれば安いところカナ

Discussion