はじめに

自社の制度やFAQなどを生成AIに理解させたいと考えたとき、まず悩むのが「AIにどうやって知識を渡せばいいのか」という点ではないでしょうか。

社内ドキュメントを検索させる仕組みが必要なのか、データベースを用意しなければならないのかと考えると、ハードルが高く感じてしまいます。

しかし、小規模な用途やPoCであれば、そこまで複雑な仕組みは不要です。
JSON形式で整理した事前知識をそのままAIに渡すだけでも、社内FAQ対応や簡単な業務サポートであれば、十分に実用的なAIを構築できます。

よく聞く「RAG」とは?

生成AIに事前情報を与える方法として、よく登場するのが「RAG(Retrieval Augmented Generation)」です。
RAGとは、AIが回答を生成する際に、外部のデータベースや文書を検索し、その結果を参照しながら回答する仕組みを指します。

大量の社内文書を横断的に検索したい場合や、情報量が非常に多いケースでは有効な方法ですが、検索基盤やデータ管理の設計が必要になるため、最初の取り組みとしては少しハードルが高く感じられることもあります。

この記事では、RAGのような仕組みを使わずに、まずはAIに必要な知識を直接教える方法を紹介します。

JSONを使った知識の組み込み

JSONとは?

JSON(JavaScript Object Notation)は、情報を「項目」と「値」の形で整理して表現できるデータ形式です。
人が読んでも分かりやすく、AIにとっても情報のまとまりを理解しやすいという特徴があります。

例:福利厚生情報をJSONで表現

{
  "福利厚生": {
    "住宅手当": "正社員に対し家賃の20%を補助(上限3万円)",
    "通勤費": "公共交通機関の定期代を全額支給",
    "健康診断": "年1回、全社員対象に実施"
  },
  "問い合わせ先": {
    "総務部": "soumu@example.com"
  }
}

プロンプトにJSONを使うメリット

JSONを使うことで、プロンプトの安定性や再現性が大きく向上します。主なメリットは次の3つです。

  1. 情報を構造的に整理できる
    制度名・条件・詳細などの関係性を明確にでき、AIが文脈を誤読しにくくなります。
  2. 簡単に更新できる
    RAGのようにデータベースを再構築する必要はありません。JSONを書き換えて再読み込みするだけで、内容を反映できます。
  3. 回答精度が安定する
    構造化された情報を渡すことで、AIの推論が安定し、いわゆる「幻覚(hallucination)」の発生を抑えやすくなります。

テキストとJSONの比較

テキスト形式では、情報が文章の中に埋もれてしまい、AIが正確に意味を把握しづらくなります。
一方で、JSON形式は項目ごとに情報を整理できるため、内容を明確に理解させることが可能です。


実践例

ここでは、Pythonを使って社内FAQ AIを構築する手順を紹介します。
OpenAIのChatGPT APIを利用し、JSON形式でまとめた社内知識をAIプロンプトに組み込む方法を実装します。

1. JSONファイルを作成

まず、FAQや社内制度などの知識を構造化してknowledge.json​として保存します。

{
  "休暇制度": {
    "有給休暇": "勤続6か月後に10日付与",
    "リフレッシュ休暇": "勤続3年ごとに3日間の特別休暇を付与"
  },
  "福利厚生": {
    "書籍購入補助": "業務に関連する書籍を年間2万円まで会社負担で購入可能",
    "食事補助": "社員食堂を1食300円で利用可能"
  }
}

2. PythonでJSONを読み込みAIに渡す

次に、作成したJSONをPythonで読み込み、プロンプトに組み込みます。

import json
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY")

with open("knowledge.json", "r", encoding="utf-8") as f:
    knowledge = json.load(f)

prompt = f"""
あなたは社内FAQアシスタントです。
以下のJSONを参照して、質問に最も関連する情報を回答してください。
回答は必ずJSON内の情報を優先してください。

【事前知識JSON】
{json.dumps(knowledge, ensure_ascii=False, indent=2)}
"""

question = "リフレッシュ休暇は誰が対象ですか?"

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": prompt},
        {"role": "user", "content": question}
    ]
)

print(response.choices[0].message.content)

出力例

A: 勤続3年以上の社員が対象です。3日間のリフレッシュ休暇が付与されます。

応用編:大規模な知識データの扱い方

知識量が増えてくると、AIの入力上限(トークン制限)や処理コストが課題になります。ここでは、データ量が増えた場合に有効な工夫を紹介します。

1. 要約の格納

規程やマニュアルなどが長文の場合は、要点をまとめた概要をJSONに含めておくと効果的です。

