チャットワークのAPIを使ってみました.プロンプトでほぼ書いています.

2025.07.13

Logging

おはようございます.チャットワークのAPIを使ってみました.プロンプトでほぼ書いたコードになります、チャットGPTの無料版にリファレンスのURLリンクとPHPのクラス化、リターンに$thisで返却出来る所は$thisを使用してスマートにコードを書いてと指示を出しました.

出来上がったコードが下記になります.ソースコードは自分の方でモンキーテスト的に動かしてみましたが、ちゃんと動作するようです.

<?php
class ChatworkClient
{
    private string $apiToken;
    private string $baseUrl = 'https://api.chatwork.com/v2';
    private int $retryCount = 3;
    private int $retryDelay = 1000000; // microseconds

    public function __construct(string $apiToken)
    {
        $this->apiToken = $apiToken;
    }

    public function setRetry(int $count, int $delayMicroseconds): self
    {
        $this->retryCount = $count;
        $this->retryDelay = $delayMicroseconds;
        return $this;
    }

    private function request(string $method, string $path, array $params = []): array
    {
        $attempts = 0;

        while ($attempts < $this->retryCount) {
            $attempts++;

            $ch = curl_init();
            $url = $this->baseUrl . $path;

            if ($method === 'GET' && $params) {
                $url .= '?' . http_build_query($params);
            }

            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $headers = ['X-ChatWorkToken: ' . $this->apiToken];

            if (in_array($method, ['POST', 'PUT', 'DELETE'])) {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
                $headers[] = 'Content-Type: application/x-www-form-urlencoded';
            }

            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $body = curl_exec($ch);
            $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);

            if ($error) {
                if ($attempts < $this->retryCount) {
                    usleep($this->retryDelay);
                    continue;
                }
                throw new RuntimeException("cURL error after {$attempts} attempts: {$error}");
            }

            if ($status >= 200 && $status < 300) {
                return [
                    'status' => $status,
                    'body' => $body ? json_decode($body, true) : null,
                ];
            }

            if ($attempts < $this->retryCount && $status >= 500) {
                usleep($this->retryDelay);
                continue;
            }

            return [
                'status' => $status,
                'body' => $body ? json_decode($body, true) : null,
            ];
        }

        throw new RuntimeException("Request failed after {$this->retryCount} attempts");
    }

    public function setToken(string $token): self
    {
        $this->apiToken = $token;
        return $this;
    }

    public function me(): array
    {
        return $this->request('GET', '/me');
    }
    public function getMyStatus(): array
    {
        return $this->request('GET', '/my/status');
    }
    public function getMyTasks(array $filters = []): array
    {
        return $this->request('GET', '/my/tasks', $filters);
    }
    public function getContacts(): array
    {
        return $this->request('GET', '/contacts');
    }
    public function getRooms(): array
    {
        return $this->request('GET', '/rooms');
    }
    public function createRoom(array $params): array
    {
        return $this->request('POST', '/rooms', $params);
    }
    public function getRoom(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}");
    }
    public function updateRoom(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}", $params);
    }
    public function deleteRoom(int $roomId, string $action = 'leave'): array
    {
        return $this->request('DELETE', "/rooms/{$roomId}", ['action_type' => $action]);
    }

    public function getMembers(int $roomId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/members");
    }
    public function updateMembers(int $roomId, array $params): array
    {
        return $this->request('PUT', "/rooms/{$roomId}/members", $params);
    }

    public function getMessages(int $roomId, bool $force = false): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages", ['force' => $force ? 1 : 0]);
    }

    public function postMessage(int $roomId, string $body, bool $selfUnread = false): self
    {
        $this->request('POST', "/rooms/{$roomId}/messages", ['body' => $body, 'self_unread' => $selfUnread ? 1 : 0]);
        return $this;
    }

    public function markRead(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/read");
        return $this;
    }

    public function markUnread(int $roomId): self
    {
        $this->request('PUT', "/rooms/{$roomId}/messages/unread");
        return $this;
    }

    public function getMessage(int $roomId, int $messageId): array
    {
        return $this->request('GET', "/rooms/{$roomId}/messages/{$messageId}");
    }

    public function getRoomTasks(int $roomId, array $filters = []): array
    {
        return $this->request('GET', "/rooms/{$roomId}/tasks", $filters);
    }

    public function createTask(int $roomId, array $params): array
    {
        return $this->request('POST', "/rooms/{$roomId}/tasks", $params);
    }

    public function uploadFile(int $roomId, string $filePath, string $message = ''): array
    {
        if (!file_exists($filePath)) {
            throw new InvalidArgumentException("File not found: {$filePath}");
        }

        $ch = curl_init();
        $url = $this->baseUrl . "/rooms/{$roomId}/files";
        $cfile = curl_file_create($filePath);

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-ChatWorkToken: ' . $this->apiToken]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $cfile, 'message' => $message]);

        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        if (curl_errno($ch)) {
            throw new RuntimeException(curl_error($ch));
        }

        curl_close($ch);
        return ['status' => $status, 'body' => json_decode($body, true)];
    }
}

人が今回のコードを書いた場合、早い人でも10分ぐらいはコードを書かないといけないと思います、どんなに早くてもそれぐらいの時間は必要だと思いますが、生成AIはこれを数十秒で書ける訳ですから、確実に時間短縮になります.

なので人工知能が使える現場は間違いなく最初のコード出力は人工知能に任せた方が良いです.特に新規案件の土台は生成AIに任せると開発コストは削減出来ます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, クラス, コード, コスト, これ, スマート, ソース, それ, チャット, テスト, プロンプト, モンキー, よう, リターン, リファレンス, リンク, ワーク, 下記, 人工, 今回, 使用, 出力, 削減, 動作, 土台, 場合, 必要, 指示, 新規, 明日, 時間, 最初, 案件, 無料, 現場, 生成, 知能, 短縮, 確実, 自分, 返却, 開発, 間違い,

英語学習にお金を使うように考えを変えます.今まで何度も

2025.07.04

Logging

おはようございます.英語学習にお金を使うように考えを変えます.今まで何度も挫折してきた英語学習にお金をかけようと思っています.自分が望むものはサブスクでスマホやPCで勉強が学べるものです.

そういうものを考えたときに浮かぶのがスタディサプリです.スタディサプリみたいなアプリが他にもないのか調べてみました.

自分で調べるのは面倒なのでGeminiさんに調べてもらいました、下記が返答結果になります.

スタディサプリ以外にも、オンラインで学習できるサービスはたくさんあります。対象年齢や学習内容によって様々な選択肢があるので、ご自身の目的やレベルに合わせて検討してみてください。

いくつか代表的な類似サービスやカテゴリーを挙げます。

大手予備校・通信教育系のオンラインサービス

  • Z会: 小学生から高校生、大学受験生まで幅広い層に対応した通信教育の老舗。映像授業と丁寧な添削指導が特徴です。
  • 進研ゼミ: ベネッセが提供する、小・中・高校生向けの通信教育。タブレット学習やAIを活用した個別最適化された学習が強みです。
  • 東進ハイスクール在宅受講コース / 東進オンライン学校: 有名講師による質の高い映像授業が特徴。大学受験に強いです。
  • 学研プライムゼミ: 高校生・浪人生向けのハイレベルな映像授業が中心。難関大学対策に特化しています。
  • 河合塾One: 河合塾が提供するオンライン学習サービスで、短時間で手軽に学べるコンテンツが特徴です。

AI学習・個別最適化に特化したサービス

  • アタマプラス (atama+): AIが生徒の理解度に合わせて最適なカリキュラムを生成し、個別指導のように学習を進められるサービスです。塾や学校への導入も進んでいます。
  • すらら: AIが生徒の学習状況を分析し、最適な問題を提供。特に苦手克服や学習習慣の定着に力を入れています。無学年式なので、さかのぼり学習も可能です。
  • スマイルゼミ: タブレットを活用した小・中学生向けの通信教育。AIが学習状況に合わせた問題を出題し、定着を促します。

資格取得・ビジネススキル系のオンライン学習サービス

  • Schoo (スクー): ビジネススキルやITスキルなど、幅広い分野のオンライン授業をライブ配信や録画で提供しています。
  • Udemy (ユーデミー): 世界中の講師が様々な分野の講座を販売しているプラットフォーム。買い切り型で、セール時には大幅割引もあります。
  • スタディング: 簿記やITパスポートなど、資格取得に特化したオンライン講座を多数提供しています。
  • ユーキャン / ヒューマンアカデミー / 資格のキャリカレ / フォーサイト など: 各種資格取得に特化した通信講座を提供しています。

その他

  • N予備校: KADOKAWAとドワンゴが運営する、高校生向けのオンライン学習サービス。多様な講座やプログラミング学習もできます。
  • Classi (クラッシー): 学校で導入されていることが多い学習支援プラットフォームで、学習動画やドリルなどが提供されます。

