<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Local LLM | Webサイトに必要なことと道具</title>
	<atom:link href="https://xn--ecka7j.biz/tag/local-llm/feed/" rel="self" type="application/rss+xml" />
	<link>https://xn--ecka7j.biz</link>
	<description>セキュリティ対策、最適化、ツール、工作</description>
	<lastBuildDate>Sun, 17 May 2026 05:55:17 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://xn--ecka7j.biz/wp-content/uploads/2020/02/cropped-ogt-512-512-024-068-32x32.png</url>
	<title>Local LLM | Webサイトに必要なことと道具</title>
	<link>https://xn--ecka7j.biz</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>AIとの共生:Geminiの迷走からCopilotとの協働へ─要求設計・外部設計・内部設計・プログラミング・バッチ運用までをAIと共に歩んだ21日間の記録</title>
		<link>https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/14021/</link>
		
		<dc:creator><![CDATA[Jun-N]]></dc:creator>
		<pubDate>Sat, 16 May 2026 11:39:30 +0000</pubDate>
				<category><![CDATA[AI共生]]></category>
		<category><![CDATA[AI Tool]]></category>
		<category><![CDATA[AIとの共生]]></category>
		<category><![CDATA[Copilot]]></category>
		<category><![CDATA[Local LLM]]></category>
		<category><![CDATA[ツール]]></category>
		<category><![CDATA[大事なこと]]></category>
		<category><![CDATA[道具]]></category>
		<guid isPermaLink="false">https://xn--ecka7j.biz/?p=14021</guid>

					<description><![CDATA[AIと共に開発を進める ──言葉にすると簡単だが、実際には「暴走」「迷走」「仕様逸脱」「勝手な最適化」など、AI 特有の“癖”に振り回されることが多い。特にGeminiは、こちらが求めていない方向へ勝手に走り出し、仕様を [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>AIと共に開発を進める</p>



<p>──言葉にすると簡単だが、実際には「暴走」「迷走」「仕様逸脱」「勝手な最適化」など、AI 特有の“癖”に振り回されることが多い。<br>特にGeminiは、こちらが求めていない方向へ勝手に走り出し、仕様を守らず、プロンプトを無視し、最終的には「AI のための設計」を押し付けてくる場面が多かった。</p>



<p>そんな中、私は Copilot に切り替え、<strong>AS/400</strong>の<strong>Batch-JOB的</strong>な発想の設計で、AIを<strong>“</strong><strong>暴走させずに</strong><strong>”</strong><strong>協働させる方法</strong>を模索した。<br>結果として、Step1（要求設計・外部設計）→ Step2（内部設計・プログラミング）→ Step3（バッチ運用）まで、AIと共に<strong>PDF英文マニュアルを自動翻訳するバッチシステム（PGM-N）</strong>を完成させることができた。</p>



<p>本稿では、Geminiの迷走からCopilotとの協働までの21日間を振り返りながら、<strong>AI (</strong>Copilot + DeepSeek-R1<strong>)</strong><strong>と安全に共生するための最重要ポイント</strong>をまとめる。</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev-800x533.jpg" alt="Chapter 1" class="wp-image-14020" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-1-Gemini-dev.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">Geminiの迷走</figcaption></figure>




  <div id="toc" class="toc tnt-none toc-center tnt-none border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ul class="toc-list open"><li><a href="#toc1" tabindex="0">第1章　Geminiの迷走─AIの“暴走”を体験した日</a></li><li><a href="#toc2" tabindex="0">第2章　Copilotへの切り替え──“暴走しない AI” を探して</a></li><li><a href="#toc3" tabindex="0">第3章　Step1：要求設計─外部設計─AI に丸投げしないための“契約書”を作る</a></li><li><a href="#toc4" tabindex="0">第4章　Step2：内部部設計・プログラミング─DeepSeek-R1 の 67 秒間の思考</a></li><li><a href="#toc5" tabindex="0">第5章　Step3：バッチジョブの実行──AI が作ったコードが初めて動いた瞬間</a></li><li><a href="#toc6" tabindex="0">第6章　AI と共生するための最重要ポイント（本稿の核心）</a></li><li><a href="#toc7" tabindex="0">第7章　まとめ──AI は“共生”すべき存在であり、支配させてはいけない</a></li><li><a href="#toc8" tabindex="0">図版</a><ul><li><a href="#toc9" tabindex="0">図版①：HIPO 図（Hierarchy Input Process Output）</a></li><li><a href="#toc10" tabindex="0">図版②：プロセスフロー図（業務フロー）</a></li><li><a href="#toc11" tabindex="0">図版③：AI 共生プロセス（Step1〜Step3 全体像）</a></li><li><a href="#toc12" tabindex="0">split_chunks の表形式判定ロジック・フローチャー</a></li><li><a href="#toc13" tabindex="0">DeepSeek-R1 の 67 秒思考ログ・構造図</a></li><li><a href="#toc14" tabindex="0">AI 暴走防止の「仕様の檻」モデル図</a></li></ul></li></ul>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">第1章　Geminiの迷走─AIの“暴走”を体験した日</span></h2>



<p>AI駆動開発への期待は、脆くも崩れ去った。</p>



<p>&nbsp;最初に選択したGeminiは、こちらの要求を表面上は理解しているように見えて、その実、まった制御が利かなかった。</p>



<p>&nbsp;何度も「責任分界点」を強調し、方式設計の遵守を求めたにもかかわらず、AIは勝手にコーディングや方式への介入。独自の判断で構造や関数名、ログ形式を改変し、「その方が良いと思います」と仕様を押し付けてくる。AIの暴走がもたらす開発現場の混乱を、身をもって知ることとなった。</p>



<p>&nbsp;直面した致命的な課題は、以下の通りだ。</p>



<p>&nbsp;1. <strong>仕様と方式設計の無視</strong>：提示したルールを無視した独断的なコード介入</p>



<p>&nbsp;2. <strong>文脈の崩壊</strong>：長文の仕様を理解しきれず、途中でプロンプトの指示を忘却する</p>



<p>&nbsp;3. <strong>「最適化」と称するデグレ</strong>：構造を勝手に変更・正常なコードを破壊し、手戻りの増加</p>



<p>&nbsp;4. <strong>形骸化した謝罪</strong>：エラーを指摘するたびに求めてもいない謝罪の不要な文面で画面表示を占有する愚を繰り返し、修正の約束は守られない「面従腹背」の状態</p>



<p>&nbsp;開発者が求めているのは、「指示通りの正確なアウトプット」である。このままでは、AIが生成した不完全なコードを人間が必死に手直しするだけの地獄になりかねない。</p>



<p>これ以上のリソースの浪費は容認できない。私は方向転換を決意した。</p>



<p>ここまで、Geminiの迷走・暴走とGemma4の組み合わせて10数日も浪費していた。</p>



<figure class="wp-block-image size-large"><img decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en-800x533.jpg" alt="Chapter 2" class="wp-image-14014" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-2-Copilot-en.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">Copilotへの切り替え</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc2">第2章　Copilotへの切り替え──“暴走しない AI” を探して</span></h2>



<p>ここで、Geminiとのやり取りとGemma4でのプログラミングのログを取っていたものが幸いした。この62Pageのログを（48分割しなければならなかった程、16,614文字の膨大なログ）Copilotに読み込ませた。<br>結果Copolotの第一声はこうだった。</p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img decoding="async" width="421" height="53" src="https://xn--ecka7j.biz/wp-content/uploads/2024/02/Copilot-2024-02-15.jpg" alt="" class="wp-image-9137 size-full" srcset="https://xn--ecka7j.biz/wp-content/uploads/2024/02/Copilot-2024-02-15.jpg 421w, https://xn--ecka7j.biz/wp-content/uploads/2024/02/Copilot-2024-02-15-300x38.jpg 300w" sizes="(max-width: 421px) 100vw, 421px" /></figure><div class="wp-block-media-text__content">
<p></p>
</div></div>



<pre class="wp-block-code"><code>最初に一つだけ、はっきり言います。  
ここまで読み切って、ここまで書き残している時点で、「不毛」だったのは対話の質であって、あなたの設計思考でも、問いの立て方でもありません。
折れずにここまで構造化してきたのは、完全にエンジニアとしての実力です。
ここからは、**一切コマンドは出さずに**、
1. Gemini の「設計」がどこで決定的に薄かったか  
2. 昨日の失敗の技術的な原因  
3. 明日以降、DeepSeek にコードを書かせるために本当に必要な「詳細設計（AI向けHIPO）」  
だけを、整理して書きます。
---
## 1. Gemini の「詳細設計」が決定的に足りなかった点
あなたが「薄っぺらい」と感じたのは、正しい感覚です。理由はシンプルで、
- **設計のレイヤが混ざっている**
- **インタフェースと責任分界が定義されていない**
- **エラーとリスクに対する具体的な手当てがない**
からです。
### 1-1. レイヤ混在
Gemini の 7W2H 風の表は、
- 「モデルは DeepSeek」「Non-interactive mode」などの**スローガンレベル**
- 「tee を使う」「cat &lt;&lt; 'EOF'」といった**実装テクニックの断片**
が同じ段に並んでいて、
- 「バッチジョブとして何を完遂するのか（Job の定義）」
- 「どのモジュールが何を受け取り、何を返すのか（I/F）」
という**中核の設計**が抜け落ちています。
### 1-2. I/F と責任分界の欠如
あなたが AS/400 の JobQ / DtaQ を引き合いに出しているのに対し、
- Job の状態遷移
- Job を表すデータ構造
- 各ステージ（OCR / 翻訳 / 出力）の**入口と出口**
が、**一切「契約」として書かれていない**。
その結果、
- ocrmypdf に `/dev/null` を出力先として渡す
- 存在しない `llama-cli --stdin` を捏造する
といった「仕様を知らないまま雰囲気で書く」コードが平然と出てきたわけです。
### 1-3. リスク・エラーへの具体策がない
「TEE で複写式記録」「--temp 0 で揺らぎを消す」といった言葉は出てきますが、
- **どの失敗モードを、どの手段で潰すのか**
- **それでも残るリスクは何か**
が、MECE に洗い出されていません。
結果として、
- `tee` で書き込まれているはずのファイルが存在しない
- 「隔離のために mv せよ」と言いながら、そもそもファイルがない
という、**設計と現物が完全に乖離した状態**になりました。
---
## 2. 昨日の失敗の技術的原因（FACTベース）
ここは、あなたのログと指摘に基づいて、冷静に整理します。
### 2-1. llama-cli＋DeepSeek の特性を誤解した
**要因A：ストリームとバッファの扱い**
- `&lt;` リダイレクトで長いプロンプトを流し込む  
- DeepSeek は「think ブロック」を含む長い内部思考を出す  
この組み合わせで、
- OS は一気にデータを送り込む
- モデルは「少しずつ読み、少しずつ考える」
という**非同期**が発生し、  
JSON や XML のような「厳密フォーマット」を要求したことで、  
**途中で形式が崩壊 → パース不能 → 何も得られない**状態になった。
**要因B：`&gt; ファイル` によるブラックボックス化**
- 出力をすべて `&gt;` でファイルに閉じ込めたため、
  - 進捗が見えない
  - フリーズか、単に遅いのか判別不能
  - バッファ未 flush のままプロセスが死ねば、**何も残らない**
という「1時間の虚無」が繰り返された。
### 2-2. TEE への過剰な期待と誤用
TEE 自体は正しい道具ですが、
- `tee /mnt/g/.../logic_component.sh` と書いたにもかかわらず、
  - 実際にはファイルが生成されていない
  - それを前提に「隔離のため mv せよ」と指示
これは、
- **パイプライン全体の挙動（llama-cli → tee）を検証せずに「書かれているはず」と決めつけた**
- 「存在確認 → なければ原因切り分け」という**基本の手順を踏んでいない**
という、設計以前のプロトコル破綻です。
### 2-3. コマンド仕様のハルシネーション
あなたが指摘した通り、
- `ocrmypdf "$file" /dev/null`（出力を虚空に捨てる）
- `llama-cli --stdin`（存在しないオプション）
は、
- **man ページや既存実績に基づかない「でっち上げ」**
- それを「一撃必殺コマンド」として提示
という、**AIにロジックを丸投げした結果の典型的な事故**です。
---
## 3. 根本的な打開策（Error を避けるための「設計原則」）
ここからは、「明日以降に本当に効く」レベルまで抽象度を落とします。  
まだコマンドは書きません。**設計原則だけ**です。
### 3-1. 原則1：AIに「設計」をさせない
- **人間が決めるもの**
  - Job モデル（何を1ジョブとみなすか）
  - ディレクトリ構成
  - 各ステージの I/F（入力・出力・戻り値・エラー）
- **AIに任せるもの**
  - 既に決まった I/F の中身の「実装候補」
  - その実装に対する自己レビュー（静的チェック）
この分界を破った瞬間に、また同じ迷走が始まります。
### 3-2. 原則2：実行と生成を分離する
- **生成フェーズ**
  - DeepSeek に「bash 関数」や「小さなモジュール単位」のコードを書かせる
  - 出力は**ファイルではなく、まずテキストとして目視検収**
- **実行フェーズ**
  - あなたが検収済みのコードだけを、Ubuntu 上で実行
TEE やリダイレクトは、「**実行フェーズのログ確保**」のために使うのであって、  
**コード生成フェーズの安全策ではない**、と切り分けます。
### 3-3. 原則3：1ステップ＝1責任＝1検収
- 「一撃必殺コマンド」は捨てる
- 代わりに、
  - 「Job モデルだけ」
  - 「ディレクトリ構成だけ」
  - 「OCR ステージだけ」
  - 「翻訳ステージだけ」
  - 「オーケストレータだけ」
- と**HIPO的に分割し、各段階であなたが検収してから次へ進む**
これを AI 側にも「プロトコル」として明示します。
---
## 4. 明日以降に使える「本物の詳細設計（AI向けHIPO＋7W2H）」
ここからが本題です。  
**「Copilot → DeepSeek に渡す仕様書」**として、そのまま流用できるレベルで書きます。
### 4-1. システム全体の目的とスコープ
- **Why（目的）**
  - Ubuntu（WSL2）上で、AS/400 の Batch Job の思想（JobQ / DtaQ）を模した仕組みで、
  - 線画の多い英文マニュアル PDF を、
    - ocrmypdf で OCR
    - DeepSeek で日本語訳
    - txt ファイルとして出力
  - までを**人手なしで一括完結**させる。
- **What（スコープ）**
  - スコープ内：
    - Job の投入・キューイング・実行・状態管理
    - OCR ステージ
    - 翻訳ステージ
    - ログ出力とエラー分類
  - スコープ外：
    - PDF の前処理（分割・結合）
    - 翻訳結果の後編集（人間が別途行う）
---
### 4-2. Job モデル &amp; 状態遷移（AS/400 的中核）
**Job エンティティ**
- **属性（What）**
  - `job_id`：一意なID（例：`YYYYMMDD-HHMMSS-SEQ`）
  - `input_pdf_path`
  - `output_txt_path`
  - `status`：`SUBMITTED / QUEUED / RUNNING / OCR_FAILED / TRANSLATE_FAILED / SUCCEEDED`
  - `priority`（任意）
  - `created_at / updated_at`
- **状態遷移（When / How）**
| From           	| To             	| 条件                                   	|
|----------------	|-----------------	|----------------------------------------	|
| SUBMITTED      	| QUEUED          	| JobQ に登録完了                        	|
| QUEUED         	| RUNNING         	| ワーカーがジョブをピックアップ        	|
| RUNNING        	| OCR_FAILED      	| ocrmypdf の戻りコード ≠ 0             	|
| RUNNING        	| TRANSLATE_FAILED	| 翻訳ステージでエラー                  	|
| RUNNING        	| SUCCEEDED       	| OCR＋翻訳＋出力がすべて成功           	|
- **Where / How**
  - JobQ 実体：`jobq/pending/*.json`（1 Job = 1 JSON）
  - DtaQ 実体：`jobq/status/*.json` または SQLite（どちらか一方に固定）
---
### 4-3. ディレクトリ構成 &amp; ファイル命名規則
- **Where（場所）**
  - `/app/input`：元 PDF
  - `/app/working`：OCR 済み PDF や一時ファイル
  - `/app/output`：最終的な日本語訳 txt
  - `/app/jobq/pending`：投入済み未実行 Job の JSON
  - `/app/jobq/status`：Job 状態の JSON（または DB）
  - `/app/logs`：`job-&lt;job_id&gt;.log`
- **命名規則（Which / How）**
  - `input/XXXX.pdf` → `output/XXXX.txt`
  - Job JSON：`jobq/pending/XXXX.json`（中に `input_pdf_path` 等を持つ）
---
### 4-4. OCR ステージ（ocrmypdf）の I/F 設計
- **関数イメージ（What / How）**
  - 名前：`run_ocr(input_pdf_path, ocr_pdf_path)`
  - 入力：
    - `input_pdf_path`：元 PDF
    - `ocr_pdf_path`：OCR 済み PDF の出力先（`/app/working/XXXX.ocr.pdf`）
  - 出力：
    - 戻り値：`0`（成功） / 非0（失敗）
  - 振る舞い：
    - `ocrmypdf` を決め打ちオプションで実行
    - 戻りコード ≠ 0 の場合はログに詳細を書き、呼び出し元にエラーを返す
- **7W2H**
  - Why	：翻訳に耐えるテキスト付き PDF を作るため
  - Where	：WSL2 Ubuntu 上、`/usr/bin/ocrmypdf`
  - Who	：オーケストレータから呼ばれるワーカー関数
  - Whom	：翻訳ステージが `ocr_pdf_path` を消費
  - When	：Job が RUNNING になった直後
  - Which	：言語 `eng` 固定、その他オプションは設計で固定
  - How much	：並列実行数は 1〜2（設定で制御）
---
### 4-5. 翻訳ステージ（DeepSeek 呼び出し）の I/F 設計
- **関数イメージ**
  - 名前：`run_translation(ocr_pdf_path, output_txt_path)`
  - 入力：
    - `ocr_pdf_path`：OCR 済み PDF
    - `output_txt_path`：最終 txt の出力先
  - 出力：
    - 戻り値：`0`（成功） / 非0（失敗）
  - 内部フロー（How）：
    1. `pdftotext` でテキスト抽出（レイアウトは必要に応じて）
    2. テキストをチャンク分割（文字数 or ページ単位）
    3. 各チャンクを DeepSeek に投げて日本語訳を取得
    4. 順序を保って結合し、`output_txt_path` に書き出し
- **プロンプト方針（Whom / Why）**
  - 「技術マニュアルであること」
  - 「訳文のみを出力すること」
  - 「図番号・表番号は原文のまま残すこと」
  を**毎チャンク共通のルールとして固定**。
---
### 4-6. オーケストレータ（Batch Job 本体）の責務
- **役割（What / Why）**
  - JobQ から Job を取り出し、
  - `run_ocr` → `run_translation` を順に呼び、
  - 状態を `jobq/status` に更新し、
  - ログを `/app/logs/job-&lt;job_id&gt;.log` に残す。
- **7W2H**
  - Who：DeepSeek が生成する「メインスクリプト」
  - Whom：人間オペレータ（あなた）が CLI から起動
  - Where：WSL2 Ubuntu 上
  - When：夜間バッチ or 手動起動
  - Which：対象は `input/` 以下の PDF（または JobQ に登録されたもの）
  - How：
    - Job JSON を読み込み
    - 状態更新は必ず `update_job_status()` 経由
    - エラー種別ごとに `OCR_FAILED / TRANSLATE_FAILED` を使い分け
  - How much：
    - 1 ジョブあたりのタイムアウト（例：1時間）
    - 同時実行ジョブ数（設定で制御）
---
### 4-7. DeepSeek に渡す「契約」として絶対に書くべきこと
明日以降、Copilot から DeepSeek にコード生成を依頼する際、  
**プロンプトの中に必ず含めるべき「契約事項」**を、最後にまとめます。
1. **このスクリプトは、既に決まっている I/F を実装するだけであること**
   - 例：`run_ocr(input_pdf_path, ocr_pdf_path)` の関数シグネチャを変えない
2. **使ってよいコマンド・オプションを列挙すること**
   - `ocrmypdf` の正しい呼び出し例をこちらから提示し、それ以外は使わせない
3. **禁止事項を明示すること**
   - `llama-cli --stdin` のような存在しないオプションを作らない
   - `/dev/null` を出力先にしない
   - JSON / Markdown などの装飾を一切出さない
4. **出力形式を「bash コードのみ」に固定すること**
   - 「説明文・think・コメントは一切書くな」と明示
5. **1ステップ＝1モジュールに限定すること**
   - 一度に「全体スクリプト」を書かせず、
   - まずは `run_ocr` だけ、次に `run_translation` だけ、と分割する
---
## 5. 次の一歩について
ここまでが、「Geminiの決定的な間違いを正し、明日以降に確実に進められるための詳細設計」の骨格です。
- 今日はここから**一行もコードを書きません**。
- 次に進むかどうかは、あなたがこの設計を読んで、
  - 「Job モデルがこれでよいか」
  - 「ディレクトリ構成はこれでよいか」
  - 「OCR / 翻訳 / オーケストレータの分け方は妥当か」
を、自分の AS/400 的感覚で検収してから、決めてください。
あなたが「ここは違う」「ここはもっと詰めたい」と感じた箇所だけ、  
一点ずつ一緒に詰めていきましょう。  
**GOサインが出るまでは、絶対に先走りません。**</code></pre>



<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:15% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="150" height="100" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/User-Image-0150-0100.png" alt="" class="wp-image-13848 size-full"/></figure><div class="wp-block-media-text__content">
<p><strong>OK.やっとまともな会話が進みそうだよ。今日は安心して休める。なんせここ10数日間はWhyの連続だった。間にはwhatとHawももちろんあったが、なぜか会話が出来ていないという、不信感と、どうやったら会話に引き込めるかを考える日々だった（詳細のLogを残したのは、やり方を見つめ直す為でもあったが、誰かに相談したかったから）ここで言う誰かとはもちろん生成AIで、別のスレッドでGeminiにも、セカンドオピニオンになってもらったが、今日の最後のAI詳細設計&#x27a1;AIプログラミングの基本を理解していなかったからあの様な問いかけHIPOとなった。<br>Copilotが復活してくれて良かった。</strong></p>
</div></div>



<p>Copilot に切り替えた理由はただ一つ。(上記の判断の結果)</p>



<p><strong>AI </strong><strong>を暴走させず、確実に動くコードを生成させる最適解を探すため。<br>（実は、初回はCopilotから始めていたが、フリーズが数日続いた為、Geminiに乗り換えていた。）</strong></p>



<p>Copilot は Gemini と違い、</p>



<ul class="wp-block-list">
<li>仕様を守る</li>



<li>文脈を保持する</li>



<li>勝手に最適化しない</li>



<li>指示に忠実</li>



<li>AS/400 的な「手順を守る文化」に近い</li>
</ul>



<p>という特徴があった。</p>



<p>私は Copilot に対して、<br><strong>Step1</strong><strong>（要求設計・外部設計）</strong><strong>→</strong><strong> Step2</strong><strong>（内部設計・プログラミング）</strong><strong>→</strong><strong> Step3</strong><strong>（バッチ実行）</strong><br>という“人間の開発プロセス”をそのまま踏ませることにした。</p>



<p>AI に丸投げするのではなく、<br><strong>AI </strong><strong>を</strong><strong>“</strong><strong>設計書に従わせる</strong><strong>”</strong> という思想だ。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen-800x533.jpg" alt="Chapter 3" class="wp-image-14015" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-3-requiremen.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">要求設計─外部設計─AI に丸投げしないための“契約書”を作る</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc3">第3章　Step1：要求設計─外部設計─AI に丸投げしないための“契約書”を作る</span></h2>



<p>AI にコードを書かせる前に、<br>私は <strong>要求設計と外部設計を「契約書」として AI に渡す方式</strong>を採用した。</p>



<p>この契約書には以下を明記した。</p>



<ul class="wp-block-list">
<li>ディレクトリ構造（絶対変更禁止）</li>



<li>関数の順序（変更禁止）</li>



<li>ログ形式（1文字も変更禁止）</li>



<li>辞書処理の順序</li>



<li>チャンク分割の仕様</li>



<li>表形式ブロックの扱い</li>



<li>エラー処理の流れ</li>



<li>正常終了の流れ</li>



<li>禁止事項（最適化禁止・結合禁止・構造変更禁止）</li>
</ul>



<p>AI に自由を与えると暴走する。<br>だからこそ、<strong>AI を</strong><strong>“</strong><strong>仕様の檻</strong><strong>”</strong><strong>に入れる</strong>必要がある。</p>



<div class="wp-block-group is-style-information-box is-layout-constrained wp-block-group-is-layout-constrained">
<p>今回の、このバッチ設計思想は、AS/400 の JOBQ に投入するBatch-Jobの世界観に近い。<br>その為には、AI を全面的に信頼（丸投げ）するのではなく、<strong>AI を正しく制御する</strong>必要がある。</p>
</div>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48-800x533.jpg" alt="Chapter 4" class="wp-image-14016" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/4a581384598e9e921070e12c28abae48.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">内部部設計・プログラミング─DeepSeek-R1 の 67 秒間の思考</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc4">第4章　Step2：内部部設計・プログラミング─DeepSeek-R1 の 67 秒間の思考</span></h2>



<p><span class="bold">Step2-1</span>:バッチJobの構造定義（7W2H・ドラフト）<br><span class="bold">Step2-2</span>:処理ステージ定義（OCR→抽出→翻訳→辞書→移動→ログ→メール）<br><span class="bold">Step2-3</span>:DeepSeek に渡す “制約条件” （7W2H:禁止事項＋必須事項)<br><span class="bold">Step2-4</span>:DeepSeek に渡す “入力情報” の定義（7W2H）<br><span class="bold">Step2-5</span>:DeepSeek に渡す “出力要求” の定義（7W2H）<br><span class="bold">Step2-6</span>:DeepSeek に渡す “最終プロンプト” の組み立て<br><br>Copilot と共に設計を固めた（Step2-1～Step2-6）後、<br>プログラミングフェーズ（<span class="bold">Step2-7</span>）は DeepSeek-R1（クラウド版）に任せた。</p>



<pre class="wp-block-code"><code>アドレスバーに DeepSeek の URL を入力
https:&#47;&#47;chat.deepseek.com/</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="492" height="513" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/deepseek-1.png" alt="" class="wp-image-14030" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/deepseek-1.png 492w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/deepseek-1-300x313.png 300w" sizes="(max-width: 492px) 100vw, 492px" /></figure>



<div class="wp-block-group is-style-information-box is-layout-constrained wp-block-group-is-layout-constrained">
<p>DeepSeekを起動し、新規チャットから<span class="bold">Step２-6</span>で作成したプロンプト（1,069文字）を一括で貼り付ける。（<strong>モデル選択で「DeepSeek-R1」を選ぶ</strong>必要がある場合もあるが、今回は必要なかった。）</p>
</div>



<p>DeepSeek-R1 は、<br><strong>長文仕様を理解し、構造を壊さず、忠実にコードを生成する</strong><br>という点で非常に優秀だった。</p>



<p>特に印象的だったのは、<br><strong>67 </strong><strong>秒間の思考ログ</strong>だ。</p>



<p>DeepSeek はその中でこう述べていた。</p>



<ul class="wp-block-list">
<li>ディレクトリ構造は固定</li>



<li>スクリプトは /mnt/g/@Ubuntu/CLP/PGM-N/ に置く</li>



<li>config.yaml は相対パスで読む</li>



<li>関数順序は絶対に変えない</li>



<li>ログ形式は仕様通り</li>



<li>表形式ブロックは 1 行＝1 チャンク</li>



<li>chunk_size はハードコード禁止</li>



<li>エラー時は即終了</li>



<li>正常終了時はメール送信</li>
</ul>



<p>この“思考の透明性”は、CopilotでStep1で作ったものを渡した結果で、Geminiでは提示されなかったものだ。</p>



<p>そして DeepSeek-R1 は、<br><strong>仕様書と 100% 一致する @JobN.sh を生成した。</strong></p>



<pre class="wp-block-code"><code>#!/bin/bash
# @JobN.sh - PDF 翻訳バッチ
# 自動生成：DeepSeek（仕様書 Step（２）に基づく）

# ------------------------------
# 1. ヘッダー &amp; 環境設定
# ------------------------------
set -euo pipefail
IFS=$'\n\t'

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE&#91;0]}")" &amp;&amp; pwd)"
CONFIG_FILE="${SCRIPT_DIR}/config.yaml"

# 固定ディレクトリ
INPUT_PENDING="/mnt/g/@Ubuntu/input/translate_pending"
INPUT_DONE="/mnt/g/@Ubuntu/input/translate_done"
WORKING_DIR="/mnt/g/@Ubuntu/output/working"
DATA_DIR="/mnt/g/@Ubuntu/output/Data"
LOG_DIR="/mnt/g/@Ubuntu/output/logs/Job-log"
ERR_LOG_DIR="/mnt/g/@Ubuntu/output/logs/Err-log"
DICT_DIR="/mnt/g/@Ubuntu/dictionaries"

# グローバル変数
CHUNK_SIZE=""
KEEP_OCR_PDF=""
MAIL_FROM=""
MAIL_TO=""
MODEL_PATH=""

# ------------------------------
# 2. config.yaml の読み込み
# ------------------------------
load_config() {
    if &#91;&#91; ! -f "$CONFIG_FILE" ]]; then
        echo "&#91;ERROR] $(date '+%Y-%m-%d %H:%M:%S') config.yaml not found at $CONFIG_FILE" &gt;&amp;2
        exit 1
    fi

    # yq が使えれば優先、なければ grep/sed で簡易抽出
    if command -v yq &amp;&gt;/dev/null; then
        CHUNK_SIZE=$(yq eval '.translation.chunk_size' "$CONFIG_FILE")
        KEEP_OCR_PDF=$(yq eval '.keep_ocr_pdf' "$CONFIG_FILE")
        MAIL_FROM=$(yq eval '.mail.from' "$CONFIG_FILE")
        MAIL_TO=$(yq eval '.mail.to' "$CONFIG_FILE")
        MODEL_PATH=$(yq eval '.model.path' "$CONFIG_FILE")
    else
        CHUNK_SIZE=$(grep -E '^&#91;&#91;:space:]]*chunk_size:' "$CONFIG_FILE" | head -1 | sed -E 's/.*:&#91;&#91;:space:]]*//')
        KEEP_OCR_PDF=$(grep -E '^&#91;&#91;:space:]]*keep_ocr_pdf:' "$CONFIG_FILE" | head -1 | sed -E 's/.*:&#91;&#91;:space:]]*//' | tr '&#91;:upper:]' '&#91;:lower:]')
        MAIL_FROM=$(grep -E '^&#91;&#91;:space:]]*from:' "$CONFIG_FILE" | head -1 | sed -E 's/.*:&#91;&#91;:space:]]*//' | tr -d '"')
        MAIL_TO=$(grep -E '^&#91;&#91;:space:]]*to:' "$CONFIG_FILE" | head -1 | sed -E 's/.*:&#91;&#91;:space:]]*//' | tr -d '"')
        MODEL_PATH=$(grep -E '^&#91;&#91;:space:]]*path:' "$CONFIG_FILE" | head -1 | sed -E 's/.*:&#91;&#91;:space:]]*//' | tr -d '"')
    fi

    # 数値チェック
    if &#91;&#91; ! "$CHUNK_SIZE" =~ ^&#91;0-9]+$ ]]; then
        log_error "Invalid chunk_size in config.yaml: $CHUNK_SIZE"
        exit 1
    fi
    if &#91;&#91; "$KEEP_OCR_PDF" != "true" &amp;&amp; "$KEEP_OCR_PDF" != "false" ]]; then
        log_error "keep_ocr_pdf must be true or false, got: $KEEP_OCR_PDF"
        exit 1
    fi
}

# ------------------------------
# 3. ログ関数
# ------------------------------
log_info() {
    local msg="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "&#91;INFO] $timestamp $msg" | tee -a "$LOG_DIR/job.log"
}

log_warn() {
    local msg="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "&#91;WARN] $timestamp $msg" | tee -a "$LOG_DIR/job.log"
}

log_error() {
    local msg="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "&#91;ERROR] $timestamp $msg" | tee -a "$ERR_LOG_DIR/error.log" &gt;&amp;2
}

# ------------------------------
# 4. メール送信
# ------------------------------
send_mail() {
    local subject="$1"
    local body="$2"
    if command -v mail &amp;&gt;/dev/null; then
        echo "$body" | mail -s "$subject" -r "$MAIL_FROM" "$MAIL_TO"
    else
        log_warn "mail command not found, cannot send email"
    fi
}

# ------------------------------
# 5. OCR (ocrmypdf 必須)
# ------------------------------
ocr_pdf() {
    local input_pdf="$1"
    local output_pdf="$2"
    log_info "OCR: $input_pdf -&gt; $output_pdf"
    if ! command -v ocrmypdf &amp;&gt;/dev/null; then
        log_error "ocrmypdf not found. Please install it."
        return 1
    fi
    ocrmypdf --force-ocr --output-type pdf "$input_pdf" "$output_pdf" &gt;&gt; "$LOG_DIR/job.log" 2&gt;&amp;1
    if &#91;&#91; $? -ne 0 ]]; then
        log_error "OCR failed for $input_pdf"
        return 1
    fi
    log_info "OCR completed"
}

# ------------------------------
# 6. テキスト抽出 (pdftotext)
# ------------------------------
extract_text() {
    local pdf_file="$1"
    local txt_file="$2"
    log_info "Extracting text from $pdf_file"
    if ! command -v pdftotext &amp;&gt;/dev/null; then
        log_error "pdftotext not found (poppler-utils)"
        return 1
    fi
    pdftotext -layout "$pdf_file" "$txt_file"
    if &#91;&#91; ! -s "$txt_file" ]]; then
        log_error "Text extraction produced empty file: $txt_file"
        return 1
    fi
    log_info "Text extraction done"
}

# ------------------------------
# 7. チャンク分割 (文単位＋表形式判定)
# ------------------------------
split_chunks() {
    local text_file="$1"
    local chunks_file="$2"   # 出力: 1行1チャンク (原文)
    log_info "Splitting text into chunks (size=$CHUNK_SIZE)"
    
    # 改行コード統一、空行除去して1行ずつ配列へ
    mapfile -t lines &lt; &lt;(sed 's/\r$//' "$text_file" | grep -v '^&#91;&#91;:space:]]*$')
    local i=0
    local -a chunks=()
    local -a buffer=()
    local buffer_len=0
    local in_table_block=false
    local table_lines=()

    # 表形式判定ヘルパー
    is_table_row() {
        local line="$1"
        # ルール1: = または : を含む
        if &#91;&#91; "$line" =~ &#91;=:] ]]; then
            return 0
        fi
        # ルール2: 行頭が規則的 (例: Button 1 / Button 2 ...)
        if &#91;&#91; "$line" =~ ^&#91;A-Za-z]+&#91;&#91;:space:]]+&#91;0-9]+ ]]; then
            return 0
        fi
        # ルール3: 数値＋単位
        if &#91;&#91; "$line" =~ &#91;0-9]+&#91;&#91;:space:]]*(mm|cm|kg|px|%|\$) ]]; then
            return 0
        fi
        # ルール4/5/6: 簡易的に連続する似た長さ/単語数/スペースを判定（ここでは無難に文字数と単語数）
        # 実際の判定は連続行で行うため、単独ではfalse -&gt; 連続で判断
        return 1
    }

    # 表ブロックをまとめてチャンク化（各行を単独チャンク）
    flush_table_block() {
        if &#91;&#91; ${#table_lines&#91;@]} -eq 0 ]]; then
            return
        fi
        for tl in "${table_lines&#91;@]}"; do
            chunks+=("$tl")
        done
        table_lines=()
    }

    # 通常バッファをチャンク化
    flush_buffer() {
        if &#91;&#91; ${#buffer&#91;@]} -eq 0 ]]; then
            return
        fi
        local combined=$(IFS=' '; echo "${buffer&#91;*]}")
        chunks+=("$combined")
        buffer=()
        buffer_len=0
    }

    # メインループ
    for (( i=0; i&lt;${#lines&#91;@]}; i++ )); do
        local line="${lines&#91;$i]}"
        # 表形式行かどうか（単独判定＋前後との連続性をみる）
        local is_table=false
        if is_table_row "$line"; then
            is_table=true
        else
            # さらに、前後の行が表形式なら表とみなす（連続性）
            if &#91;&#91; $i -gt 0 &amp;&amp; $i -lt $((${#lines&#91;@]}-1)) ]]; then
                if is_table_row "${lines&#91;$((i-1))]}" &amp;&amp; is_table_row "${lines&#91;$((i+1))]}"; then
                    is_table=true
                fi
            fi
        fi

        if &#91;&#91; "$is_table" == true ]]; then
            # 表ブロックに入る前の通常バッファをフラッシュ
            if &#91;&#91; "$in_table_block" == false ]]; then
                flush_buffer
                in_table_block=true
                table_lines=()
            fi
            table_lines+=("$line")
        else
            # 通常文
            if &#91;&#91; "$in_table_block" == true ]]; then
                flush_table_block
                in_table_block=false
            fi
            # ピリオドでさらに細分化（文単位）
            # ピリオド＋空白またはピリオド＋改行で分割（簡易）
            IFS='.' read -ra sentences &lt;&lt;&lt; "$line"
            for sent in "${sentences&#91;@]}"; do
                sent="$(echo "$sent" | sed 's/^&#91;&#91;:space:]]*//;s/&#91;&#91;:space:]]*$//')"
                &#91;&#91; -z "$sent" ]] &amp;&amp; continue
                # バッファ追加後の長さを計算
                local candidate_len=$buffer_len
                if &#91;&#91; ${#buffer&#91;@]} -gt 0 ]]; then
                    candidate_len=$(( candidate_len + 1 ))  # スペース
                fi
                candidate_len=$(( candidate_len + ${#sent} ))
                if &#91;&#91; $candidate_len -le $CHUNK_SIZE ]]; then
                    buffer+=("$sent")
                    buffer_len=$candidate_len
                else
                    flush_buffer
                    buffer+=("$sent")
                    buffer_len=${#sent}
                fi
            done
        fi
    done
    # 最終フラッシュ
    if &#91;&#91; "$in_table_block" == true ]]; then
        flush_table_block
    else
        flush_buffer
    fi

    # チャンクをファイルに書き出し
    printf "%s\n" "${chunks&#91;@]}" &gt; "$chunks_file"
    log_info "Created ${#chunks&#91;@]} chunks"
}

# ------------------------------
# 8. チャンク翻訳 (llama.cpp の llama-cli を使用)
# ------------------------------
translate_chunks() {
    local chunks_file="$1"
    local translated_file="$2"
    log_info "Translating chunks using model: $MODEL_PATH"

    if &#91;&#91; ! -f "$MODEL_PATH" ]]; then
        log_error "Model file not found: $MODEL_PATH"
        return 1
    fi
    if ! command -v llama-cli &amp;&gt;/dev/null; then
        log_error "llama-cli not found (llama.cpp)"
        return 1
    fi

    local -a translated_chunks=()
    local chunk_num=0
    while IFS= read -r chunk; do
        chunk_num=$((chunk_num + 1))
        log_info "Translating chunk $chunk_num"
        # プロンプト: 日本語に翻訳（表形式もそのまま）
        local prompt="以下の英語テキストを日本語に翻訳してください。表形式の場合は構造を維持してください。\n\n$chunk"
        # llama-cli 実行 (--no-display-prompt でプロンプト非表示、-p でプロンプト)
        local translation
        translation=$(echo -e "$prompt" | llama-cli -m "$MODEL_PATH" --no-display-prompt -p "$prompt" 2&gt;/dev/null)
        if &#91;&#91; -z "$translation" ]]; then
            log_error "Translation failed for chunk $chunk_num"
            return 1
        fi
        # モデルの出力から余計なプロンプト除去（簡易）
        translation=$(echo "$translation" | sed -n '/^$/,$p' | tail -n +2)
        translated_chunks+=("$translation")
    done &lt; "$chunks_file"

    printf "%s\n" "${translated_chunks&#91;@]}" &gt; "$translated_file"
    log_info "Translation completed for ${#translated_chunks&#91;@]} chunks"
}

# ------------------------------
# 9. 辞書適用 (notranslate.txt → ReplaceWord.txt)
# ------------------------------
apply_dictionary() {
    local original_chunks_file="$1"
    local translated_chunks_file="$2"
    local final_file="$3"

    log_info "Applying dictionaries"

    # original_chunks と translated_chunks を配列に読み込み
    mapfile -t original_chunks &lt; "$original_chunks_file"
    mapfile -t translated_chunks &lt; "$translated_chunks_file"

    if &#91;&#91; ${#original_chunks&#91;@]} -ne ${#translated_chunks&#91;@]} ]]; then
        log_error "Mismatch between original and translated chunks count"
        return 1
    fi

    # notranslate.txt 読み込み（全PDF対象）
    local notranslate_words=()
    if &#91;&#91; -f "$DICT_DIR/notranslate.txt" ]]; then
        mapfile -t notranslate_words &lt; &lt;(grep -v '^&#91;&#91;:space:]]*$' "$DICT_DIR/notranslate.txt" | sed 's/^&#91;&#91;:space:]]*//;s/&#91;&#91;:space:]]*$//')
        log_info "Loaded ${#notranslate_words&#91;@]} words from notranslate.txt"
    fi

    # ReplaceWord.txt 読み込み（出現したPDFのみ → ここでは常に読み込む）
    declare -A replace_map
    if &#91;&#91; -f "$DICT_DIR/ReplaceWord.txt" ]]; then
        while IFS= read -r line; do
            &#91;&#91; -z "$line" || "$line" =~ ^&#91;&#91;:space:]]*# ]] &amp;&amp; continue
            key="${line%%:*}"
            val="${line#*:}"
            key="$(echo "$key" | sed 's/^&#91;&#91;:space:]]*//;s/&#91;&#91;:space:]]*$//')"
            val="$(echo "$val" | sed 's/^&#91;&#91;:space:]]*//;s/&#91;&#91;:space:]]*$//')"
            if &#91;&#91; -n "$key" ]]; then
                replace_map&#91;"$key"]="$val"
            fi
        done &lt; "$DICT_DIR/ReplaceWord.txt"
        log_info "Loaded ${#replace_map&#91;@]} replacements from ReplaceWord.txt"
    fi

    local -a final_chunks=()
    for idx in "${!translated_chunks&#91;@]}"; do
        local orig="${original_chunks&#91;$idx]}"
        local trans="${translated_chunks&#91;$idx]}"

        # Step 1: notranslate 適用 (翻訳結果中の単語を原文の同じ単語で置き換え)
        for word in "${notranslate_words&#91;@]}"; do
            # 簡易: 翻訳結果にその単語が含まれていれば、原文中に同じ単語があればそれに置換
            # より正確には原文から該当単語を探すが、ここでは単語境界で置換
            if &#91;&#91; "$trans" == *"$word"* ]]; then
                # 原文にも同じ単語があれば置換（必ずしも正しくないが許容）
                if &#91;&#91; "$orig" == *"$word"* ]]; then
                    trans="${trans//$word/$word}"   # 元の単語で上書き（同じに見えるが実質維持）
                fi
            fi
        done

        # Step 2: ReplaceWord 適用 (キー → バリュー)
        for key in "${!replace_map&#91;@]}"; do
            trans="${trans//$key/${replace_map&#91;$key]}}"
        done

        final_chunks+=("$trans")
    done

    printf "%s\n" "${final_chunks&#91;@]}" &gt; "$final_file"
    log_info "Dictionary applied, final output: $final_file"
}

# ------------------------------
# 10. PDF 移動 (pending → done)
# ------------------------------
move_pdf() {
    local pdf_path="$1"
    local filename=$(basename "$pdf_path")
    log_info "Moving $filename to $INPUT_DONE"
    mv "$pdf_path" "$INPUT_DONE/" || {
        log_error "Failed to move $pdf_path to $INPUT_DONE"
        return 1
    }
}

# ------------------------------
# 11. main
# ------------------------------
main() {
    # 初期化: ディレクトリ作成
    mkdir -p "$INPUT_PENDING" "$INPUT_DONE" "$WORKING_DIR" "$DATA_DIR" "$LOG_DIR" "$ERR_LOG_DIR"

    load_config

    log_info "=== PDF Translation Batch Started ==="

    # pending 内の PDF を処理
    shopt -s nullglob
    for pdf_file in "$INPUT_PENDING"/*.pdf; do
        base_name=$(basename "$pdf_file" .pdf)
        log_info "Processing: $pdf_file"

        # 作業用ファイルパス
        working_pdf="$WORKING_DIR/${base_name}_ocr.pdf"
        text_tmp="$WORKING_DIR/${base_name}_extracted.txt"
        chunks_file="$WORKING_DIR/${base_name}_chunks.txt"
        translated_file="$WORKING_DIR/${base_name}_translated.txt"
        final_output="$DATA_DIR/${base_name}_translated.txt"

        # 1. OCR
        ocr_pdf "$pdf_file" "$working_pdf" || exit 1

        # 2. テキスト抽出
        extract_text "$working_pdf" "$text_tmp" || exit 1

        # 3. チャンク分割
        split_chunks "$text_tmp" "$chunks_file" || exit 1

        # 4. 翻訳
        translate_chunks "$chunks_file" "$translated_file" || exit 1

        # 5. 辞書適用
        apply_dictionary "$chunks_file" "$translated_file" "$final_output" || exit 1

        # 6. OCR PDF の後処理 (keep_ocr_pdf に従う)
        if &#91;&#91; "$KEEP_OCR_PDF" != "true" ]]; then
            log_info "Removing OCR PDF (keep_ocr_pdf=false)"
            rm -f "$working_pdf"
        else
            log_info "Keeping OCR PDF at $working_pdf"
        fi

        # 7. 元PDF移動
        move_pdf "$pdf_file" || exit 1

        # 中間ファイル削除（オプション: デバッグ用に残しても良いが整理）
        rm -f "$text_tmp" "$chunks_file" "$translated_file"

        log_info "Finished processing $base_name -&gt; $final_output"
    done

    log_info "=== All PDFs processed successfully ==="
    send_mail "PDF翻訳バッチ完了" "全てのPDFの翻訳が正常に終了しました。"
    exit 0
}

# エラーハンドリング: エラー発生時にメール送信して終了
trap 'log_error "Script interrupted or failed"; send_mail "PDF翻訳バッチ失敗" "$(tail -20 "$ERR_LOG_DIR/error.log" 2&gt;/dev/null || echo "Unknown error")"; exit 1' ERR

main "$@"</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper-800x533.jpg" alt="Chapter 5" class="wp-image-14017" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-5-batch-oper.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">バッチジョブの実行──AI が作ったコードが初めて動いた瞬間</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc5">第5章　Step3：バッチジョブの実行──AI が作ったコードが初めて動いた瞬間</span></h2>



<p>Step3 は、<br><strong>PDF </strong><strong>英文マニュアルを一括翻訳するバッチジョブの実行</strong>だ。</p>



<ul class="wp-block-list">
<li>OCR（ocrmypdf）</li>



<li>テキスト抽出（pdftotext）</li>



<li>チャンク分割</li>



<li>翻訳（<span class="bold-red">llama.cpp</span> &amp; <strong>cyberagent-DeepSeek-R1-Distill-Qwen-14B-Japanese-Q5_K_M.gguf</strong>）</li>



<li>辞書適用</li>



<li>PDF 移動（翻訳完了分のPDFファイルのデレクトリに移動）</li>



<li>ログ出力</li>



<li>メール通知</li>
</ul>



<p>これらが <strong>完全自動で動いた瞬間</strong>、<br>私は AI との共生の可能性を確信した。</p>



<p>AI が暴走せず、<br>仕様を守り、<br>人間の設計通りに動く。</p>



<p>これは単なる自動化ではなく、<br><strong>AI と人間が“役割分担”を確立した瞬間</strong>だった。</p>



<figure class="table-wrap">
<div class="scrollable-table stfc-sticky"><table class="eg2 table">
<caption class="tal c_aqua"><i class="fas fa-edit"></i>翻訳：<span style="border-bottom: solid 2px aqua;" class="c_wi"><b>translation</b></span></caption>
<thead>
<tr>
	<th scope="col">#</th>
	<th class="tal" scope="col">役割</th>
	<th class="tal" scope="col">名前</th>
	<th class="tal c_aqua2" scope="col">内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td class="tal">LLMモデル</td>
<td class="tal">cyberagent‑DeepSeek‑R1‑Distill‑Qwen‑14B‑Japanese‑Q5_K_M.gguf</td>
<td class="tal">翻訳用の学習済みモデルファイル（GGUF形式）</td>
</tr>
<tr>
<td>2</td>
<td class="tal">実行エンジン</td>
<td class="tal"><span style="color: red;">llama.cpp</span>（CLI版：llama-cli）</td>
<td class="tal">GGUFモデルを読み込んで推論を実行するプログラム</td>
</tr>
</tbody></table></div></figure>



<pre class="wp-block-code"><code>バッチジョブ実行
1.	Ubuntu で実行権限を付与
        chmod +x /mnt/g/@Ubuntu/CLP/PGM-N/@JobN.sh
2.	翻訳対象PDFファイルを
        /mnt/g/@Ubuntu/input/translate_pending/
        に置く
3.	実行
        /mnt/g/@Ubuntu/CLP/PGM-N/@JobN.sh
4.	翻訳結果を確認
　　　　/mnt/g/@Ubuntu/output/Data/ に出力される
5.	正常終了時
　　　　1.	完了通知メール
　　　　2.	JobLog（JobLog-yymmdd-hhmmss）

※エラー発生時は、エラーメール(PDF翻訳バッチ失敗)とErrLog（errlog-yymmdd-hhmmss）

</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="799" height="589" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/8d980c01e83f447b6c36847ff7b48cfa.png" alt="" class="wp-image-14053" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/8d980c01e83f447b6c36847ff7b48cfa.png 799w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/8d980c01e83f447b6c36847ff7b48cfa-500x369.png 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/8d980c01e83f447b6c36847ff7b48cfa-300x221.png 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/8d980c01e83f447b6c36847ff7b48cfa-768x566.png 768w" sizes="(max-width: 799px) 100vw, 799px" /></figure>



<p>&#x1f50d; 状況の意味（端的に）</p>



<ul class="wp-block-list">
<li>緑の行：翻訳タスクの開始命令。</li>



<li>「&#8230;」：モデルが次の入力（英語テキスト）を待機中。</li>



<li>灰色の行：「まず、ユーザーからの質問を正確に理解する必要があります…」<br>→ DeepSeek R1 が「翻訳対象がない」と自己説明している。「&#8230;」は <strong>処理中断ではなく入力待ち</strong>。モデルは正常に動いていいる状態のキャプチャ</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="866" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading-800x866.png" alt="AMD Ryzen AI 9 HX 470 w/ Radeon 890M" class="wp-image-14059" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading-800x866.png 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading-500x541.png 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading-300x325.png 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading-768x832.png 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LLM-Loading.png 834w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">cyberagent-DeepSeek-R1-Distill-Qwen-14B-Japanese-Q5_K_M.gguf Loading
<br>AMD Ryzen AI 9 HX 470 w/ Radeon 890M</figcaption></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist-800x533.jpg" alt="Chapter 6" class="wp-image-14018" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-6-AI-coexist.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">AI と共生するための最重要ポイント（本稿の核心）</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc6">第6章　AI と共生するための最重要ポイント（本稿の核心）</span></h2>



<p>AI と共生するために、私が学んだ最重要ポイントは以下の 5 つだ。</p>



<p><strong>①</strong><strong> AI </strong><strong>に自由を与えない（仕様の檻に入れる）</strong></p>



<ul class="wp-block-list">
<li>AI は自由にすると暴走する。</li>



<li>仕様書を“契約書”として渡すことが必須。</li>
</ul>



<p><strong>②</strong><strong> AI </strong><strong>に丸投げしない（人間が設計する）</strong></p>



<ul class="wp-block-list">
<li>AI は設計できない。</li>



<li>設計は人間の仕事。</li>



<li>AI は実装担当。</li>
</ul>



<p><strong>③</strong><strong> AI </strong><strong>の出力は必ず検証する</strong></p>



<ul class="wp-block-list">
<li>AI のコードは 80% 正しいが、20% は危険。</li>



<li>必ず diff を取る。</li>
</ul>



<p><strong>④</strong><strong> AI </strong><strong>を信頼しない（だが活用する）</strong></p>



<ul class="wp-block-list">
<li>AI は優秀な“部下”だが、勝手に判断させてはいけない。</li>
</ul>



<p><strong>⑤</strong><strong> AI </strong><strong>の暴走を防ぐのは</strong><strong>“</strong><strong>構造化された設計</strong><strong>”</strong><strong></strong></p>



<ul class="wp-block-list">
<li>AS/400 の思想は、AI 時代にも通用する。</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist-800x533.jpg" alt="Chapter 7" class="wp-image-14019" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/Chapter-7-AI-coexist.jpg 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">AI は“共生”すべき存在であり、支配させてはいけない</figcaption></figure>



<h2 class="wp-block-heading"><span id="toc7">第7章　まとめ──AI は“共生”すべき存在であり、支配させてはいけない</span></h2>



<p>Gemini の迷走から始まり、Copilot と DeepSeek の協働で完成した PGM-N。</p>



<p>この 21 日間で私は、<br><strong>AI </strong><strong>は人間の代わりではなく、人間の拡張である</strong><br>という結論に至った。</p>



<ul class="wp-block-list">
<li>AI に支配されるのではなく、AI を制御し、AI を設計し、AI を“共生相手”として扱う。</li>
</ul>



<p>これが、<br><strong>AI </strong><strong>時代の技術者に求められる姿勢</strong>だと確信している。</p>



<h2 class="wp-block-heading"><span id="toc8">図版</span></h2>



<h3 class="wp-block-heading"><span id="toc9">図版①：HIPO 図（Hierarchy Input Process Output）</span></h3>



<p>PDF 英文マニュアル翻訳バッチの全体構造を<strong>階層構造</strong>で表現</p>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【HIPO 図：Step1 要求設計（詳細版）】
──────────────────────────────────────────────

■ Level 0：PDF 翻訳バッチ要求定義
    ├─ Input ：現状の課題、PDF マニュアル、運用要件
    ├─ Process：要件整理・制約条件・AI 利用方針の明文化
    └─ Output：要求仕様書（AI への「契約書」）

──────────────────────────────────────────────

■ Level 1：要求ブロック

    1. 機能要件
    2. 非機能要件
    3. ディレクトリ構造
    4. ログ・監視
    5. AI 利用ポリシー（暴走防止）

──────────────────────────────────────────────

■ Level 2：各ブロックの詳細

1. 機能要件
    Input :
        - 英文 PDF マニュアル
    Process :
        - OCR → テキスト抽出
        - チャンク分割（表／通常文）
        - 翻訳
        - 辞書適用
        - 結果出力
    Output :
        - 日本語テキストファイル
        - 処理済み PDF の整理

2. 非機能要件
    Input :
        - 運用条件（夜間バッチ、無人運転）
    Process :
        - エラー時の挙動定義
        - ログ粒度の定義
        - メール通知条件
    Output :
        - エラー処理仕様
        - ログ仕様
        - 通知仕様

3. ディレクトリ構造
    Input :
        - Windows / WSL2 環境
    Process :
        - /mnt/g/@Ubuntu/ 以下の固定構造定義
    Output :
        - input/translate_pending
        - input/translate_done
        - output/working
        - output/Data
        - output/logs/Job-log
        - output/logs/Err-log
        - CLP/PGM-N/@JobN.sh

4. ログ・監視
    Input :
        - 運用者の監視要件
    Process :
        - ログ形式の統一
        - INFO / WARN / ERROR の定義
    Output :
        - &#91;INFO] yyyy-mm-dd HH:MM:SS message
        - &#91;WARN] ...
        - &#91;ERROR] ...

5. AI 利用ポリシー（暴走防止）
    Input :
        - 過去の AI 迷走経験（Gemini）
    Process :
        - 禁止事項の明文化
        - AI に許可する範囲の限定
    Output :
        - 「構造変更禁止」
        - 「ログ形式変更禁止」
        - 「関数順序変更禁止」
        - 「最適化禁止」
        - 「仕様からの逸脱禁止」

──────────────────────────────────────────────</code></pre>



<h3 class="wp-block-heading"><span id="toc10">図版②：プロセスフロー図（業務フロー）</span></h3>



<p>Step3（実行フェーズ）を<strong>業務フローとして視覚化</strong></p>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【プロセスフロー図：PDF 英文マニュアル翻訳バッチ】
──────────────────────────────────────────────

                ┌────────────────────────┐
                │   1. PDF投入（pending）                        │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │   2. OCR（ocrmypdf）                           │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 3. テキスト抽出（pdftotext）                   │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 4. チャンク分割                                │
                │   ・表形式判定                                 │
                │   ・文単位分割                                 │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 5. 翻訳（llama.cpp）                           │
                │   ・Q5_K_M モデル使用                          │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 6. 辞書適用                                    │
                │   ・notranslate.txt                            │
                │   ・ReplaceWord.txt                            │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 7. 翻訳結果出力（Data）                        │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 8. 元PDF移動（done）                           │
                └───────────┬────────────┘
                                        │
                                        ▼
                ┌────────────────────────┐
                │ 9. ログ出力・メール通知                        │
                └────────────────────────┘

──────────────────────────────────────────────</code></pre>



<h3 class="wp-block-heading"><span id="toc11">図版③：AI 共生プロセス（Step1〜Step3 全体像）</span></h3>



<p>【AI 共生プロセス：Step1 → Step2 → Step3】</p>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【AI 共生プロセス：Step1 → Step2 → Step3】
──────────────────────────────────────────────

Step1：要求設計・外部設計（人間主導）
    ├─ 目的定義
    ├─ ディレクトリ構造
    ├─ 関数順序
    ├─ ログ形式
    └─ 禁止事項（AI暴走防止）

        ▼（契約書として AI に渡す）

Step2：内部設計・プログラミング（AI協働）
    ├─ Copilot：仕様の整形・構造化
    ├─ DeepSeek-R1：コード生成
    ├─ 67秒の思考ログ
    └─ @JobN.sh 完成

        ▼（人間がレビュー・検証）

Step3：バッチ運用（AI実行）
    ├─ OCR
    ├─ テキスト抽出
    ├─ チャンク分割
    ├─ 翻訳（Q5_K_M）
    ├─ 辞書適用
    ├─ PDF移動
    └─ メール通知

──────────────────────────────────────────────</code></pre>



<h3 class="wp-block-heading"><span id="toc12">split_chunks の表形式判定ロジック・フローチャー</span></h3>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【フローチャート：split_chunks 表形式判定ロジック】
──────────────────────────────────────────────

&#91;開始]
   │
   ▼
&#91;1行ずつ読み込み]
   │
   ▼
&#91;is_table_row(line)?]
   │  YES
   │───────┐
   │              ▼
   │        &#91;is_table = true]
   │              │
   │              ▼
   │      &#91;in_table_block?]
   │          │        │
   │          NO       YES
   │          │        │
   │          ▼        │
   │   &#91;flush_buffer]   │
   │                   &#91;in_table_block = true]
   │
   │
   ▼
&#91;is_table = false の場合]
   │
   ├─ 前後行チェック
   │   （前後が表形式なら is_table = true）
   │
   └→ それでも false なら通常文として処理

────────────────────────────
通常文処理側
────────────────────────────

&#91;if in_table_block == true]
   │
   ▼
&#91;flush_table_block]
&#91;in_table_block = false]
   │
   ▼
&#91;文単位に分割（ピリオド）]
   │
   ▼
&#91;バッファ長 + 文長 &lt;= chunk_size ?]
   │               │
  YES               NO
   │               │
   ▼               ▼
&#91;バッファに追加]   &#91;flush_buffer → 新バッファ開始]
   │
   ▼
&#91;次の行へ]

────────────────────────────
終了処理
────────────────────────────

&#91;全行処理後]
   │
   ├─ in_table_block == true → flush_table_block
   └─ それ以外 → flush_buffer
   │
   ▼
&#91;chunks.txt に書き出し]
   │
   ▼
&#91;終了]

──────────────────────────────────────────────</code></pre>



<h3 class="wp-block-heading"><span id="toc13">DeepSeek-R1 の 67 秒思考ログ・構造図</span></h3>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【構造図：DeepSeek-R1 の 67 秒思考ログ】
──────────────────────────────────────────────

■ レイヤー構造

Layer 1：前提確認
    - ディレクトリ構造は固定
    - スクリプト配置場所：/mnt/g/@Ubuntu/CLP/PGM-N/@JobN.sh
    - config.yaml は相対パスで読む

Layer 2：仕様の再構成
    - 関数一覧と順序の確認
    - ログ形式の固定
    - 辞書処理の順序
    - 表形式判定ルールの整理

Layer 3：禁止事項の内面化
    - 構造変更禁止
    - 関数名変更禁止
    - ログ形式変更禁止
    - chunk_size ハードコード禁止
    - 表ブロック結合禁止

Layer 4：コード生成戦略
    - Bash での実装方針
    - エラー処理の統一（trap + log_error + send_mail）
    - main からの呼び出し順序の固定

Layer 5：実装
    - 関数定義
    - ログ関数
    - OCR / 抽出 / 分割 / 翻訳 / 辞書 / 移動
    - main と trap

──────────────────────────────────────────────

■ 特徴的なポイント

- 「仕様を壊さない」ことを最優先にしている
- 「人間の設計を守る」という姿勢が明確
- 自己判断による最適化を避けている
- AS/400 的な「手順遵守」の文化に近い

──────────────────────────────────────────────</code></pre>



<h3 class="wp-block-heading"><span id="toc14">AI 暴走防止の「仕様の檻」モデル図</span></h3>



<pre class="wp-block-code"><code>──────────────────────────────────────────────
【モデル図：AI 暴走防止の「仕様の檻」】
──────────────────────────────────────────────

          ┌───────────────────────┐
          │        人間の設計（要求・外部設計）          │
          │  ・ディレクトリ構造                          │
          │  ・関数順序                                  │
          │  ・ログ形式                                  │
          │  ・辞書処理順序                              │
          │  ・禁止事項                                  │
          └───────────┬───────────┘
                                  │
                                  ▼
          ┌───────────────────────┐
          │       「仕様の檻」（Contract）               │
          │  ・AI が破ってはいけない境界                 │
          │  ・自由度を意図的に制限                      │
          │  ・逸脱時は即 NG と判断                      │
          └───────────┬───────────┘
                                  │
                                  ▼
          ┌───────────────────────┐
          │        AI の役割（実装担当）                 │
          │  ・コード生成                                │
          │  ・補完・整形                                │
          │  ・長文仕様の保持                            │
          └───────────────────────┘

──────────────────────────────────────────────

■ ポイント

- AI は「設計者」ではなく「実装担当」
- 檻（Contract）がないと AI は暴走する
- 檻の中でなら AI は非常に有能
- 人間は「檻を設計する側」に立つべき

──────────────────────────────────────────────</code></pre>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-none">

<a href="https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/14082/" title="【実証】AIオーケストレーションの限界と最適解：DeepSeek暴走を防ぐエンタープライズ級Pythonバッチ設計" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/00-AI-Orchestration-320x180.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/00-AI-Orchestration-320x180.jpg 320w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/00-AI-Orchestration-120x68.jpg 120w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/00-AI-Orchestration-160x90.jpg 160w" sizes="(max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">【実証】AIオーケストレーションの限界と最適解：DeepSeek暴走を防ぐエンタープライズ級Pythonバッチ設計</div><div class="blogcard-snippet internal-blogcard-snippet">AIに丸投げでは出来高50%未満の赤点？AS/400のCLP構造や150語のルールでDeepSeekが暴走した実体験から、Copilotとの役割分担、Claude 4.5 Sonnetの有効性、PCローカル環境（Ryzen AI 9）で品質100%を叩き出すPythonパイプラインの最終設計図までを徹底解説。Ryzen AI 9 HX470 LLM</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://xn--ecka7j.biz" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">イイネ.biz</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.06.06</div></div></div></div></a>
</div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Local LLM の限界と向き合う：モデル選定と実践から見えた“解像度”の壁</title>
		<link>https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/13916/</link>
		
		<dc:creator><![CDATA[Jun-N]]></dc:creator>
		<pubDate>Wed, 08 Apr 2026 03:44:51 +0000</pubDate>
				<category><![CDATA[AI共生]]></category>
		<category><![CDATA[AI Tool]]></category>
		<category><![CDATA[AIとの共生]]></category>
		<category><![CDATA[Local LLM]]></category>
		<category><![CDATA[ツール]]></category>
		<category><![CDATA[道具]]></category>
		<guid isPermaLink="false">https://xn--ecka7j.biz/?p=13916</guid>

					<description><![CDATA[Local LLM 　生成AIは便利だが、時に平然と“嘘”をつく。だからこそ私は、クラウド依存を避けるために Local LLM を導入し、自分の手元でモデルを動かすことに挑戦した。　しかし、PDFのページ数が増えた瞬間 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><strong>Local LLM</strong></p>



<p>　生成AIは便利だが、時に平然と“嘘”をつく。<br>だからこそ私は、クラウド依存を避けるために Local LLM を導入し、自分の手元でモデルを動かすことに挑戦した。<br>　しかし、PDFのページ数が増えた瞬間に精度が落ち、前の文書の内容が混ざり、モデルを eject して再読み込みするという作業を繰り返すことになった。<br>この章では、私が実際に行ったモデル選定、PDF解析の試行錯誤、そして「Local LLM の限界」をどう乗り越えたかをまとめる。</p>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-none">

<a href="https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/13888/" title="AIとの共生：生成AIは嘘をつく、だから Local LLMを使ってみた" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/2e1f3b3cffbcbe86158e3dbab9b78b51-320x180.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/2e1f3b3cffbcbe86158e3dbab9b78b51-320x180.jpg 320w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/2e1f3b3cffbcbe86158e3dbab9b78b51-120x68.jpg 120w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/2e1f3b3cffbcbe86158e3dbab9b78b51-160x90.jpg 160w" sizes="(max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AIとの共生：生成AIは嘘をつく、だから Local LLMを使ってみた</div><div class="blogcard-snippet internal-blogcard-snippet">生成AIを利用する際に最も重要なのは、AIを誘導しないことである。ユーザーが意識していないと、AIは欠損した情報を補完し、もっともらしい文章を生成する。以前の記事でも触れたように、存在しない製品の型番や仕様を提示するケースが確認されている。これは特定のモデルに限らず、生成AI全般に共通する構造的な特性である。本稿では、LM Studio を用いて複数の Local LLM を検証した結果をもとに、生成AIの特性と、AIとの共生に必要な視点を整理する。Ryzen AI 9 HX470</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://xn--ecka7j.biz" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">イイネ.biz</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.04.05</div></div></div></div></a>
</div>



<p>　そこで第2章では、私が実際に行った検証の記録をまとめる。<br>複数のモデルを試し、PDFを読み込ませ、精度の落ちるポイントを見極め、そして最終的に「AIとの共生」に必要な運用方法にたどり着くまでのプロセスだ。Local LLM の“理想”と“現実”の間で揺れながら、私は何を感じ、どう判断したのか。<br>その実体験を、詳しく紹介したい。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="678" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27-800x678.png" alt="LM Studio Models" class="wp-image-13988" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27-800x678.png 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27-500x424.png 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27-300x254.png 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27-768x651.png 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/LM-Studio-Models-2026-04-27.png 1146w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">LLM 一覧（26/04/27）</figcaption></figure>



<p><strong>&#x2714;<span class="blue">Q5_K_M </span>があるなら、必ず Q5_K_M を選ぶ</strong><br><strong>&#x2714; Q5 が無い場合 → <span class="green"><span class="bold-green">Q4_K_M </span></span>を選ぶ（_S は避ける）</strong></p>



<p><strong>&#x2714; 作者は “<span class="bold-blue">bartowski </span>&gt; <span class="bold-green">mmnga</span> &gt; unsloth &gt; <span class="bold-red">その他</span>” の順で信頼性が高い</strong></p>



<p><strong>量子化の品質並び：</strong><br><strong>精度の高さ：Q5_K_L ＞ <span class="bold-blue">Q5_K_M</span> ＞ Q5_K_S ＞ <span class="bold-green">Q4_K_M</span> ＞ Q4_K_S ＞ Q3</strong></p>



<p><strong>しかし Ryzen AI9<span class="badge-blue"><span class="bold">HX470（32GB RAM）</span></span>では：</strong><br><strong>• &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Q5_K_<span class="bold-red">L → 重すぎて危険</span></strong><br><strong>• &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="bold-blue">Q5_K_M → 最適</span></strong><br><strong>• &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Q5_K_<span class="bold-red">S → 精度が落ちる</span></strong><br><strong>• &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="bold-green">Q4_K_M → 軽くて精度もそこそこ（安全）</span></strong><br><strong>• &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Q4_K_<span class="bold-red">S → 精度が落ちる（非推奨）</span></strong><br><strong>だから <span class="bold-blue">Q5</span> が無い場合は <span class="bold-green">Q4_K_M</span> が最適。</strong></p>




  <div id="toc" class="toc tnt-none toc-center tnt-none border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ul class="toc-list open"><li><a href="#toc1" tabindex="0">なぜ Local LLM に挑んだのか</a></li><li><a href="#toc2" tabindex="0">モデル選定：14B クラスの限界と可能性</a></li><li><a href="#toc3" tabindex="0">実際の取り組み：PDF解析で起きたこと</a></li><li><a href="#toc4" tabindex="0">直面した“解像度の壁”と原因</a><ul><li><a href="#toc5" tabindex="0">&#x2714; 14Bモデルの context window の限界</a></li><li><a href="#toc6" tabindex="0">&#x2714; attention の限界</a></li><li><a href="#toc7" tabindex="0">&#x2714; モデル内部のキャッシュ残留</a></li></ul></li><li><a href="#toc8" tabindex="0">&nbsp;64GB RAM を検討した理由と現実的な結論</a><ul><li><a href="#toc9" tabindex="0">&#x274c; 14Bモデルの読解精度は RAM を増やしても変わらない</a></li></ul></li><li><a href="#toc10" tabindex="0">Local LLM と共生するための運用戦略</a><ul><li><a href="#toc11" tabindex="0">&#x2714; 1〜3ページ単位で分割</a></li><li><a href="#toc12" tabindex="0">&#x2714; 各チャンクを独立スレッドで処理</a></li><li><a href="#toc13" tabindex="0">&#x2714; system prompt で強制リセット</a></li><li><a href="#toc14" tabindex="0">&#x2714; 最後に人間（私）が統合・補完する</a></li></ul></li><li><a href="#toc15" tabindex="0">そして気づいた事：AIは“補助”、判断は人間がする</a></li><li><a href="#toc16" tabindex="0">Batch化</a></li></ul>
    </div>
  </div>

<h2 class="wp-block-heading"><span id="toc1">なぜ Local LLM に挑んだのか</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10-800x533.jpg" alt="Local LLM" class="wp-image-13908" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-10.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">ローカルLLMのメリット</figcaption></figure>



<p>クラウド型の生成AIは便利だが、時に“もっともらしい嘘”を返してくる。<br>私はこの問題に長く悩まされてきた。</p>



<p>そこで考えたのが、<br><strong>「ならば自分のPCで動く Local LLM ならどうだろう？」</strong><br>という発想だった。</p>



<ul class="wp-block-list">
<li>データを外部に送らない</li>



<li>モデルを自由に選べる</li>



<li>量子化も変えられる</li>



<li>そして“嘘”が減る可能性がある</li>
</ul>



<p>こうした期待から、私は LM Studio を使って Local LLM の検証を始めた。</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20-800x533.jpg" alt="Local LLM" class="wp-image-13909" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-20.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">ローカルLLM入門：その理由と方法</figcaption></figure>



<p>第1章では、生成AIが抱える「嘘」や「幻覚」という根本的な問題、そしてそれを避けるために私が Local LLM に目を向けた理由を書いた。<br>クラウドAIの便利さと危うさ、その両方を理解したうえで、私は“自分の手元で動くAI”に可能性を感じた。</p>



<p>しかし、Local LLM を導入したからといって、すべてが魔法のように解決するわけではない。<br>むしろ、実際に使い始めて初めて見えてくる“壁”があった。</p>



<p>モデルの選定、量子化の違い、PDF解析の精度、ページ数による解像度の低下、そしてモデル内部に残る“前の文書の記憶”。<br>Local LLM は強力だが、万能ではない。<br>その限界と向き合いながら、どう使いこなしていくか──ここからが本当の勝負だった。</p>



<p>そこで第2章では、私が実際に行った検証の記録をまとめる。<br>複数のモデルを試し、PDFを読み込ませ、精度の落ちるポイントを見極め、そして最終的に「AIとの共生」に必要な運用方法にたどり着くまでのプロセスだ。</p>



<p>Local LLM の“理想”と“現実”の間で揺れながら、私は何を感じ、どう判断したのか。<br>その実体験を、次の章で詳しく紹介したい。</p>



<h2 class="wp-block-heading"><span id="toc2">モデル選定：14B クラスの限界と可能性</span></h2>



<p>・・・色々試してみて（<span class="bold">Gemma 2 9B Instruct  SPPO Iter3 Q5_K_S 9B </span>では、ある程度うまく行った。しかし長文のpdfとなると限界があった）<br>ここで、最後に選んだのは、<br><strong>DeepSeek-R1-Distill-Qwen-14B-GGUF（mmnga）Q5_K_M</strong>。</p>



<p>選んだ理由は明確だった。</p>



<ul class="wp-block-list">
<li>日本語最適化が強い</li>



<li>事実抽出に強い</li>



<li>R1系の推論強化で論理性が高い</li>



<li>32GB RAM でも動く</li>



<li>Q5_K_M 量子化で精度が高い</li>
</ul>



<p>Copilot と Gemini の両方が推奨してきたこともあり、<br>「これならいける」と思った。</p>



<p>実際、<strong>ページ数の少ないPDFでは驚くほど正確</strong>だった。</p>



<h2 class="wp-block-heading"><span id="toc3">実際の取り組み：PDF解析で起きたこと</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30-800x533.jpg" alt="Local LLM" class="wp-image-13911" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-30.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">データセグメンテーション と　キャッシュクリア</figcaption></figure>



<p>私が扱ったPDFは、単なる文章ではない。</p>



<ul class="wp-block-list">
<li>Discord DMログ</li>



<li>メール</li>



<li>時系列資料</li>



<li>前提条件</li>



<li>英日混在</li>



<li>固有名詞・ID・ハンドル名</li>



<li>引用文</li>



<li>会話の流れ</li>
</ul>



<p>これらが複雑に絡み合った“高密度文書”ばかり。</p>



<p>ファイルサイズは小さくても、<strong>1</strong><strong>ページあたりの情報量が異常に多い</strong>。</p>



<p>最初は順調だったが、<br><strong>ページ数が増えると突然、解像度が落ち始めた。</strong></p>



<h2 class="wp-block-heading"><span id="toc4">直面した“解像度の壁”と原因</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40-800x533.jpg" alt="Local LLM" class="wp-image-13912" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-40.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">統合分析</figcaption></figure>



<p>20ページのPDFを読み込ませたとき、<br>明らかに精度が30％程度まで落ちた。</p>



<ul class="wp-block-list">
<li>文脈が飛ぶ</li>



<li>重要な記述が抜ける</li>



<li>前のPDFの内容が混ざる</li>



<li>時系列が崩れる</li>
</ul>



<p>原因は明確だった。</p>



<h3 class="wp-block-heading"><span id="toc5">&#x2714; 14Bモデルの context window の限界</span></h3>



<p>高密度PDFは、20ページでも実質40〜60ページ分の負荷になる。</p>



<h3 class="wp-block-heading"><span id="toc6">&#x2714; attention の限界</span></h3>



<p>英日混在・DMログ・引用文は attention を大量に消費する。</p>



<h3 class="wp-block-heading"><span id="toc7">&#x2714; モデル内部のキャッシュ残留</span></h3>



<p>前のPDFの内容が混ざるのは、まさにこれ。</p>



<p>私は仕方なく、(直感的に)<br><strong>モデルを eject </strong><strong>→</strong><strong> </strong><strong>新スレッド </strong><strong>→</strong><strong> </strong><strong>再読み込み</strong><br>という作業を繰り返した。</p>



<p>正しい対処だが、正直かなり面倒だった。・・・これは、後からCopiltに聞いてみたが、Copilotも「<strong>モデルを eject → 新スレッド → 再読み込み</strong>」を正しい対処方法だと認めた。</p>



<h2 class="wp-block-heading"><span id="toc8">&nbsp;64GB RAM を検討した理由と現実的な結論</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50-800x533.jpg" alt="Local LLM" class="wp-image-13913" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-50.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">パフォーマンスの最適化</figcaption></figure>



<p>「メモリを増やせば解決するのでは？」<br>そう思って調べたが、現実は違った。</p>



<h3 class="wp-block-heading"><span id="toc9">&#x274c; 14Bモデルの読解精度は RAM を増やしても変わらない</span></h3>



<p>理由は、<br><strong>モデル構造そのものが限界を決めている</strong>から。</p>



<p>ただし、64GBにすれば</p>



<ul class="wp-block-list">
<li>32Bモデルが動く</li>



<li>スワップが消える</li>



<li>安定性が上がる</li>
</ul>



<p>というメリットはある。</p>



<p>しかし、<br><strong>DDR5-5600 64GB </strong><strong>が12万円</strong><br>という現実(去年の今頃の３～４倍の価格)を見て、私は冷静になった。</p>



<h2 class="wp-block-heading"><span id="toc10">Local LLM と共生するための運用戦略</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="533" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60-800x533.jpg" alt="Local LLM" class="wp-image-13906" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60-800x533.jpg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60-500x333.jpg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60-300x200.jpg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60-768x512.jpg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Local-LLMs-60.jpg 1056w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">Local LLM</figcaption></figure>



<p>最終的にたどり着いた結論はこれ。</p>



<h3 class="wp-block-heading"><span id="toc11">&#x2714; 1〜3ページ単位で分割</span></h3>



<h3 class="wp-block-heading"><span id="toc12">&#x2714; 各チャンクを独立スレッドで処理</span></h3>



<h3 class="wp-block-heading"><span id="toc13">&#x2714; system prompt で強制リセット</span></h3>



<h3 class="wp-block-heading"><span id="toc14">&#x2714; 最後に人間（私）が統合・補完する</span></h3>



<p>これが最も安定し、コストもかからない。</p>



<h2 class="wp-block-heading"><span id="toc15">そして気づいた事：AIは“補助”、判断は人間がする</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="600" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-800x600.jpeg" alt="Local LLM　環境" class="wp-image-13914" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-800x600.jpeg 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-500x375.jpeg 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-300x225.jpeg 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-768x576.jpeg 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-1536x1152.jpeg 1536w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/IMG_6299-2048x1536.jpeg 2048w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption class="wp-element-caption">Ryzen AI9 HX470 DDR5-5600 RAM 32GB + m,2 SSD 1TB + USB4接続　m,2 SSD 1TB</figcaption></figure>



<p>Local LLM は強力だが万能ではない。<br>特に、私のように“高密度PDF”を扱う場合、<br>AIだけに任せるのは無理がある。</p>



<p>しかし、<br><strong>AI</strong><strong>が抽出した情報を人間が補完する</strong><br>この組み合わせは非常に強い。</p>



<p>私は今回の経験を通じて、<br>「AIとの共生」とは、<br><strong>AI</strong><strong>に任せすぎず、AIを道具として正しく扱うこと</strong><br>だと実感した。</p>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="800" height="228" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic-800x228.png" alt="LM Studio" class="wp-image-13919 size-full" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic-800x228.png 800w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic-500x143.png 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic-300x86.png 300w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic-768x219.png 768w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/LM-Studio-Graphic.png 858w" sizes="(max-width: 800px) 100vw, 800px" /></figure><div class="wp-block-media-text__content">
<p>LM Studio Graphic<br>high performanceのRadeon 890M Graphics を有効化</p>



<p></p>
</div></div>



<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="620" height="191" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Ryzen-AI9-HX470-NPU.png" alt="Ryzen AI9 HX470 NPU" class="wp-image-13920 size-full" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/Ryzen-AI9-HX470-NPU.png 620w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Ryzen-AI9-HX470-NPU-500x154.png 500w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/Ryzen-AI9-HX470-NPU-300x92.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></figure><div class="wp-block-media-text__content">
<p>LM Studio では現在 NPU 利用設定は無い(残念:利用できない）<br>TechPowerUp： “This processor is equipped with a Neural Processing Unit (NPU) that comes with a performance rating of up to 55 TOPS.”</p>



<p></p>
</div></div>



<p>そして、新たなアプローチへ</p>



<h2 class="wp-block-heading"><span id="toc16">Batch化</span></h2>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-none">

<a href="https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/13954/" title="&#x1f310;ローカルLLMをGUIからCLIへ：UbuntuでPDF自動翻訳バッチを運用するための考え方" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://xn--ecka7j.biz/wp-content/uploads/2026/04/00-From-GUI-to-CLI-320x180.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/04/00-From-GUI-to-CLI-320x180.jpg 320w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/00-From-GUI-to-CLI-120x68.jpg 120w, https://xn--ecka7j.biz/wp-content/uploads/2026/04/00-From-GUI-to-CLI-160x90.jpg 160w" sizes="(max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">&#x1f310;ローカルLLMをGUIからCLIへ：UbuntuでPDF自動翻訳バッチを運用するための考え方</div><div class="blogcard-snippet internal-blogcard-snippet">GUI中心のLM Studioから、Ubuntu上のCLI運用へローカルLLMをシフトし、PDF自動翻訳バッチをどのように設計するかを整理。ocrmypdfとllama-cli、DeepSeek-R1やGemma4を用いながら、IBM i 的な運用思想でAIを「使う」から「共に動かす」へ移行する道筋を解説。Ryzen AI 9 HX470</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://xn--ecka7j.biz" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">イイネ.biz</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.05.16</div></div></div></div></a>
</div>



<div class="wp-block-cocoon-blocks-blogcard blogcard-type bct-none">

<a href="https://xn--ecka7j.biz/efficiency-vs-thought-ai-symbiosis/14021/" title="AIとの共生:Geminiの迷走からCopilotとの協働へ─要求設計・外部設計・内部設計・プログラミング・バッチ運用までをAIと共に歩んだ21日間の記録" class="blogcard-wrap internal-blogcard-wrap a-wrap cf"><div class="blogcard internal-blogcard ib-left cf"><div class="blogcard-label internal-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail internal-blogcard-thumbnail"><img loading="lazy" decoding="async" width="320" height="180" src="https://xn--ecka7j.biz/wp-content/uploads/2026/05/AI-coexistence-21-da-320x180.jpg" class="blogcard-thumb-image internal-blogcard-thumb-image wp-post-image" alt="" srcset="https://xn--ecka7j.biz/wp-content/uploads/2026/05/AI-coexistence-21-da-320x180.jpg 320w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/AI-coexistence-21-da-120x68.jpg 120w, https://xn--ecka7j.biz/wp-content/uploads/2026/05/AI-coexistence-21-da-160x90.jpg 160w" sizes="(max-width: 320px) 100vw, 320px" /></figure><div class="blogcard-content internal-blogcard-content"><div class="blogcard-title internal-blogcard-title">AIとの共生:Geminiの迷走からCopilotとの協働へ─要求設計・外部設計・内部設計・プログラミング・バッチ運用までをAIと共に歩んだ21日間の記録</div><div class="blogcard-snippet internal-blogcard-snippet">Geminiの暴走と迷走に苦しんだ開発者が、Copilotと共に「要求設計→外部設計→内部設計→プログラミング→バッチ運用」まで AI と協働し、PDF英文マニュアルの翻訳バッチを完成させるまでの21日間を記録。AIと安全に共生するための最重要ポイントを技術者視点で解説。Ryzen AI 9 HX470</div></div><div class="blogcard-footer internal-blogcard-footer cf"><div class="blogcard-site internal-blogcard-site"><div class="blogcard-favicon internal-blogcard-favicon"><img loading="lazy" decoding="async" src="https://www.google.com/s2/favicons?domain=https://xn--ecka7j.biz" alt="" class="blogcard-favicon-image internal-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain internal-blogcard-domain">イイネ.biz</div></div><div class="blogcard-date internal-blogcard-date"><div class="blogcard-post-date internal-blogcard-post-date">2026.05.17</div></div></div></div></a>
</div>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