{
  "勤務制度_概要": "フレックス制・リモートワーク制度を導入。詳細は別途規程参照。"
}

詳細は別ドキュメントで管理し、AIには概要だけを渡すことで、トークン使用量を抑えつつ必要な情報を伝えられます。

2. カテゴリ別分割とスコープの制御

AIに大量の知識データを一度に渡すと、処理が重くなり、効率も低下しがちです。
そこで有効なのが、情報をカテゴリごとに分割し、質問内容に応じて必要な部分だけを読み込む「スコープ制御」という考え方です。

スコープ制御の流れ

  1. ディレクトリ構造を整理する
    まず、JSONファイルをカテゴリ単位で管理できるように、次のようなディレクトリ構成にします。
📁 knowledge/
├── 福利厚生.json
├── 勤務制度.json
└── 人事関連.json
  1. 質問内容からスコープを判定する
    ユーザーから質問が来たら、その内容をもとに、どのカテゴリに該当するかを判定します。
    たとえば「カフェ手当について教えて?」という質問であれば、「福利厚生」に関する内容だと判断します。
  2. 対象となるJSONだけを読み込む
    判定結果に応じて、「福利厚生.json」だけを読み込み、AIに渡します。
    このように必要な知識だけを扱うことで、処理負荷を抑えつつ、安定した回答を得やすくなります。

まとめ

RAGを使わなくても、JSON形式を活用すれば、生成AIに必要な知識を直接与えることができます。
情報を整理して渡すことで、回答の安定性が高まり、誤った回答も減らしやすくなります。

特に、小規模なプロジェクトやPoCのように、まずは小さく試したいケースでは、この方法が有効です。
JSONでシンプルに仕組みを作り、手応えを確認したうえで、必要に応じてRAGを検討する。そうした段階的な進め方が、無理なく生成AIを業務に取り入れる近道になります。

お読みいただきありがとうございました。

はじめに

生成AIの実用化が進み、営業支援や社内ナレッジ共有など、AI活用を検討する企業が増えています。
特に、情報システム部門やDX推進担当者、AI導入を検討する現場担当者の間では、「どの言語モデル(LLM)を選ぶべきか」が重要な検討テーマとなっています。

外部サービスとして提供されるAPI型LLMを利用するか、自社管理下のサーバやクラウド上で運用するローカルLLM(オープンソースLLM)を構築するかで、コストやセキュリティ、開発体制が大きく変わります。

この記事では、ローカルLLMの特徴とAPI型LLMとの比較を通じて、導入目的に応じた最適な選び方を紹介します。
あわせて、どちらか一方を一律に推奨するのではなく、社内業務での利用を想定し、それぞれが選択肢となる条件を整理します。

ローカルLLMとは

ローカルLLMは、MetaやMicrosoftなどが公開している自由に利用・改変可能なモデルです。
自社のサーバーやクラウド環境上で稼働させることができ、機密情報を外部に出さずに活用できます。
オープンソースとして公開されているため、ライセンス費用がかからず、モデルの内部構造を理解した上でカスタマイズできるのも特徴です。

主なローカルLLMの例

モデル名提供元特徴
Llama 3Meta高精度・軽量で商用利用可能。
Phi-3Microsoft小型ながら高精度。低コスト運用が可能。
Mistral / MixtralMistral AI高速処理・日本語対応が進化。
Falcon 180BTII (UAE)完全オープンソースで多言語対応。大規模処理にも対応可能。

ローカルLLMのメリット

  1. 自社データを活かした再学習が可能
    独自データでチューニングし、業務に特化したモデルを構築できます。
  2. セキュリティを自社で完結
    外部通信を行わない設計が可能で、情報漏洩リスクを抑えられます。
    特に金融や医療など、機密性の高い情報を扱う業界では有効です。
  3. 長期的なコスト最適化
    一度環境を構築すれば、トークン課金なしで運用可能です。
    利用量が増えても追加コストが発生しないため、大規模な運用に向いています。

ローカルLLMのデメリット

  • 初期投資が必要
    GPUサーバーやクラウド環境の構築にコストがかかります。
    特に大規模なモデルを運用する場合、高性能なGPUが必要となり、初期費用が高額になる可能性があります。
  • 運用・保守の負担
    モデル更新や推論最適化にはMLOpsの知識が必要で、トラブルシューティングやパフォーマンス改善も自社で対応する必要があります。
  • 性能差
    初期状態では商用モデルに劣ることもあり、精度向上には追加の学習が欠かせません。

API型LLMとローカルLLMの比較