自分で調べるより本当にチャットAIで調べたほうが早いですね便利です、ちなみに生成AIに勉強を教えてもらうという方法もあるようです、自分もある程度身についたらそういう方向にシフトしていくつもりでいますが、何せ土台がガタガタなのでお金をかけて勉強をしようと思っています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, アカデミー, アタマ, アプリ, いくつ, オンライン, お金, ガタガタ, カテゴリー, カリキュラム, キャリカレ, クラッシー, コース, こと, コンテンツ, サービス, サブスク, サン, シフト, スキル, スクー, スタディサプリ, スタディング, スマイル, スマホ, セール, セミ, その他, たくさん, タブレット, チャット, つもり, とき, ドリル, ドワンゴ, ハイスクール, ハイレベル, パスポート, ビジネス, ヒューマン, フォーサイト, プライム, プラス, プラットフォーム, プログラミング, ベネッセ, ほう, みたい, もの, ユーキャン, ユーデミー, よう, ライブ, レベル, 丁寧, 下記, 世界中, 中心, 予備校, 代表, 以外, 便利, 個別, 克服, 内容, 出題, 分析, 分野, 割引, 勉強, 動画, 取得, 受講, 受験, 受験生, 可能, 各種, 向け, 問題, 土台, 在宅, 多数, 多様, 大学, 大幅, 大手, 学年, 学校, 学研, 学習, 定着, 対応, 対策, 対象, 導入, 小・中学生, 小学生, 年齢, 強み, 手軽, 指導, 挫折, 授業, 提供, 支援, 教育, 方向, 方法, 明日, 映像, 最適, 有名, 東進, 検討, 様々, 河合塾, 活用, 浪人, 添削, 特徴, 状況, 理解, 生徒, 生成, 目的, 短時間, 簿記, 結果, 習慣, 老舗, 考え, 自分, 自身, 苦手, 英語, 講師, 講座, 販売, 資格, 返答, 通信, 運営, 選択肢, 配信, 録画, 難関, 面倒, 類似, 高校生,

Llama-3-ELYZA-JP-8Bとは何か?モデルという奴です.

2025.07.03

Logging

おはようございます.Llama-3-ELYZA-JP-8Bは、MetaのLlama 3(8Bパラメータ)をベースに、日本語の指示応答能力を強化するためELYZAがファインチューニングした日本語特化型の大規模言語モデルです。

ではモデルとは何か?モデルとは、データからパターンやルールを学習し、新しい入力に対して予測や生成を行うための数学的・計算的な仕組みやプログラムのことです。

今回、自分が試したのはLlama-3-ELYZA-JP-8Bの一番軽量ものを試してみました.軽量すぎてたまに回答が無限ループに陥ることがあります.これはカーソル(cursor)やディビン系でも無限ループに陥ることがあるらしいです.俗に言うトークン食いですね.

トークン食いが一度発生すると次のプロンプトにも影響が出る場合があるので、一度離脱して再度プロンプトを投げることで回避出来るようです.

因みにモデルをCPUで動かしたい場合は、llama.cpp で動かすようにするのだけど、既存のモデルをggufに一度、変換してあげる必要があります.そうすることでグラボが貧弱でも動きます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

カーソル, グラボ, クン, こと, これ, ため, データ, ディビン, トー, パターン, パラメータ, ファインチューニング, プログラム, プロンプト, ベース, モデル, もの, よう, ループ, ルール, 一番, 予測, 今回, 仕組み, 入力, 回答, 回避, 場合, 変換, 学習, 強化, 影響, 必要, 応答, 指示, 数学, 既存, 日本語, 明日, 無限, 生成, 発生, 能力, 自分, 規模, 言語, 計算, 貧弱, 軽量, 離脱, 食い,

Photo by Aaditya Arora on Pexels.com

検索から離れていく時代になった時の対処法というかこれしか対応策がない.

2025.07.02

Logging

おはようございます.そろそろGさんが日本でも検索から生成AIに切り替えを行いそうな気配がありますというのは、自分でモバイル検索していたら検索が対話型に切り替わった時があったのでそろそろな予感がします.

最初に対話型(AIチャット)に切り替わった時に影響を受けやすいサイトは「何々とは」を教えてくれるアンサーサイトだそう、そういうサイトはかなりアクセス数が激減するとのこと、また広告収益の出てないサイトも同じくアクセス数が減るとのこと、逆に影響を受けにくいサイトは広告収益を生み出しているサイトだそうです.

では、どうやってアクセス数を対話型になった時に補うかの話ですが、もうこれしかないと自分は思っています.SNSのフル活用です、フル活用なので一つのSNSの活動をするのではなく複数のSNSを運用し集客に繋げるしか道のりはないじゃないかと.

あと、ネットで商品を販売しているサイトは大手、例えば楽天やアマゾンと言ったサイトに出店しないと成り立たない時代になると思います.本当に人気商品を持っているサイトはダイレクトに物が売れると思いますが、そうではない他店舗の商品を売っている小売サイトは影響を受けると思います.

なので、大手のサイトに店舗を構えることは必須と言えるでしょう、またSNSにも力を入れることや他店舗よりも安く売らないと厳しい時代になりそうです.

尚、Gさんは人工知能対話型検索に広告を挟むことを検討しているので広告を使用するのも一つの手なのかもしれません.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アクセス, あと, アマゾン, アンサーサイト, こと, これ, サイト, サン, そう, ダイレクト, チャット, ネット, プル, モバイル, 一つ, 予感, 人工, 人気, 使用, 出店, 切り替え, 収益, 商品, 大手, 対話, 小売, 広告, 店舗, 影響, 必須, 日本, 明日, 時代, 最初, 検索, 検討, 楽天, 気配, 活動, 活用, 激減, 生成, 知能, 自分, 複数, 販売, 運用, 道のり, 集客,

AIで今後どうなるだろうな.自然言語処理で指示出し出来てきた今日.

2025.07.01

Logging

おはようございます.何だか梅雨明けした休日にGeminiCliでコードを生成しています.仕事ではまだ自分はChatに分からない事を質問するぐらいの事しかしていないのだけども絶対にCliなどで作業すると時間短縮になるのは間違いです(仕事でも導入しているのですが自分は使用していない).

休日に作業するときはコパイロットとGeminiを使用して開発しているのです、どちらも無料版なのだけど自分は無料板で事足りています.

因みにコパイロットとGemini、どちらが優秀かという問いに関しては今のところコパイロットの方が優秀なソースコードを書いてくれるというイメージが強いです.有料版ではカーソルやデビィンなどが優秀らしいけども余裕資金があんま無いので試していない.

お金に余裕があればいろいろと試したいことはあります.例えばグラボ(グラフィックボード)を取り替えて機械学習の学習をローカルで試してみたいなどがあります.

この頃思うのだけど、何かとこの業界は移り変わりが激しいのと新しい技術を学ぶときにたまに技術投資が必要になります.昔はオープンソース的な感じだったけどこのIT業界ビックテックはお金を取り出して来ています.

その中でMETA社?だけがオープンソースでいろいろと提供してくれていてとても有り難いです.それでもやっぱそれを動かす端末の推奨環境という物があるので古いPCだと動かなかったりします.

今後、Llm(大規模言語モデル)は容量が小さくなっていくということとローカル端末で動かすのが当たり前になる時代が来るそうです.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

あんま, イメージ, オープン, お金, カーソル, グラフィック, グラボ, コード, こと, コパイロット, ソース, そう, それ, たま, デビィン, とき, ところ, どちら, ビックテック, ボード, みたい, モデル, ローカル, 今後, 仕事, 休日, 余裕, 作業, 使用, 優秀, 問い, 学習, 容量, 導入, 当たり前, 必要, 感じ, 技術, 投資, 推奨, 提供, 明け, 明日, 時代, 時間, 有料, 梅雨, 業界, 機械, 無料, 環境, 生成, 短縮, 移り変わり, 端末, 絶対, 自分, 規模, 言語, 資金, 質問, 開発, 間違い,

Photo by Victor Dunn on Pexels.com

AIで記事を学習して新たな記事を生み出すにはお金が必要だと思っていたがそうでも.

2025.06.22

Logging

おはようございます.AIで記事を学習して新たな記事を生み出すにはお金が必要だと思っていたがそうでもなくローカルPCでそこら辺に落ちているLlamaモデルを持ってきてチューニングすれば何とかなるじゃねぇという思いに至った.

実はあなたの手元にあるPCと、そこら中に「落ちている」オープンソースのAIモデル、特にLlama 3があれば、十分記事が生成できるんです。


ローカルAI記事生成は、もはや夢物語じゃない

「AIで記事生成」と聞くと、SFのような世界や、大企業だけが使える特権のように感じるかもしれません。しかし、今は違います。オープンソースの強力な言語モデル、特にMetaが公開したLlama 3の登場は、この常識を大きく覆しました。

Llama 3は、その性能の高さにもかかわらず、誰でも無料で利用できるという点が最大の魅力です。さらに、80億パラメータの8Bモデルであれば、最新のゲーミングPCとまではいかなくとも、ある程度の性能を持つPCであれば十分に動作します。これにより、高額なクラウドサービスを利用せずとも、自分のPCでAI記事生成の環境を構築することが現実的になりました。


なぜLlama 3があなたのPCと相性抜群なのか?

