Claudeで図面の公差を拾い、加工の見積依頼の条件を揃える
加工図面のPDFから材質・寸法公差・表面処理の注記を原文つきの表に起こし、図面に無い項目を空欄で残して、各社に同じ条件で見積を依頼する手順です。
たとえば、3社に同じ図面を送ったのに、見積の金額が倍近く違うとします。理由を聞くと、A社は図面の注記どおりの表面処理で、B社は「指示がないので無処理」で、C社は公差を一段ゆるく読んでいた。こういう食い違いの多くは、図面に書いてある条件と、依頼メールに書いた条件が揃っていないことから起きます。
この記事は、加工図面のPDFをClaudeに読ませて、寸法公差・表面粗さ・表面処理・材質などの注記を「原文つきの条件表」に起こし、その表から依頼文を作る手順です。ポイントは、図面に書かれていない項目を推測で埋めず、空欄のまま質問として残すことにあります。数量拾いの入口はClaudeで積算の数量拾いをする方法、届いた見積の比較は見積書PDFをClaude APIで品目表に構造化する方法にあり、ここで扱うのは、見積を取る前の「依頼条件をそろえる」工程です。
見積の前提差はどこで生まれるか
加工の見積依頼で金額を動かす条件は、図面のあちこちに散らばっています。依頼文を書く人が全部を拾い切れず、拾った分だけが依頼文に載るので、受け取った側は図面と依頼文の「読める範囲」で前提を置きます。
| 条件の種類 | 図面での書かれ方の例 | 揃っていないと起きること |
|---|---|---|
| 材質・材料規格 | 図面での書かれ方の例材質欄、注記 | 揃っていないと起きること代替材で見積が出る |
| 寸法公差 | 図面での書かれ方の例寸法に直接付いた公差、一般公差の注記 | 揃っていないと起きること加工工程や検査の想定がずれる |
| 幾何公差 | 図面での書かれ方の例公差記入枠(データム付き) | 揃っていないと起きること測定方法の違いで価格が変わる |
| 表面粗さ | 図面での書かれ方の例粗さ記号、注記 | 揃っていないと起きること仕上げ工程の有無が変わる |
| 表面処理・熱処理 | 図面での書かれ方の例注記欄、表題欄の近く | 揃っていないと起きること処理が見積に入る会社と入らない会社が出る |
| 数量・納期・検査書類 | 図面での書かれ方の例図面に無いことが多い | 揃っていないと起きること依頼文にも無ければ各社が違う仮定を置く |
最後の行が要点です。数量・納期・検査書類は図面に無いことが多く、依頼文を書く人が決めて書かなければ誰も揃えられません。Claudeに表を作らせると、この「図面に無い項目」が空欄として見えるようになります。
PDFを渡す前に確かめておくこと
図面PDFは、一般の文書より条件に引っかかりやすい資料です。PDF対応の要件は次のとおりです。
| 項目 | 上限・条件 |
|---|---|
| リクエストサイズ | 上限・条件32MB(プラットフォームにより異なる) |
| 1リクエストのページ数 | 上限・条件600ページ(コンテキストウィンドウが100万トークン未満のリクエストは100ページ) |
| 形式 | 上限・条件標準的なPDF(パスワード・暗号化なし) |
サイズとページ数はリクエスト全体に掛かります。文字の小さいページや複雑な表、図の多いPDFは、ページ数の上限より前にコンテキストウィンドウを埋めることがあります。パスワードで保護された図面PDFは、保護を外した複製を作ってから渡します。ページ数やサイズが原因の失敗は、「Could not process PDF」400エラーの原因と対処法で症状別に見分けられます。
PDFを渡すと、各ページが画像に変換され、ページから抽出された文字が画像と並べて渡されます。CADから文字を埋め込んで書き出したPDFなら、注記は文字としても画像としても読まれます。スキャンした図面は画像だけが頼りになるので、細かい注記ほど読み違いが出やすくなります。
画像認識の制限も、公差の読み取りに直接関わります。低品質・回転・小さい画像では誤りが出ることがあり、位置や座標の出力は概算で、物の数え上げも不正確になりやすいと書かれています。「0.05」と「0.03」の取り違えのような読み間違いは、この制限の範囲で起こりえます。だから条件表には、必ず原文と読み取り位置を残します。
条件表の列を先に決める
Claudeに「図面を要約して」と頼むと、読みやすい文章が返りますが、各社に送る条件にも照合の足場にもなりません。先に列を決め、1行を1条件にします。
| 列 | 中身 | 空欄のとき |
|---|---|---|
| item | 中身条件の名前(材質、表面処理など) | 空欄のとき使わない |
| drawing_text | 中身図面の原文をそのまま写した文字列 | 空欄のとき図面に記載なし |
| location | 中身ページ番号と、注記欄・表題欄・視図名などの位置 | 空欄のとき位置不明 |
| status | 中身stated(明記)/unclear(読み取り不確か)/absent(図面に無い) | 空欄のとき使わない |
| request_text | 中身依頼文にそのまま貼れる文面 | 空欄のときstatusがabsentの行は空にする |
| question | 中身absentとunclearの行で、依頼者が決めること | 空欄のとき使わない |
効いているのは status の3区分です。absent を許すだけで、Claudeは「無い項目を一般的な値で埋める」方向に流れにくくなります。drawing_text が原文であるおかげで、人が図面と1行ずつ照合できます。
PDFを渡して条件表のJSONを受け取る
PDFをテキストより前に置くと結果が安定する、というのがPDF対応のベストプラクティスです。ほかに、標準的なフォントを使う、文字を明瞭にする、ページを上向きに直す、プロンプトではPDFビューアの論理ページ番号を使う、が挙げられています。次のスクリプトはこの順序で書いています。
pip install anthropic
export ANTHROPIC_API_KEY="..."
export CLAUDE_MODEL="使うモデルのID"
python extract_conditions.py drawing_001.pdf > conditions.jsonimport base64, json, os, sys
import anthropic
ITEMS = ["材質", "寸法公差", "一般公差", "幾何公差", "表面粗さ",
"表面処理", "熱処理", "バリ・面取り", "検査・成績書", "その他の注記"]
PROMPT = f"""添付は加工部品の図面PDFです。次の項目ごとに条件を拾い、
JSON配列だけを返してください。
項目: {', '.join(ITEMS)}
各要素のキー:
- item: 上の項目名
- drawing_text: 図面の原文をそのまま写す。要約・言い換えをしない
- location: PDFのページ番号と、注記欄・表題欄・視図名など
- status: stated / unclear / absent のいずれか
- request_text: 見積依頼にそのまま貼れる1文。absentなら空文字
- question: absent と unclear のとき、依頼者が決める内容
規則:
- 図面に書かれていない項目は status を absent にし、一般的な値で補わない
- 読み取りに自信がない数値や記号は status を unclear にする
- 同じ項目が複数箇所にあれば、要素を分ける
"""
def extract(pdf_path: str) -> list[dict]:
with open(pdf_path, "rb") as f:
pdf_b64 = base64.standard_b64encode(f.read()).decode("utf-8")
client = anthropic.Anthropic()
message = client.messages.create(
model=os.environ["CLAUDE_MODEL"],
max_tokens=4096,
messages=[{
"role": "user",
"content": [
{"type": "document",
"source": {"type": "base64",
"media_type": "application/pdf",
"data": pdf_b64}},
{"type": "text", "text": PROMPT},
],
}],
)
text = message.content[0].text
rows = json.loads(text[text.index("["): text.rindex("]") + 1])
covered = {r["item"] for r in rows}
for item in ITEMS:
if item not in covered: # 返ってこなかった項目も空欄として残す
rows.append({"item": item, "drawing_text": "", "location": "",
"status": "absent", "request_text": "",
"question": f"{item}の指定を決める"})
return rows
if __name__ == "__main__":
json.dump(extract(sys.argv[1]), sys.stdout, ensure_ascii=False, indent=2)最後のループは、Claudeが項目を飛ばしたときの保険です。飛ばされた項目を「図面に無い」と区別できる形で残すため、question に決める内容を入れて absent にしています。ただし、absent が「図面に本当に無い」のか「見落とした」のかは、この段階では区別できません。人が図面の注記欄を見て確かめる欄になります。
書き出されるJSONは、例えば次のような形になります(架空の図面の例です)。
[
{
"item": "表面処理",
"drawing_text": "表面処理:無電解ニッケルめっき 5μm",
"location": "p.1 注記欄 注3",
"status": "stated",
"request_text": "表面処理は無電解ニッケルめっき(膜厚5μm)とする。",
"question": ""
},
{
"item": "検査・成績書",
"drawing_text": "",
"location": "",
"status": "absent",
"request_text": "",
"question": "寸法検査成績書の要否と、検査対象の寸法を決める"
},
{
"item": "寸法公差",
"drawing_text": "Φ12 H7(下の寸法線は潰れて読めない)",
"location": "p.1 正面図 右下の穴",
"status": "unclear",
"request_text": "",
"question": "Φ12の穴の公差等級を図面原本で確認し、H7でよいか決める"
}
]unclear の行は、読めた部分だけを drawing_text に写し、読めなかった箇所を括弧で書き添えさせます。request_text は空にして、question に図面原本で何を確かめるかを書かせます。こうしておくと、人が見に行く場所がページと視図まで絞れます。
一般公差の注記(「普通公差 中級」のように等級だけを示すもの)を拾ったときは、item を 一般公差 にして1行にまとめ、drawing_text に注記をそのまま写します。個々の寸法に付いた公差とは別の行にしておけば、依頼文でも「個別指定のある寸法」と「それ以外の寸法」を分けて書けます。
APIを使わず、claude.aiの画面で同じ表を作る
プログラムを書かなくても、claude.aiのチャットに図面PDFを添付すれば同じ条件表は作れます。チャットの「+」から「Add files or photos」を選ぶか、ファイルをチャット欄へドラッグ&ドロップします。上の PROMPT の本文(項目・キー・規則の部分)をそのまま貼り、「JSON配列だけ」の指定を「表形式で」に変えれば、画面上で表として読めます。
アップロードの上限はAPIと別で、チャットでは1ファイル500MB・1チャット20ファイル・PDFは1000ページまでです。ただし視覚要素(図や線画)まで読まれるのは100ページ以下のPDFに限られ、101ページ以上は文字だけが読まれます。図面は線と記号が中身なので、100ページを超える図面集は分けて添付します。ページを指定するときは、図面の枠内に印刷された番号でなく、PDFビューアの番号を使います。
プロジェクトのファイルに入れた場合は、マルチモーダルPDFを除いて文字の抽出だけが使われます。図面の注記を画像として読ませたいときは、プロジェクトに置かず、チャットへ直接添付します。
画面での作業は、JSONの代わりに表を人が直接見られる点が利点です。一方で、次の項で述べる「2回読ませて突き合わせる」作業はコピーと比較を手でやることになります。件数の多い図面を日常的に回すなら、APIのスクリプトが向きます。
図面に無い項目を、依頼者の決定事項に変える
absent の行は、依頼文では空欄にできません。各社が違う仮定を置く場所になるからです。そこで、question の列を人が埋め、決めた内容を request_text に移します。
| 例 | absent で出る質問 | 決め方の見当 |
|---|---|---|
| 検査・成績書 | absent で出る質問成績書は要るか、どの寸法を測るか | 決め方の見当受入検査の運用に合わせる |
| 熱処理 | absent で出る質問材質の指定だけで足りるか | 決め方の見当設計者に確認する |
| 数量・納期 | absent で出る質問ロット数、納入希望日 | 決め方の見当発注側で決める |
| 梱包・納入形態 | absent で出る質問防錆・個別包装の要否 | 決め方の見当運用に合わせて指定する |
図面の外にある条件(数量・納期・梱包)は、ITEMS に足して同じ表に載せると、1枚の表で依頼条件が閉じます。ITEMS はそれぞれの会社の依頼書の項目に合わせて増減してください。
人が確認する欄と、Claudeに任せる欄
Claudeの出力は、図面と突き合わせるまで下書きです。確認の分担は次のとおりです。
| 作業 | Claudeに任せる | 人が見る |
|---|---|---|
| 注記の転記 | Claudeに任せる注記欄の文字を列に整理する | 人が見るdrawing_text が原文と一字一句同じか |
| 寸法公差の拾い出し | Claudeに任せる各寸法の公差表記の抽出 | 人が見る数値・符号(+ − ±)・桁を図面と照合 |
| 幾何公差 | Claudeに任せる公差記入枠の内容の文字化 | 人が見る記号・データム文字・数値 |
| 表面処理 | Claudeに任せる処理名・膜厚・規格の抽出 | 人が見る図面の改訂版に対応しているか |
| 空欄の洗い出し | Claudeに任せるabsent と unclear の列挙 | 人が見る本当に図面に無いか |
| 依頼文の整形 | Claudeに任せるrequest_text の組み立て | 人が見る社外に出してよい表現か |
公差は、桁の取り違えがそのまま加工の可否に関わります。status が stated の行でも、公差の数値だけは全行を人が図面と照合する前提にします。これは数量拾いと同じ考え方で、同じ図面を別の切り出しでもう一度読ませて、2回の結果が割れた行を優先して図面に戻る方法も使えます。切り出しと照合の組み立ては積算の数量拾いの記事に詳しく書かれています。
条件表では、extract_conditions.py を2回実行して conditions_a.json と conditions_b.json を作り、item と location の組ごとに突き合わせます。
python extract_conditions.py drawing_001.pdf > conditions_a.json
python extract_conditions.py drawing_001.pdf > conditions_b.json
python compare_runs.py conditions_a.json conditions_b.jsonimport json, sys
def load(path):
rows = json.load(open(path, encoding="utf-8"))
return {(r["item"], r["location"]): r for r in rows}
a, b = load(sys.argv[1]), load(sys.argv[2])
for key in sorted(set(a) | set(b)):
ra, rb = a.get(key), b.get(key)
if ra is None or rb is None:
print(f"片方にだけある行: {key}")
elif ra["drawing_text"] != rb["drawing_text"] or ra["status"] != rb["status"]:
print(f"結果が割れた行: {key}")
print(f" A: {ra['status']} / {ra['drawing_text']}")
print(f" B: {rb['status']} / {rb['drawing_text']}")出力に出た行から先に、図面原本と見比べます。2回とも同じ結果だった行でも、同じ読み違いを繰り返している場合があるので、公差の数値は全行の照合が要る点は変わりません。location の書き方が回ごとに揺れると別の行に見えるため、割れた行が多すぎるときは、まず location の書式を揃える指示をプロンプトに足します。
細かい注記が潰れて読めないときは、PDF全体を渡すのをやめて、注記欄と表題欄だけを切り出した画像で読み直します。画像は大きすぎると縮小されて文字が読みにくくなりうるため、文字が読める大きさのまま渡します。日本語の読み取り精度そのものを測る手順は、Claude VisionでOCRした日本語PDFの精度の見極め方にあります。
条件表から見積依頼文を作る
確認が終わった表は、依頼文の元になります。request_text を項目順に並べるだけで、各社に同じ文面で条件を伝えられます。
import json, sys
rows = json.load(open(sys.argv[1], encoding="utf-8"))
decided = [r for r in rows if r["request_text"]]
open_items = [r for r in rows if not r["request_text"]]
print("見積依頼条件(図面番号: ________ / 改訂: ____)")
for i, r in enumerate(decided, 1):
print(f"{i}. {r['item']}: {r['request_text']}")
if open_items:
print("\n未確定の項目(送付前に決めてください)")
for r in open_items:
print(f"- {r['item']}: {r['question']}")未確定の項目が1つでも残っているときは、送付を止めます。この出力を見れば、決まっていない項目が先に見えるからです。決まった依頼文は、全社に同じものを貼ります。会社ごとに文面を書き換えると、前提差をまた作ることになります。
各社からの質問が来たら、答えを条件表に1行足してから、全社に同じ補足を流します。1社だけに答えると、他社の見積が別の条件のままになります。
つまずきやすい点
- 「無処理」と書かれた回答: 図面に表面処理の指定がないとき、各社が「無処理」と置くことがあります。
absentのまま送らず、依頼者が「指定なし」と決めて書きます - 一般公差の注記を寸法の公差と取り違える: 一般公差は図面全体に掛かる注記、寸法公差は個々の寸法に付く指定です。
itemを分けておくと取り違えを見つけやすくなります - 図面の改訂版が混ざる: 依頼文に図面番号と改訂記号を書き、条件表の元にした版と一致させます
- Claudeが条件を言い換える:
drawing_textには「要約・言い換えをしない」と指示しておき、原文と違う行を人が見つけられるようにします - 取引先に図面を送ってよいか: 図面は機密にあたることがあるため、APIに渡す前に自社の取り決めを確認します
まとめ
見積依頼の条件を揃える作業は、図面の注記を「原文・位置・状態」の3つで表に起こし、図面に無い項目を決定事項として埋めるところに尽きます。Claudeに任せるのは、注記の転記と空欄の洗い出しまでです。公差の数値は人が図面と照合してから、全社に同じ文面で依頼します。届いた見積の比較は、品目表への構造化がその続きの工程です。