API型LLMは「すぐに高精度なAIを使いたい企業」に向き、ローカルLLMは「自社要件に合わせてカスタマイズしたい企業」に適しています。
両者の主な違いは、運用場所とカスタマイズ性にあります。

API型LLMとは

API型LLMとは、OpenAI・Google・Anthropicなどが提供するクラウド型AIモデルです。
APIを経由で利用でき、モデル構築不要ですぐに導入できるのが最大のメリットです。

代表的なAPI型LLMの例

モデル名提供企業主な特徴
GPT-4OpenAI高精度な言語生成・要約・コード生成が可能。ChatGPTとしても利用可。
GeminiGoogleマルチモーダル対応(画像・音声・テキストを統合処理)。Google製品との連携が容易。
Claude 3Anthropic長文処理と安全性に優れ、企業利用に適する。
Command R+Cohere検索連携(RAG)に最適化され、社内ナレッジ連携に強い。

API型LLMのメリット

  1. 導入の即効性
    APIキーを取得すればすぐに利用可能で、PoC(概念実証)や小規模実装に向いています。
  2. 高い精度と安定性
    継続的な学習により、常に最新性能が維持され、広いタスクに高精度で対応します。
  3. メンテナンス不要
    モデルの更新や改善はベンダー側が行うため、ユーザーの保守負担がほとんどありません。

API型LLMのデメリット

  • 従量課金によるコスト変動
    利用量が増えるとコストが予測しづらく、展開時に費用管理が課題となります。
  • データ外部送信リスク
    入力データがベンダーのクラウドを通過するため、セキュリティ上の制約が発生する場合があります。
  • カスタマイズの制限
    内部構造や学習データにアクセスできず、自社固有の知識を直接反映しづらい場合があります。

ローカルLLMの導入判断ポイント

ローカルLLM導入時は「利用目的」「データの取り扱い」「社内リソース」「コスト」の4つの観点で比較検討が必要です。
社内ナレッジ検索や特定業務の自動化など用途が明確な場合や、機密情報を扱う場合はローカルLLMが適しています。

ケース別おすすめモデル

用途・導入目的別のおすすめモデルを紹介します。

シナリオLLMおすすめモデル理由
小規模なAIチャット導入API型LLMGPT-4 / Geminiすぐに高品質な出力を得られる
社内ナレッジ検索システムローカルLLMLlama 3 / Phi-3内部データ連携に強い
コストを抑えたAI文書要約ローカルLLMPhi-3軽量・低コストで運用可能
Google Workspace連携API型LLMGemini組織内アプリ連携が容易
特定業務向けAI構築ローカルLLMLlama 3再学習により最適化が可能

さいごに

業務で生成AIを扱う機会が増える中で、目的や体制に合わせた使い分けが大切です。
まずはAPI型LLMで小さく試し、運用で得た知見をもとにローカルLLMで内製化や最適化を進めていく段階的な進め方が現実的だと考えています。
実際に使いながら理解を深めていくことで、プロジェクトに適したLLMが少しずつ見えてくるのではないかと思います。

お読みいただきありがとうございました。

はじめに

システム開発でよく使われるデータベースといえば、RDB(リレーショナルデータベース)が定番です。私のチームでも長らく、Oracle や MySQL などの RDB を利用してきましたが、ある新規APIの開発で MongoDB を採用してみたところ、思っていた以上に開発がスムーズになりました。

この記事では、MongoDB を Java + Spring Boot で使用してみて感じた3つのメリットを、実際の実装例を交えて紹介します。

MongoDB の特徴

MongoDB はドキュメント指向の NoSQL データベースであり、RDB と比べて非常に緩い設計になっているのが特徴です。RDBと違いを感じるのは、例えば以下のような点です。

  • 構造化オブジェクト(JSONのようなもの)を丸ごと保存できる
  • 格納するオブジェクトの仕様を厳密に決めておく必要が無い(カラム定義などは不要)
  • コレクション(RDBでいうところのテーブル)に追加しようとしたときに、コレクションが無ければ自動的に作成される。データベースが無かった場合は、データベースも自動的に作成される

プログラムから 何でも入る入れ物 的な感覚で、簡単に使えるのが特徴です。

簡単に始められる MongoDB

MongoDB の準備

MongoDB はローカルにインストールして起動します。インストール手順は割愛しますが、Dockerイメージ を使うか、公式サイトからダウンロードしてインストールすることになります。

前述した通り、データベースやコレクションを用意する必要は無いのですが、ユーザだけは用意しておく必要があります。インストールした後、以下のコマンドを MongoDB Shell などで実行します。