Llama 3がローカルPCでの記事生成に適している理由はいくつかあります。

  • 完全無料のオープンソース: 利用に費用がかからないため、予算を気にせずAIを試したり、本格的に導入したりできます。
  • 選べるモデルサイズ: Llama 3には様々なサイズのモデルがあり、PCのスペックに合わせて選べます。特に8Bモデルは、個人利用に最適なバランスを持っています。
  • 活発な開発者コミュニティ: 世界中の開発者がLlama 3を使った新しいツールや効率的なチューニング方法を日々共有しています。困ったときには助けを借りられる心強い味方です。
  • 「量子化」でさらに軽量に: モデルのサイズを大幅に小さくする「量子化」という技術を使えば、より少ないメモリでLlama 3を動かせるようになります。これにより、より多くのPCで利用の道が開けます。

あなたのPCを「記事生成マシン」に変える秘訣

もちろん、いきなりプロのライター並みの記事をAIに書かせるのは難しいかもしれません。しかし、ちょっとした工夫で「何とかなる」レベルの記事生成は十分に可能です。

  1. 少量のデータでファインチューニング: 大量の記事データは不要です。あなたが書きたい記事のテーマやスタイルに合った、質の良い記事を数十〜数百程度集めてLlama 3を学習(ファインチューニング)させれば、その分野に特化した記事生成能力が格段に向上します。
  2. プロンプト(指示文)の工夫: AIへの「指示の出し方」は非常に重要です。具体的で明確なプロンプトを与えることで、チューニングが完璧でなくても、驚くほど質の高い記事が生成できます。これはまるで、優秀なアシスタントに的確な指示を出すようなものです。
  3. 効率的な学習方法の活用: 「LoRA(Low-Rank Adaptation)」のような効率的なファインチューニング手法を使えば、少ないGPUメモリでも短時間でモデルを特定のタスクに最適化できます。

あなたの創造性が、今、AIで加速する

かつては一部の専門家や企業にしか手の届かなかったAIによる記事生成が、今やあなたのPCで実現できる時代になりました。これはまさにAI技術の「民主化」です。

とまぁそういう訳なので何とかしてみますが、ファインチューニングにどれぐらい時間がかかるのかが未知数だったりする.

ファインチューニングPythonコード

以下のPythonコードは、Llama 3モデルをロードし、提供されたテキスト記事でファインチューニング(LoRA使用)を実行し、結果を保存します。 上記の入力値は、このコードに自動的に反映されます。 このコードをPythonファイル(例: `finetune_llama.py`)として保存し、実行してください。

import os
import torch
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType

# GPUの利用可能性を確認
print("GPUが利用可能か確認中...")
if not torch.cuda.is_available():
    print("GPUが見つかりません。Fine-tuningにはGPUが強く推奨されます。")
    # GPUがない場合は、ここでスクリプトを終了するか、CPUモードで続行するか選択できます。
    # exit("GPUがないため終了します。")
else:
    print(f"GPUが利用可能です: {torch.cuda.get_device_name(0)}")

# --- 1. モデルとトークナイザーのロード ---
# Llama 3モデルのパスを指定します。Hugging Faceのモデル名(例: "meta-llama/Llama-3-8B")
# またはローカルにダウンロードしたモデルのパスを指定してください。
MODEL_NAME = "meta-llama/Llama-3-8B" # ユーザーが入力したパスがここに挿入されます

print(f"モデルとトークナイザーをロード中: {MODEL_NAME}")

# 4bit量子化設定 (GPUメモリの節約に役立ちます)
# bnb_4bit_compute_dtypeは、Ampere以降のNVIDIA GPUに推奨されるbfloat16を使用しています。
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4", # NF4 (NormalFloat4) 量子化タイプ
    bnb_4bit_compute_dtype=torch.bfloat16 
)

# トークナイザーをロード
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
# Llama 3はデフォルトでbos_tokenを付与しないことがあるため、明示的に追加。
# また、padding_side='right'はLlamaモデルに推奨される設定です。
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# モデルをロードし、量子化設定を適用し、自動的にGPUにマッピングします。
model = AutoModelForCausalLM.from_pretrained(
    MODEL_NAME,
    quantization_config=bnb_config,
    device_map="auto", # 利用可能なデバイス(GPU)に自動的にモデルを分散
    trust_remote_code=True # リモートコードの実行を許可
)
print("モデルロード完了。")

# k-bit学習用にモデルを準備 (PEFTライブラリのため)
# gradient_checkpointingを有効にすることで、メモリ使用量をさらに削減できます。
model.gradient_checkpointing_enable()
model = prepare_model_for_kbit_training(model)
print("k-bit学習用にモデルを準備しました。")

# --- 2. データセットの準備 ---
# あなたのテキスト記事ファイルが格納されているディレクトリを指定します。
# 例: 'your_article_data/' の中に 'article1.txt', 'article2.txt', ... と置かれている場合
DATA_DIR = "./your_article_data/" # ユーザーが入力したパスがここに挿入されます

print(f"データセットをロード中: {DATA_DIR}")

# 'text'形式でデータセットをロードします。指定されたディレクトリ内のすべての.txtファイルを読み込みます。
# 各ファイルが1つのエントリとして扱われます。
try:
    dataset = load_dataset('text', data_files={'train': os.path.join(DATA_DIR, '*.txt')})
    print(f"データセットのサンプル数: {len(dataset['train'])}")
except Exception as e:
    print(f"データセットのロード中にエラーが発生しました。ディレクトリとファイル形式を確認してください: {e}")
    exit("データセットロード失敗。")

# データセットをトークン化する関数
# 長い記事をモデルの最大入力長に分割します。
def tokenize_function(examples):
    # Llama 3の最大入力長は通常8192ですが、お使いのGPUのVRAMに合わせて調整してください。
    # ここでは一般的な値として2048を設定しています。
    max_length = 2048 
    # truncate=Trueで最大長を超えるテキストを切り捨てます。
    return tokenizer(examples["text"], truncation=True, max_length=max_length)

# データセットをトークン化します。
# num_procはCPUコア数に応じて並列処理を行い、処理を高速化します。
tokenized_dataset = dataset.map(
    tokenize_function,
    batched=True,
    num_proc=os.cpu_count(),
    remove_columns=["text"] # 元のテキスト列は学習に不要になるため削除します。
)
print("データセットのトークン化が完了しました。")

# --- 3. PEFT (LoRA) の設定 ---
# LoRA (Low-Rank Adaptation) は、元のモデルの重みをフリーズし、
# 小さなアダプター層を追加して学習させることで、効率的にファインチューニングを行います。
# これにより、GPUメモリの使用量を抑えつつ、高い性能を実現できます。
lora_config = LoraConfig(
    r=16, # LoRAのランク。値を大きくすると表現力が増すが、メモリ消費も増える。
    lora_alpha=32, # LoRAのスケーリング係数。rの2倍程度が推奨されることが多いです。
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], # LoRAを適用する層。Llamaモデルで一般的な層。
    bias="none", # バイアスを学習しない設定。
    lora_dropout=0.05, # ドロップアウト率。過学習を防ぐために設定します。
    task_type=TaskType.CAUSAL_LM, # タスクタイプを因果言語モデルに設定。
)

# モデルにLoRAアダプターを追加します。
model = get_peft_model(model, lora_config)
print("モデルにLoRAアダプターを適用しました。")
model.print_trainable_parameters() # 学習可能なパラメータ数を確認します。

# --- 4. 学習の実行 ---
# 学習済みモデルを保存するディレクトリ
OUTPUT_DIR = "./llama3_finetuned_model/" # ユーザーが入力したパスがここに挿入されます

# 学習の設定
training_args = TrainingArguments(
    output_dir=OUTPUT_DIR,
    num_train_epochs=3, # エポック数。データセットのサイズと希望する精度に応じて調整してください。
    per_device_train_batch_size=1, # GPUあたりのバッチサイズ。VRAMが少ない場合は1に設定。
    gradient_accumulation_steps=4, # 勾配を蓄積するステップ数。実質的なバッチサイズは per_device_train_batch_size * gradient_accumulation_steps になります。
    optim="paged_adamw_8bit", # 8bit AdamWオプティマイザを使用し、メモリ効率を向上させます。
    save_steps=500, # 500ステップごとにモデルを保存します。
    logging_steps=100, # 100ステップごとにログを出力します。
    learning_rate=2e-4, # 学習率。
    fp16=True, # 混合精度学習を有効化 (GPUが対応している場合)。VRAM削減と高速化に寄与します。
    max_steps=-1, # num_train_epochsに基づいて学習します。
    group_by_length=True, # 同じ長さのシーケンスをグループ化し、パディングを削減します。
    lr_scheduler_type="cosine", # 学習率スケジューラーのタイプ。
    warmup_ratio=0.03, # ウォームアップ比率。
    report_to="none", # レポート先を指定しない (wandbなどを使用しない場合)。
)

# トレーナーの初期化
# data_collatorは、モデルの入力形式に合わせてデータを整形します。
trainer = Trainer(
    model=model,
    train_dataset=tokenized_dataset["train"],
    args=training_args,
    data_collator=lambda data: {
        'input_ids': torch.stack([f['input_ids'] for f in data]),
        'attention_mask': torch.stack([f['attention_mask'] for f in data]),
        'labels': torch.stack([f['input_ids'] for f in data]), # 因果言語モデルでは、入力自体がラベルとなります。
    },
)

# 学習の開始
print("Fine-tuningを開始します...")
trainer.train()
print("Fine-tuningが完了しました。")

# --- 5. 学習済みモデルの保存 ---
# LoRAアダプターのみを保存します。これにより、ファイルサイズが小さく、効率的に管理できます。
trainer.save_model(OUTPUT_DIR)
print(f"学習済みLoRAアダプターが '{OUTPUT_DIR}' に保存されました。")

# 保存したアダプターを使って推論を行う方法の例 (コメントアウトされています):
# このコードは、ファインチューニング後にモデルをロードして推論を行うための参考例です。
# from peft import PeftModel
#
# # 元のモデルをロード (学習時と同じ量子化設定を使用します)
# base_model = AutoModelForCausalLM.from_pretrained(
#     MODEL_NAME,
#     quantization_config=bnb_config,
#     device_map="auto",
#     trust_remote_code=True
# )
#
# # 保存したLoRAアダプターを元のモデルに結合します。
# peft_model = PeftModel.from_pretrained(base_model, OUTPUT_DIR)
#
# # 推論モードに設定します。
# peft_model.eval()
#
# # テキスト生成の例
# prompt = "ローカルPCでのLlama 3ファインチューニングの利点とは"
# inputs = tokenizer(prompt, return_tensors="pt").to("cuda") # 入力をGPUに移動
#
# with torch.no_grad(): # 勾配計算を無効化し、メモリ使用量を削減
#     outputs = peft_model.generate(
#         **inputs,
#         max_new_tokens=200, # 生成する新しいトークンの最大数
#         do_sample=True, # サンプリングによる生成を有効化
#         top_p=0.9, # Nucleusサンプリングの閾値
#         temperature=0.7, # 生成の多様性を制御する温度
#         eos_token_id=tokenizer.eos_token_id # 終了トークンID
#     )
# print("\n--- 生成されたテキスト ---")
# print(tokenizer.decode(outputs[0], skip_special_tokens=True))

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, ;;), )。, アウト, アシスタント, アダプター, あたり, アップ, あなた, いくつ, ウォーム, エポック, エラー, エントリ, オープン, オプティマイザ, お金, クラウドサービス, グループ, クン, ゲーミング, コード, コア, ここ, こと, コミュニティ, コメント, これ, サイズ, サンプリング, サンプル, シーケンス, スクリプト, スケーリング, スケジューラー, スタイル, ステップ, スペック, すべて, ソース, そこら, タイプ, ダウンロード, タスク, ため, チューニング, ツール, データ, データセット, テーマ, ディレクトリ, テキスト, デバイス, デフォルト, トー, トークナイザー, とき, どれ, トレーナー, ドロップ, バイアス, パス, バッチ, パディング, パラメータ, バランス, ファイル, ファイルサイズ, ファインチューニング, ファインチューニングコード, フリーズ, プロ, プロンプト, マシン, マッピング, メモリ, モード, モデル, もの, ユーザー, よう, ライター, ライブラリ, ラベル, ランク, リモート, レベル, レポート, ローカル, ロード, ログ, 一般, 一部, 上記, 不要, 世界, 世界中, 並み, 並列, 予算, 付与, 以下, 以降, 企業, 使い, 使用, 係数, 保存, 個人, 優秀, 入力, 公開, 共有, 具体, 処理, 出力, 分割, 分散, 分野, 初期, 利点, 利用, 制御, 削減, 削除, 創造, 加速, 助け, 効率, 動作, 勾配, 十分, 参考, 反映, 可能, 向上, 味方, 因果, 場合, 多様, 夢物語, 大幅, 大量, 失敗, 学習, 完了, 完全, 完璧, 実現, 実行, 実質, 寄与, 対応, 専門, 導入, 少量, 工夫, 希望, 常識, 強力, 形式, 必要, 思い, 性能, 手元, 手法, 技術, 抜群, 指定, 指示, 挿入, 推奨, 推論, 提供, 整形, 新た, 方法, 日々, 明日, 明確, 明示, 時代, 時間, 最大, 最新, 最適, 有効, 未知数, 本格, 格段, 格納, 構築, 様々, 比率, 民主, 活用, 活発, 消費, 混合, 済み, 温度, 準備, 無効, 無料, 特定, 特権, 現実, 理由, 環境, 生成, 発生, 登場, 的確, 相性, 短時間, 確認, 秘訣, 移動, 程度, 管理, 節約, 精度, 終了, 結合, 結果, 続行, 能力, 自体, 自分, 自動的, 蓄積, 表現, 言語, 計算, 記事, 設定, 許可, 調整, 費用, 軽量, 追加, 通常, 適用, 選択, 重み, 重要, 量子, 開始, 開発, 関数, 閾値, 非常, 高速, 高額, 魅力,

日本語形態素解析ライブラリをVibratoに切り替えました.自動タブ生成プラグインの話.

2025.06.10

Logging

おはようございます.日本語形態素解析ライブラリをVibratoに切り替えました.今までYahoo!APIを使用して日本語形態素解析を行って自動でタブ生成を行っていましたが、脱APIの一環としてVPSサーバにデータを送信して日本語文章を日本語形態素解析しタブ生成するように変更を加えました.

サーバが落ちていない限り動作する感じですね.

特に苦労した点は無いのですが、この頃さくらレンタルサーバーの通信が良くないのか分からないのですが通信エラーで処理が頻繁にエラーを出力するようになっています.

どうも、同時接続が多発するとなるようです、ちょっと困りものです、でもまぁ、660円で動いているですからね、あまり文句は言えないのですが困っています.

尚、ユーザーが管理画面からApacheサービスを再起動する唯一無二の方法はphp.iniを再保存することです、そうするとアパッチサービスが再起動します.そうすることにより原因不明の通信エラーが直ることもあります.

最後に日本語形態素解析ライブラリの参考にしたサイトを貼っときます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アパッチサービス, エラー, こと, サーバ, サーバー, サービス, サイト, さくら, タブ, データ, もの, ユーザー, よう, ライブラリ, レンタル, 一環, 不明, 使用, 保存, 処理, 出力, 動作, 原因, 参考, 同時, 唯一, 変更, 多発, 形態素, 感じ, 接続, 文句, 文章, 方法, 日本語, 明日, 最後, 無二, 生成, 画面, 管理, 自動, 苦労, 解析, 起動, 送信, 通信, 限り, 頻繁,

Devin(でびん)とかいう生成AIが凄いらしいのは知っていたけど知らんけど

2025.06.06

Logging

おはようございます.Devin(でびん)とかいう生成AIが凄いらしいのは知っていたけどついに自分が勤めている会社でもDevinを導入したみたいです.ひとつのリポジトリはDevinさんがほぼコードを書いていて何だか悲しい気持ちになりました?.

逆に言えばこういうDevinみたいな高性能な生成AIを使えば自分一人でも高機能なwebサービスが出来るだなって言う思いがあります、でも高機能なサービスが作れたとしてもそれを営業するノウハウ等がないので自分には結局意味がないのではないかと思います.

Devinさんに負けない高度なコードを書いても生産性では確実に劣っている気がします、ものの数秒で数千行のコードを書くことは人は出来そうにないので、正直なところDevinの性能が上がったら本当に必要なエンジニアは少なくなるでしょうね.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

エンジニア, コード, サービス, すひとつ, ところ, ノウハウ, びん, リポジトリ, 会社, 性能, 悲しい気持ち, 意味, 数千行, 数秒, , 生成, 生産性, 自分, 自分一人, 高性能,

自前のAPIでほぼ動かしている.利点はサービスの終了が無いところ

2025.06.05

Logging

おはようございます.自前のAPIでほぼ動かしている.利点はサービスの終了が無いところですが、VPSサーバー等でしか動かない代物なのでそこが難でサーバー代がかさみます.

そこを何とか低予算で運用したいのだけどもなかなか難しいのが現状です.因みにいまはVPSサーバーとレンタルサーバーを合わして1300円ぐらいを毎月支払っています.

自分にとっては1300円は高いし未だに生成AIの有料版は高いので無料版でしのいでいます.もっと稼げるように慣れば有料版とかを使ってみたいなって思います.

お給与が今の倍以上に慣れば良いのだけども、なかなか難しいそうと言う想いもあります.何時までこのような状況が続くか分からないのであまりお金の掛かることは控えています.

最近読んだ記事で老後2000万円では足りないとか言う記事を読んで絶望しています、老後が心配でいまをあまり楽しんでいないような気もしています.今を楽しみたいなーって!

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

お給与, サーバー, サーバー代, ば有料版, ば良い, レンタルサーバー, 代物, 低予算, 倍以上, 利点, 有料版, 未だ, 状況, 現状, 生成, 終了, 老後, 老後万円, 自前, ,

Photo by Adil on Pexels.com

AIでレコメンド記事が表示させるロジックを作りました.#機械学習って

2025.06.04

Logging

おはようございます.AIでレコメンド記事が表示させるロジックを作りました、前からそのような事を考えていたのですが、あまり機械学習のことを分かっていなかったのですが、以前、地域の商品券で「実務で役立つPython機械学習入門」を購入していたのを先日の休みにパラパラと捲っていたら、これだったらなんか出来そうだなって思いたち.

昨日の休みに生成AIともに作りました.生成AIが出力したコードに対して再度指示を出したり自分で直したりして上手く処理される形に落ち着きました.

Pythonコードは昨日の記事がある程度役に立つと思います、あのコードを元にブラッシュアップ(改善)した形になります.