use admin
db.createUser({
  user: "appuser",
  pwd:  "secret",
  roles: [ { role: "readWrite", db: "sampledb" } ]
})

Spring Boot の設定

Spring Boot では、spring-boot-starter-data-mongodb を依存関係に追加するだけで、 MongoDB を簡単に利用できます。Maven の場合は以下を pom.xml に追加します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

接続設定は Spring Boot の application.yml に以下のように記述します。

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: sampledb
      username: appuser
      password: secret
      auto-index-creation: true

auto-index-creation は、後に説明する @Indexed でインデックスを作る機能を有効にするための設定です。

エンティティ

@Document(collection = "login_history")
public class LoginHistory {
    @Id
    private String id;

    @Indexed
    private String userId;

    @Indexed(expireAfter = "30d") // 30日で自動削除
    private LocalDateTime createdAt;
}

エンティティクラスに付けている @Document アノテーションで、保存するコレクション名を指定しています。

@Id をつけたフィールドは _id という特殊なフィールドにマッピングされます。これはコレクション内でドキュメントを一意に識別するための値で、RDBでいうところの主キーに相当する役割を持ちます。

@Indexed は項目にインデックスを作成するアノテーションです。RDBのインデックスと同様で、この項目による検索を高速に行えるようになります。

expireAfter をつけると、 TTL(Time To Live)インデックス という特殊なインデックスが作成されます。これは、設定した期間を過ぎると、MongoDBが自動的にレコードを削除してくれる機能です。この例では createdAt から30日以上経過している場合に削除対象となります。

リポジトリ

public interface LoginHistoryRepository extends MongoRepository<LoginHistory, String> {
    List<LoginHistory> findByUserId(String userId);
}

あとはこのリポジトリをDIして、簡単に読み書きができます。

// 保存
loginHistory.setId("a001");
loginHistory.setUserId("sampleUser");
loginHistory.setCreatedAt(java.time.LocalDateTime.now());
loginHistoryRepository.save(loginHistory);

// IDで取得
Optional<LoginHistory> h1 = loginHistoryRepository.findById("a001");

// ユーザIDで取得
List<LoginHistory> histories = loginHistoryRepository.findByUserId("sampleUser");

このようなコードで最初のレコードを save すると、MongoDB 側には自動的に login_history コレクションが作成され、userIdcreatedAt にインデックスが付与されます。

実感した MongoDB の3つのメリット

1. DDL作成や実行が不要

前述した通り、MongoDB はコレクションが無くても自動的に作ってくれますし、スキーマを決めておく必要もありません。

そのため、Spring のプログラムから何かを保存したいと思ったときに、エンティティとリポジトリさえ用意すれば、すぐに保存することができます。

これによって、開発者がプログラムとDBを同時に扱えるようになり、RDBと比べて開発の自由度とスピードが上がりました。

2. TTLインデックスによる自動削除が便利

ログやセッション情報など、「一定期間で削除してよいデータ」は多く存在します。RDBでは古いデータを削除するためにバッチ処理を用意し、スケジュール実行・監視を行うのが一般的です。

MongoDBでは、前述したTTLインデックスを設定するだけで、MongoDBが自動的に期限切れのデータを削除してくれるため、削除バッチを作る必要がなくなりました。

3. データ構造が柔軟で変更に強い

正規化せずにデータを格納するため、RDBでは複数テーブルに分けてJOINしていたデータも1ドキュメントにまとめて保持できます。

そのため、データ構造が変更になっても、RDBと比べて影響が少なく、変更に強いと感じました。

導入して感じたこと

MongoDB はとても使いやすくて便利なデータベースですが、必ずしもRDBよりも優れているというわけではありません。向き不向きはあります。

具体的には、やはり正規化されていないので、複雑な結合クエリや集計は書きづらいです。複雑な検索が必要なデータには、RDBのほうが向いていると思います。

一方で、複雑な集計を必要としないデータであれば、非常に使いやすく、用途によっては良い選択肢になると感じました。

まとめ

MongoDB を Java/Spring 環境で使ってみて感じたメリットは、以下の3点でした。

  • DDL作成や実行が不要
  • TTLインデックスによる自動削除が便利
  • データ構造が柔軟で変更に強い

一昔前は、データベースと言えばRDBでしたが、最近は MongoDB のようなドキュメント指向DBを始めとして、様々な種類のデータベースが登場しています。そして、それらが現場で使われ始めているとも感じています。

データベースには向き不向きがあります。特定の技術に固執するのではなく、様々な種類のデータベースの特徴を比較検討し、最適なものを選択することが、これからの開発には求められていくと思います。

Learn how we helped 100 top brands gain success