自分で機械学習のことに手を出すことになるとは思っていなかったけど、これからはPythonの事もたまに試していこうと思います.

因みに過去記事を参照してもらったら分かるかもですが何度か機械学習にトライして挫折した経緯がありますが、今回は生成AIという物があるので生成AIよって噛み砕いた言葉とコードで何とか自分でも初級か中級ぐらいのことは出来そうな気もします.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, ブラッシュアップ, レコメンド記事, ロジック, 中級, 休み, 何度か機械学習, , 再度指示, 初級, 実務, , 改善, 機械学習, 機械学習入門, 生成, 生成とも, 程度役, 経緯, 言葉,

お知らせ.ブログの不具合をコンプリートしました.

2025.06.01

Logging

おはようございます、ブログの不具合をコンプリートしました.今までほったらかしにしていた、検索結果のページの不具合をこの度修正しました.

どんな不具合が発生していたかと言えば、次頁へ遷移せずシングルページの次頁へ遷移するという不具合です.この不具合は自分のテンプレートを作ってからずっと今まで発生したのを知っていたけど対応を放置していた不具合になります.

ちなみに分かりにくいと思いますが、関数名のポストが複数形に置き換わっただけです…じゃ直ぐに対応出来たのではというご指摘があるかと思いますが案外気が付かないですよ.生成AIに投げてやっと「あっ」と思ったわけです.

人には先入観とかいう物があるけど今のところ、生成AIは機械的なのでそういうミスは指摘してくれます.いやー便利ですよね本当に.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

ご指摘, シングルページ, テンプレート, ところ, ブログ, ページ, ミス, , 先入観, , 検索結果, 次頁, , , 生成, 自分, 複数形, 関数名,

万博の来場者数と5月23日以降の予測をバイブコーディングで作ってみました

2025.05.31

Logging

おはようございます.万博の来場者数と5月23日以降の予測をバイブコーディングで作ってみましたのでコードをシェアします.大阪万博の来場者数はYahooニュースの記事のデータを元にしています、其処から今後の予測を立ててもらいました.

https://zip358.com/tool/EXPO2025-OSAKA-KANSAI-JAPAN

因みに予測は簡易的なものなので、恐らく大きくハズレるとは思いますがそれなりの表が生成されるのが凄いなと思います.生成AIはOpenAIの無料枠を使用してデータと次のデータを元に10月13日までの予測を出力してという指示とJavaScriptやCSSを使用してグラフ化してという指示を出しただけで、コードを書いてくれます.

    const labels = [];
    const allVisitors = [];
    const generalVisitors = [];
    const staffVisitors = [];

    const rawData = [
      ["4/13", 146426, 22000], ["4/14", 70488, 17000], ["4/15", 63719, 16000], ["4/16", 73869, 15000],
      ["4/17", 82692, 15000], ["4/18", 93908, 15000], ["4/19", 108773, 15000], ["4/20", 95524, 16142],
      ["4/21", 99638, 17352], ["4/22", 103729, 17099], ["4/23", 99140, 17795], ["4/24", 108888, 17376],
      ["4/25", 110759, 17591], ["4/26", 122102, 17299], ["4/27", 102015, 16985], ["4/28", 121282, 17465],
      ["4/29", 97559, 17813], ["4/30", 101397, 17621], ["5/1", 105945, 17548], ["5/2", 104805, 17741],
      ["5/3", 120696, 17886], ["5/4", 136805, 16289], ["5/5", 126371, 16804], ["5/6", 76517, 16935],
      ["5/7", 91688, 16932], ["5/8", 105449, 18578], ["5/9", 105782, 19813], ["5/10", 128918, 21373],
      ["5/11", 121667, 18268], ["5/12", 117658, 17856], ["5/13", 123640, 18087], ["5/14", 129527, 17668],
      ["5/15", 129456, 17762], ["5/16", 132817, 17700], ["5/17", 123974, 16464], ["5/18", 117000, 16000],
      ["5/19", 129000, 17000], ["5/20", 125000, 18000], ["5/21", 129000, 19000], ["5/22", 134000, 18000],
      ["5/23", 157000, 18000]
    ];

    rawData.forEach(([date, total, staff]) => {
      labels.push(date);
      allVisitors.push(total);
      staffVisitors.push(staff);
      generalVisitors.push(total - staff);
    });

    const futureDays = 143;
    for (let i = 1; i <= futureDays; i++) {
      const futureDate = new Date(2025, 4, 13 + i); // 4月13日からスタート
      const label = `${futureDate.getMonth() + 1}/${futureDate.getDate()}`;
      labels.push(label);

      // 予測ロジック: 最近5日間の平均にランダムなゆらぎを加える
      const recentGeneral = generalVisitors.slice(-5);
      const avgGeneral = recentGeneral.reduce((a, b) => a + b, 0) / recentGeneral.length;
      const fluctuation = Math.sin(i / 5) * 5000 + (Math.random() - 0.5) * 8000;
      const predictedGeneral = Math.round(avgGeneral + fluctuation);

      const predictedStaff = 18000 + Math.round(Math.sin(i / 7) * 1000);
      const predictedTotal = predictedGeneral + predictedStaff;

      generalVisitors.push(predictedGeneral);
      staffVisitors.push(predictedStaff);
      allVisitors.push(predictedTotal);
    }

    const ctx = document.getElementById('visitorChart').getContext('2d');
    const chart = new Chart(ctx, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [
          {
            label: '来場者数(合計)',
            data: allVisitors,
            borderColor: 'rgba(75, 192, 192, 1)',
            backgroundColor: 'rgba(75, 192, 192, 0.1)',
            borderWidth: 2,
            tension: 0.3,
            fill: true
          },
          {
            label: '一般来場者数',
            data: generalVisitors,
            borderColor: 'rgba(255, 159, 64, 1)',
            backgroundColor: 'rgba(255, 159, 64, 0.1)',
            borderWidth: 2,
            tension: 0.4,
            fill: true
          },
          {
            label: '関係者数',
            data: staffVisitors,
            borderColor: 'rgba(153, 102, 255, 1)',
            backgroundColor: 'rgba(153, 102, 255, 0.1)',
            borderWidth: 2,
            tension: 0.4,
            fill: true
          }
        ]
      },
      options: {
        animation: {
          duration: 1500,
          easing: 'easeInOutQuart'
        },
        responsive: true,
        scales: {
          y: {
            title: {
              display: true,
              text: '人数'
            }
          },
          x: {
            title: {
              display: true,
              text: '日付'
            },
            ticks: {
              maxRotation: 90,
              minRotation: 45,
              maxTicksLimit: 50
            }
          }
        },
        plugins: {
          legend: {
            position: 'top',
          },
          title: {
            display: false
          }
        }
      }
    });

これは脅威だなって思う人もいると思いますが、自分は便利だなって思う方です.今後、数年でエンジニア職を奪われかねないという懸念もありますが、コード書きは無くならないじゃないかなって思う方です.理由は修正しないといけない事が必ず起きる事.動作はするが予期しない動作が発生した場合、素人には対応できないため.

未来は人が描いている斜め上の未来になる事が多く、どう転ぶかは「神のみぞ知る」だと思います.なのであまり脅威に思わずそうなった時に対応するというスタンスで良いのかなと.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, エンジニア職, スタンス, バイブコーディング, ミゾ, ランダム, 万博, 予測, 予測ロジック, 人数, 其処, 動作, 大阪万博, 懸念, 指示, 日付, 月日, 月日以降, 生成, 脅威,

デジタルアドレスAPIのコードを書いてみました.書いたのは

2025.05.30

Logging

おはようございます.デジタルアドレスAPIのコードを書いてみました.書いたのは生成AIだけど一度で上手く正しいコードが生成出来たわけではなくて二、三回の指示出しを行って下記のコードが生成されました.

デジタルアドレスのAPIを使用するには企業もしくは個人事業者で屋号を登録されている方でないとAPIのアカウント登録は今のところ出来ないので、自分はリファレンスと生成AIが出力したコードを見て恐らく正しく処理されるだろうと思ったのでgist.githubに公開しました.

尚、引数にIPアドレスを渡さないといけない所があるけれど、これはサーバーのIPアドレスになります.


<?php

class JapanPostAPIClient
{
    private string $clientId;
    private string $secretKey;
    private string $clientIp;
    private ?string $accessToken = null;
    private ?array $lastResponse = null;

    public function __construct(string $clientId, string $secretKey, string $clientIp)
    {
        $this->clientId = $clientId;
        $this->secretKey = $secretKey;
        $this->clientIp = $clientIp;
    }

    public function authenticate(): self
    {
        $url = 'https://api.da.pf.japanpost.jp/api/v1/j/token';
        $data = json_encode([
            'grant_type' => 'client_credentials',
            'client_id' => $this->clientId,
            'secret_key' => $this->secretKey
        ]);

        $headers = [
            "Content-Type: application/json",
            "x-forwarded-for: {$this->clientIp}"
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $response = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpcode !== 200) {
            throw new Exception("Token request failed with status {$httpcode}: {$response}");
        }

        $responseData = json_decode($response, true);
        $this->accessToken = $responseData['token'] ?? null;
        $this->lastResponse = $responseData;

        return $this;
    }

    public function searchCode(string $searchCode, array $params = []): self
    {
        if (!$this->accessToken) {
            throw new Exception("Access token is not set. Please call authenticate() first.");
        }

        $defaultParams = [
            'page' => 1,
            'limit' => 10,
            'choikitype' => 1,
            'searchtype' => 1
        ];

        $queryParams = http_build_query(array_merge($defaultParams, $params));
        $url = "https://api.da.pf.japanpost.jp/api/v1/searchcode/{$searchCode}?{$queryParams}";

        $headers = [
            "Authorization: Bearer {$this->accessToken}",
            "Accept: application/json"
        ];

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            throw new Exception("Search request failed with status {$httpCode}: {$response}");
        }

        $this->lastResponse = json_decode($response, true);
        return $this;
    }

    public function getJson(): string
    {
        return json_encode($this->lastResponse, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    }

    public function getArray(): ?array
    {
        return $this->lastResponse;
    }
}

// 使い方の例:
// $client = new JapanPostAPIClient('YOUR_CLIENT_ID', 'YOUR_SECRET_KEY', 'IPアドレス.xxx.xxx.xxx');
// echo $client->authenticate()->searchCode('1000001')->getJson();

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, アカウント登録, アドレス, コード, サーバー, デジタルアドレス, リファレンス, 下記, 企業, 使い方, , 個人事業者, 屋号, 引数, , 指示出し, 正しいコード, 生成, 自分,

いにしえのサイトの変数の命名を直しました.大部分を生成AIに直してもらった.

2025.05.29

Logging

おはようございます.いにしえのサイトの変数の命名を直しました.大部分を生成AIに直してもらいましたがまだ残ってはいます.因みにいにしえのサイトというのは、このサイトのことを指しています.

生成AIに「変数と関数の命名を直して」と頼むとプログラミングのコードはそのままで変数の命名や関数の命名を直してくれます.

その方法でいにしえのサイトのコードを書き換えて「駆け出し感」は少し消えている感じがします.

命名もそうですがプログラミングには命名規則という物があります.自分はそんな事を知らずにコードを書いてきたのですが、いまやっと命名規則などをちゃんとした職場にいます.

なのですが、今までのなんか癖が抜けきれていない部分があり、ちゃんとしたコードを昔から書いていたらという後悔があります.

最後に命名規則というのは何なのかという人のために命名規則をわかりやすく書いているQiitaの記事を載せておきます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

いにしえ, コード, プログラミング, 命名, 命名規則, 変数, 大部分, 少し, 後悔, 方法, , 最後, , 生成, , 職場, 自分, 部分, 関数, 駆け出し感,

Noteは飽和しているのでなかなか難しそうですね.

2025.05.27

Logging

おはようございます.Noteに2記事書いてみたのだけどもアクセス数は一桁台でした、これからユーザーを増やして収益化に繋げる道のりは遠そうだと判断したので一時停止するつもりです.

そしてNoteはもう生成AIで書かれた記事が無数にあり、もう人の書いた記事にたどり着くのが難しそうな状態になっていますよね.

記事が無数にあるということは競争相手が多くて、利益が薄まる傾向にあるのである一定の収入を得たい人には向かないプラットホームになっているように思えます.

ではブログはどうかと言えば同じだと思うだけど、Noteと違うところと言えばブログでレンタルサーバーなどを借りて運用している人は、カスタマイズ出来るので個性的なページが作れたり他のSNSへの連携などもしやすいし、投げ銭を募ることも可能なので結果、ブログの方が良い気がしている.

AI検索時代になった場合、どうなるのかが自分は見通せていないけど、ひとつ言えることは後発は厳しいということです.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アクセス数, プラットホーム, ユーザー, レンタルサーバー, 一定, 一桁台, 傾向, 利益, 厳しい, 収入, 収益化, 後発, 投げ銭, 検索時代, 状態, 生成, 競争相手, 結果, 連携, 道のり,

AIでは作れないものの例えばこの人の職業は今後数十年は安泰だと思いました.

2025.05.25

Logging

おはようございます、AIでは作れないものの例えばこの人の職業は今後数十年は安泰だと思いました.下記のような職業は全然、AIの影響は受けていないと思います.こんな感じでリアルで何かを創作する人達はあまり影響を受けないかと思います.

今から影響を受けてくるのは、エンジニアやデスクワークの方々なんですよ、これ結構な勢いで置き換わっていくと思います.いままでエンジニアしか出来なかったプログラミングの職業もAIを使用してちょっとしたアプリなんかを作れるようになって来ています.

いわゆるバイブコーディングという奴です.でもこれを修正することは素人には難しいので、結局のところプログラミングの素養が必要みたいです.いま一番影響を受けているのはデジタルなクリエイターだと思います.

ちょっとお金を支払えばAIでかなり良い物が作れるようになってきて…正直なところこれから大変になってきそうです.殆どのユーザーが生成AIで良いと思ったらそれはカナリ辛いものだと思います.

因みに何故、日本はAI生成の影響を受けにくいかといえば、生成AIの操作するユーザーインターフェースが英語で表記しているからなんだと思います.ここを取っ払うことが出来てくると浸透してくると自分は思っています.

AIで作ったものが溢れてきてしまうのは時間の問題なのかも知れない.

これからはリアルで創作するか、もしくはAIを上手く使用してモノづくりするべきなのかもと思います.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アプリ, エンジニア, カナリ辛いもの, クリエイター, デスクワーク, ところプログラミング, バイブコーディング, プログラミング, ユーザー, ユーザーインターフェース, 下記, 勢い, 影響, 方々, 殆ど, 生成, 素人, 素養, 職業, 英語,

見るだけでわかる!! 英語ピクト図鑑ってのを購入してみて

2025.05.23

Logging

おはようございます.見るだけでわかる!! 英語ピクト図鑑ってのを購入してみて思ったことを書いていきます.まず、図解は分かりやすいのですが自動詞や前置詞、他動詞とかいう用語が出てきてそこが知らないというか、もう全忘れしている自分にとっては難解でした.

難解でしたが生成AIが解説してくれたので何とかなりそうで、今回はなんか今までよりは続きそうな予感がします.

因みに英語が全く分からないわけでもないのだけど何となく理解できるけど、日本語にちゃんとした和訳が出来ないレベルなんですね、何を言わんとするかは分かるので頭の中で分かると言えば良いのかな.

そんな理由でちゃんとした訳が出来ないや基礎が全く出来ていないまま、生きてきたので結構コードを書くのが大変です.今でもどう書けばよいのやらと不安だらけ…そう言っても命名はしないといけないので命名しているけども自信がないですよね.

この頃は生成AIだよりになっている部分もあり前よりは命名が良くなってきている気がしています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, 予感, 他動詞, 命名, 和訳, 図解, 基礎, 日本語, , 理由, 生成, 用語, 置詞, 自信, 自動詞, 英語, 英語ピクト図鑑, , 部分, ,

5月は何故に広告収入が低くなるのだろうか?教えて

2025.05.22

Logging

おはようございます.5月は何故に広告収入が低くなるのだろうか?教えて生成AIと呪文を唱えるとそれらしい回答が返ってくる.いやー学校や師はいらないくなるのは時間の問題なのかも知れないなって思います.

もし自分が学生に戻ったら寝てるぞって思います、生成AIを使って学生時代は勉強してそうな気がします.

当時(高校時代)、自分は授業にノートをあまり取っていなかったけど、上位の中に入っていたのは教科書読めば理解できた人だったのでテスト期間中に詰め込み勉強していました.なおテスト期間は貫徹で受けていたので期間中に体重減少していました、、、.

当時に生成AIがあったら多分べんきょうよりも夢中で生成AIに分からない事を質問していたに違いないと思います.それが自ずと勉強になるからいいよね~今の世代は.

1. ゴールデンウィーク後のユーザー行動の変化

  • ゴールデンウィーク(5月初旬)は一時的にアクセスが増えることがありますが、休暇明けは一気にアクセスが減少しやすいです。
  • ユーザーは旅行・外出・学校・仕事に戻るため、広告を見る機会が減少します。

2. 広告主の予算が落ち着く時期

  • 4月(新年度)は企業の広告予算が豊富にある一方で、5月になると 「様子見」 モードに入る企業も多く、CPC(クリック単価)やCPM(インプレッション単価)が下がる傾向にあります。
  • 特にBtoB企業はゴールデンウィークで商談が止まり、5月の後半まではプロモーションが鈍化しやすいです。

3. 季節的な消費意欲の低下

  • 5月は「新生活」や「春のキャンペーン」が一段落した時期で、大きなイベント(バレンタイン・クリスマス・年末年始など)もないため、購買意欲が一時的に落ちます。
  • その結果、ECや物販系広告のCVR(コンバージョン率)が下がり、広告主が配信を絞ることもあります。

4. 期の中間でマーケティング戦略を見直す時期

  • 日本企業は3月末決算が多く、4月から新しい施策を試しますが、**5月はその効果を一旦評価する「調整期間」**として広告出稿を抑える傾向があります。

5. 海外要因

  • 海外(特にアメリカや欧州)の広告マーケットに依存している媒体やジャンルでは、5月に特別なイベントがないため、広告単価が低下しがちです。
  • 海外の大イベント(ブラックフライデーやクリスマスなど)は年後半に集中しているため、今は「低需要期」。

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

インプレッション単価, ゴールデンウィーク, コンバージョン率, ブラックフライデー, プロモーション, 一方, 一旦, 中間, 休暇明け, 低下, 呪文, 商談, 外出, 媒体, 広告出稿, 月初旬, 欧州, 生成, 貫徹, 購買意欲,

推し記事をXに頻度にポストする「ぷらぐいん」を作りました.

2025.05.20

Logging

おはようございます.昨日から自分の推し記事をXに頻度にポストする「ぷらぐいん」を作りました.コードは使い回し的な要素が多いのですが、上手く動いていたりしてアクセス数も普段より微量に多かったりして作ったのは良かったと思っています.

この頃、生成AIがコードを書いてくれるので、以前よりも早くコードが書けている気がしています.そのままでは使用できない時もあるけれど、良い感じです.ただ、無料枠のGeminiはテストコードやGitHubのgithub Actionなんかを作るのが難しい.

ここらへんは無料枠なので仕方がないかなって思っています.

生成AIが進化していくと人はいらない、ただAIの苦手な部分もあってUIやUXはどうも苦手な部分みたいですね.でもこれも時間の問題なのかも知れないなって思います、何故かというと人の意図を汲み取るのは今からいろいろな人が生成AIを使用する中でデータが蓄積されそれを元に改善されていくと思うので.

そのうち、生成AIとエンジニアの二人三脚でアプリやWEBサービス、ソフトウェアを個人が作り出す時代になるでしょうけど、アプリの飽和が起こりそうな気もしています.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アプリ, うち, エンジニア, コード, ここらへん, ソフトウェア, データ, テストコード, プラグイン, 二人三脚, , 微量, 意図, 推し記事, 普段, 無料枠, 生成, 要素, 頻度, 飽和,

AI 2027 シナリオ😱は当たらないかもね.

2025.05.18

Logging

おはようございます.IT業界ではAI2027の予測が一部当たったのでこの予測あたっているかもと言われているけど自分はこのシナリオ通りに未来がなるとは思えない.AGIなどは出来るかも知れないけど、実際、AIに自我が芽生えたら精神が安定しなくて鬱や幻覚を見出したりしそうです.

なので、AGI研究はストップしAI開発していくことになりそうです.数年で社会にインパクトを与えれるには生成AIが無料枠でかなり正しい返答が出来るようになれば変わると思いますが、いまはちょっと精度が良くないこともあり、まだIT界隈やその他、一部の業界が使い出したに過ぎない.なので、まだ微妙だと思っている方も多そうです.

結局のところ、AIは自我までは出来るけど自我の精神が安定した物になるかは未知数だと思っていますし精神を安定させるのが難しそうな気がしています.そして、自分はそもそも考えるということは組合の産物なのかも知れないなって思っていているので人間を超える発想は出来無さそうだなと思っています.ただAIは人よりも早く組合を試せるということに関しては人よりも現段階でも優れていると思います.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

インパクト, かなり正しい返答, シナリオ通り, 予測, 人間, 幻覚, 未来, 未知数, 業界, 現段階, 生成, 産物, 界隈, 発想, 研究, 精度, 精神, 組合, 自我, ,

自サイトのJavaScriptのエラーなどを直していた.#華金

2025.05.10

Logging

おはようございます.先日の自サイトのJavaScriptのエラーなどを直していましたが、なかなか難解だったです…エラーを生成AIに投げてみたところ、新たなエラーを生み出してくれましてそのバグを直すのに1時間ぐらい格闘してました.

生成AIありそうでないメソッドなんかをしらっと提案するので知らない人はこんなメソッドがあるだろうと思って実行してみるとそのありそうでないメソッドでコケるということも.

でもこの頃の生成AIは無料でもかなり良いソースコードを提案してくれるので本当に良いですけど、どんどんとエンジニアいらない説が濃厚になってきている気がします.これから一番いらないのは自分みたいなレベルのエンジニアなのかもしれない.

これからは生成AIを活用しながら開発していくのが主流になってくるでしょうね.特に新規案件はほとんどプロジェクトで使用していくようになってきています.特に大手はその流れが強いです.因みに今までのプロジェクトで生成AIを使用しても生産性は瀑上がりしません、生成AIはソースコードの意図を読み取る力や秘伝のソースコードなんかを読解する力は無さそうですね.

そこもカバー出来るようになれば人が要らなくなりそうです.今からエンジニアになろうとしている人は20年後には仕事を確実に人工知能に仕事を奪われている産業だと思った方が良いと思います.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

エラー, エンジニア, かなり良いソースコード, ソースコード, バグ, プロジェクト, メソッド, 主流, 人工知能, , 大手, 年後, 意図, 新規案件, 生成, 生産性, 産業, 秘伝, 自サイト, ,

notebooklm[ノートブックエルエム]のポッドキャスト風な生成はガチ

2025.05.04

Logging

おはようございます.notebooklm[ノートブックエルエム]のポッドキャスト風な生成はガチ(本当に凄い)です.notebooklmとは何かをGiminiを解説してもらった.

NotebookLMは、Googleが開発したAIを活用した情報整理ツールです。アップロードしたドキュメントに基づいて、AIが要約、説明、回答を生成することで、ユーザーの情報整理、理解、分析を支援します。まるで、自分専用のAIアシスタントを作るようなイメージです。

トイウワケデ、AIアシスタントなんだけど、今回、音声(日本語)機能が追加.この音声機能で自分が書いた記事を要約してもらった.出力結果はこちら、聞いてもらったら分かると思うのですがAI同士が自分が書いた記事に対して2つのAIが対話していてまるでラジオのMCのような感じです.

notebooklmで生成しました!

若干、音声の抑揚が変なところがあるモノの完璧に会話が成り立っているところが本当に凄い.これ無料使用出来るらしいけど、この機能の有料版使おうかなって思っていますが下記の懸念もあるので考え中です.

これを使用してYOUTUBEにUPしたら面白そうだなと思ったけれども、最初は新鮮さがあるけど徐々に飽きられそうだと思いました.やっぱり人には勝てないのかも知れない.人と区別がつかない状態になってから使用するのはありかも知れないな.

結構悩むところですね.生成AIの有料版、結構高いので未だに無料版で使用しているというのが庶民の現状だと思います.お金に余裕がありnotebooklmが面白そうだなとか便利そうと感じた方は課金もありかもですねー.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

アシスタント, トイウワケデ, ドキュメント, ノートブックエルエム, ポッドキャスト風, ラジオ, 会話, 出力結果, 区別, 同士, 回答, 庶民, 懸念, 抑揚, 未だ, 生成, 若干, 要約, 課金, 音声,

Photo by Amy Chandra on Pexels.com

tMDbのAPIを使用して今まで観た映画をリスト化してみましたよ.

2025.04.27

Logging

おはようございます.tMDbのAPIを使用して今まで観た映画をリスト化してみましたよ.sqliteの構造は下記になります.idはbigintと記載していますが、AUTO_INCREMENTの間違いです🐼.

Xにも呟きましたがAPIを使用して何かするのはこの頃飽きてきて触らなかったのですが、たまには触れてみようとコードを書いているうちに簡単に作れるようになってしまって少々物足りなさを感じています.

次回はAPIを使う側ではなくて作る側になろうと思っています.GW期間になると思いますが600円のレンタルサーバーのフリードメインを使ってツマラナイAPIみたいな失笑系を作ってみます.

なお、ソースコードの解説がなくてすみません、このソースコードを生成AIに投げてどのような処理か説明して言えば恐らく正解を教えてくれます.

明日へ続く

#真相をお話します.
少年と犬
Flow
curl -sS https://getcomposer.org/installer | php
composer require guzzlehttp/guzzle
composer require illuminate/database
<?php
require_once 'config.php';
require_once 'vendor/autoload.php';
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Capsule\Manager as DB;

class MovieList
{
    public $result = '';
    public $imgBasicUrl = 'https://image.tmdb.org/t/p/w500';
    public $filePath = FILEPATH_DIR_;
    public function __construct($filePath='')
    {
        $filePath = $filePath?$filePath:$this->filePath;
        if (!file_exists($filePath.'/movie-list.db')) {
            exit;
        }        
        $capsule = new Capsule();

        $capsule->addConnection([
            'driver'   => 'sqlite',
            'database' => $filePath.'/movie-list.db',
            'prefix'   => '',
        ]);

        $capsule->setAsGlobal();
        $capsule->bootEloquent();
    }

    public function getMovieList(string $q): void
    {
        $client = new \GuzzleHttp\Client();

        $response = $client->request('GET', 'https://api.themoviedb.org/3/search/multi?query=' . $q . '&include_adult=false&language=ja-JP&page=1', [
            'headers' => [
                'Authorization' => 'Bearer ' . API_KEY,
                'accept' => 'application/json',
            ],
        ]);
        $this->result = $response->getBody();
    }

    public function getResult(): void
    {
        $data = DB::table('list')->get();
        $lists = [];
        foreach ($data as $key => $value) {
           $result = unserialize($value->value);
            if(isset($result?->media_type) && $result->media_type == 'movie'){
                $lists[] = [
                    'id'=>$data[$key]->id,
                    'title'=>$result->title,
                    'img'=>$this->imgBasicUrl . $result->poster_path,
                ];
            }
        }
        print json_encode($lists);
    }

    public function saveCsvlist(): void
    {
        $fileData = explode("\n",file_get_contents('movie-list.csv'));
        $fileData = array_reverse($fileData);
        foreach($fileData as $line)
        {
            foreach(explode(',',$line) as $data){
                $q = urlencode($data);
                $movieList = new MovieList();
                $movieList->getMovieList($q);
                foreach((json_decode($movieList->result))?->results as $result){
                    DB::table('list')->insert([
                        'value' => serialize($result)
                    ]);
                }
            }
        }        
    }

    public function delete($id): void
    {
        
        DB::table('list')->where('id', '=', $id)->delete();
        print json_encode(['res'=>'true']);
    }

}
//(new MovieList())->saveCsvlist();
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
    if(!isset($_POST['id'])){
        (new MovieList())->getResult();
    }else{
        //(new MovieList())->delete($_POST['id']);
    }   
}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

```, コード, ソースコード, ツマラナイ, フリードメイン, レンタルサーバー, , , 処理, 失笑系, 少年, 構造, 次回, 正解, , 生成, 真相,

Camera+ recipe? ? scene: Cloudy ? crop: Golden ? effect: Redscale (77%) ? border: Round White

Reactでパスワード生成にバグがあって数値、記号が確実に入らなかったので.

2025.04.22

Logging

おはようございます.Reactでパスワード生成にバグがあって数値、記号が確実に入らなかったのでその修正を先日行いました.そういやそうだなってソースコードを見返して思った次第です…

修正したコードはこちらになります.その話とは別にVScodeにもAI補助が付いてから自分も生成AIと言う物を個人開発するときに使用するようになっただけど…

import RingLoader from "react-spinners/RingLoader";
import { useState } from "react";
import "./App.css";

function PasswordTmp() {
  const [passwordLength, setPasswordLength] = useState(8);
  const [password, setPassword] = useState("");
  const [includeSymbols, setIncludeSymbols] = useState(false);
  const [includeNumbers, setIncludeNumbers] = useState(false);

  function makePassword(passwordLength, includeSymbols, includeNumbers) {
    const lowercase = "abcdefghijklmnopqrstuvwxyz";
    const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const numbers = "0123456789";
    const symbols = "!@#$%^&*()_+[]{}|;:,.<>?";
    let characters = lowercase + uppercase; // 文字のセットを初期化
    if (includeNumbers) {
      characters += numbers; // 数字を追加
    }
    if (includeSymbols) {
      characters += symbols; // 記号を追加
    }
    let result = remakePassword(characters,includeNumbers,includeSymbols);
    setPassword(result);
  }

  function remakePassword(characters,includeNumbers,includeSymbols){
    let passwords = "";
    let NumbersChecking = true;
    let SymbolsChecking = true;
    for (let i = 0; i < passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      passwords += characters[randomIndex]; // ランダムな文字を選択
    }
    if (includeNumbers) {
      NumbersChecking = passwords.match(/[0-9]/g) ? true : false;
    }
    if (includeSymbols) {
      SymbolsChecking = passwords.match(/[\!@#\$%\^&\*\(\)_\+\[\]\{\}\|;:\,\.<>\?]/g) ? true :false;
    }
    return NumbersChecking && SymbolsChecking?passwords:remakePassword(characters,includeNumbers,includeSymbols);
  }


  return (
    <>
      <div>
        <h1>パスワード生成</h1>
        <p>
          <input
            type="number"
            value={passwordLength}
            placeholder="パスワードの長さ"
            max={99}
            min={3}
            onChange={(e) => setPasswordLength(e.target.value)}
          />
        </p>
        <p>
          <input id={'Symbols'}
            type="checkbox"
            value={1}
            checked={includeSymbols}
            onChange={(e) => setIncludeSymbols(e.target.checked)}
          />
          <label for={'Symbols'}>記号を含める</label>
        </p>
        <p>
          <input id={'Numbers'}
            type="checkbox"
            value={1}
            checked={includeNumbers}
            onChange={(e) => setIncludeNumbers(e.target.checked)}
          />
          <label for={'Numbers'}>数字を含める</label>
        </p>
        <button
          className="btn"
          onClick={() =>
            makePassword(passwordLength, includeSymbols, includeNumbers)
          }
        >
          パスワードを生成
        </button>
        <button
          className="btn"
          onClick={() => navigator.clipboard.writeText(password)}
        >
          パスワードをコピー
        </button>
        <p>生成されたパスワード: {password}</p>
        <p>パスワードの長さ: {passwordLength}</p>
        <p>記号を含める: {includeSymbols ? "はい" : "いいえ"}</p>
        <p>数字を含める: {includeNumbers ? "はい" : "いいえ"}</p>
      </div>
    </>
  );
}

export default PasswordTmp;

この頃、補完機能がとても「うざったく」思う時と「ありがとう」と思うときが存在していてなんとも言えない.特にウザって思うときは自分が望んでいないコードが出てきた時は正直困る.コードを直打ちしないといけないので今までの補完機能がやはり良いなと思います.

自分としては生成AIの補完機能をOFFに出来る機能がほしいところ、それがあればとてもコードを書くのは快適ですねー.あるのかなぁー🤔調べてみます.

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コード, コピー, セット, ソースコード, バグ, パスワード, パスワード生成, ほしいところ, ランダム, 修正, 初期化, 数値, 数字, 文字, 次第, 生成, 補助, 補完機能, 記号, 選択,

Reactの簡単なものなら今でも作れるのだけども.#簡単止まり.

2025.04.20

Logging

おはようございます.Reactの簡単なものなら今でも作れるのだけども簡単止まりなところを1UPしたいなと思っています.Xにもポストしたんだけどパスワード生成出来るものをReactで作ったのでソースコードを公開しますね.

Reactは基本そのままだとさくらレンタルサーバーなどでは動かないだけど、viteというモノを使用してビルドするとJavascriptに変換されたソースコードが出力されるので、それをレンタルサーバーにファイルアップロードする事によりレンタルサーバーでも動くようになります.

Reactにviteというモノを導入するに当たってDockerにUbuntuかcentOSなどを構築してその中にNodeJsとApache2を入れて自分はビルドしたモノを確認しています.

普通はNodeJsでサーバー立ててそちらで確認するのが普通なんだと思うのだけど、それだとレンタルサーバーで動いているかどうかが分からないので自分はビルド後のdistフォルダを中をApacheと紐づけて確認している形です.

トイウコトデ、ソースコードとサイトのリンクを貼っときます.

import RingLoader from "react-spinners/RingLoader";
import { useState } from "react";
import "./App.css";

function PasswordTmp() {
  const [passwordLength, setPasswordLength] = useState(8);
  const [password, setPassword] = useState("");
  const [includeSymbols, setIncludeSymbols] = useState(false);
  const [includeNumbers, setIncludeNumbers] = useState(false);

  function makePassword(passwordLength, includeSymbols, includeNumbers) {
    const lowercase = "abcdefghijklmnopqrstuvwxyz";
    const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const numbers = "0123456789";
    const symbols = "!@#$%^&*()_+[]{}|;:,.<>?";
    let characters = lowercase + uppercase; // 文字のセットを初期化
    if (includeNumbers) {
      characters += numbers; // 数字を追加
    }
    if (includeSymbols) {
      characters += symbols; // 記号を追加
    }
    let passwords = "";
    for (let i = 0; i < passwordLength; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      passwords += characters[randomIndex]; // ランダムな文字を選択
    }
    setPassword(passwords); // パスワードを更新
  }

  return (
    <>
      <div>
        <h1>パスワード生成</h1>
        <p>
          <input
            type="number"
            value={passwordLength}
            placeholder="パスワードの長さ"
            max={99}
            min={3}
            onChange={(e) => setPasswordLength(e.target.value)}
          />
        </p>
        <p>
          <input id={'Symbols'}
            type="checkbox"
            value={1}
            checked={includeSymbols}
            onChange={(e) => setIncludeSymbols(e.target.checked)}
          />
          <label for={'Symbols'}>記号を含める</label>
        </p>
        <p>
          <input id={'Numbers'}
            type="checkbox"
            value={1}
            checked={includeNumbers}
            onChange={(e) => setIncludeNumbers(e.target.checked)}
          />
          <label for={'Numbers'}>数字を含める</label>
        </p>
        <button
          className="btn"
          onClick={() =>
            makePassword(passwordLength, includeSymbols, includeNumbers)
          }
        >
          パスワードを生成
        </button>
        <button
          className="btn"
          onClick={() => navigator.clipboard.writeText(password)}
        >
          パスワードをコピー
        </button>
        <p>生成されたパスワード: {password}</p>
        <p>パスワードの長さ: {passwordLength}</p>
        <p>記号を含める: {includeSymbols ? "はい" : "いいえ"}</p>
        <p>数字を含める: {includeNumbers ? "はい" : "いいえ"}</p>
      </div>
    </>
  );
}

export default PasswordTmp;

https://zxz.sakura.ne.jp

明日へ続く

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

OFUSEで応援を送る

タグ

コピー, さくらレンタルサーバー, セット, ソースコード, トイウコトデ, ところ, パスワード, パスワード生成, ビルド後, フォルダ, ランダム, レンタルサーバー, 初期化, , 数字, 文字, 普通, 生成, , 記号,