🍉

教育ライター出身エンジニアは何を考え、どう学びを設計するのか?

に公開

これまで&これから(小峯知之 Tomoyuki.Komine)

せっかくの長期休暇。自己理解を深めるためのメモを、自己紹介も兼ねて記しておこうと思います。

これまで

  • :教育
    • Webライター・教育ライター(AI・PKM・Obsidianなど)
      - 作品例:Mermaid入門 #1 フローチャートの書き方
    • Udemy講師(AI教育)
      • ChatGPTを200%活用するマークダウン記法入門
        • プロンプトエンジニアリングの初歩を解説
        • レビュー:★4.56
        • 受講者数:77名(2025/07/05現在)
        • 無料クーポン(~2025年8月4日まで有効)
  • :エンジニア(システム開発)
    • エンジニア歴1年の駆け出し
    • 経験プロジェクト数:3(いずれも小規模)
      • WordPress記事自動投稿システム(PHP → WPプラグイン)
      • ビジネス書の付録GPTs(JSON、Markdown)
      • WordPress商品紹介記事・自動投稿システム
        • フロントエンド:PHP+JavaScript
          • スライドショー
          • 初歩的なレコメンデーションを実装
          • function.phpによるカスタマイズ
        • バックエンド:Python
          • WordPress REST API操作
          • その他API経由での商品情報取得
          • DBはWordPress側のキーバリューストアを使用(post_meta)
          • 自社システムへのスクレイピング
          • 機械学習によるノイズ判定

これから

  • ラーニング・エクスペリエンス・デザインの探求
  • RAG・LangChainの学習
    • Streamit・FastAPI・FastMCPも
    • 学習中のコード例
import os
import PySimpleGUI as sg
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
from langchain.chains import RetrievalQA
from dotenv import load_dotenv

# .envファイルから環境変数をロード。GOOGLE_API_KEYを読み込むためよ。
load_dotenv()

def run_nerv_rag(term: str) -> str:
    """
    指定された用語について、Geminiに問い合わせて回答を生成する関数。
    """
    if not term:
        return "あんたバカァ? 何を調べるか入力しなさいよ!"

    try:
        # Wikipediaから情報を引っこ抜くわよ
        url = f"https://ja.wikipedia.org/wiki/{term}"
        loader = WebBaseLoader(url)
        docs = loader.load_and_split()

        # ページが存在しない場合はエラーメッセージを返す。当然でしょ?
        if not docs:
            return f"'{term}' なんて用語、NERVのデータベースには存在しないわ。本当に実在するの?"

        # 情報をAIが理解できるベクトルデータに変換するの。これがキモよ。
        embed_model = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
        db = FAISS.from_documents(docs, embed_model)

        # 思考エンジンは最新のGemini 1.5 Flash。速くて賢いの、アタシみたいにね。
        llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash-latest", temperature=0.5)

        # これら一連の作戦(RAG)をまとめる司令塔がRetrievalQAチェーンよ。
        qa = RetrievalQA.from_chain_type(
            llm=llm,
            chain_type="stuff",
            retriever=db.as_retriever()
        )

        # プロンプト
        query = f"'{term}'というテーマについて、この私、惣流・アスカ・ラングレーが理解できるように、要点を3つに絞って解説しなさい。専門家ぶった退屈な説明は不要よ。パイロットとしての視点も少し加味すること。いいわね?"

        answer = qa.run(query)
        return answer

    except Exception as e:
        return f"作戦中にエラー発生! ちょっと、何よこれ!\nエラー内容: {e}"

# --- ここからがインターフェース部分 ---
sg.theme('DarkAmber')

layout = [
    [sg.Text('Wiki用語解説 "AsuPedia"', font=('Helvetica', 20))],
    [sg.Text('知りたい用語を入力しなさい。この私が特別に調べてあげるわ。')],
    [sg.InputText(key='-TERM-', size=(50, 1))],
    [sg.Button('調査開始', key='-SUBMIT-'), sg.Button('終了', key='-EXIT-')],
    [sg.Text('回答:', font=('Helvetica', 14))],
    [sg.Multiline(size=(88, 22), key='-OUTPUT-', disabled=True, autoscroll=True, background_color='black', text_color='#33FF33')]
]

window = sg.Window("AsuPedia v2.0", layout, finalize=True)

# --- イベントループ ---
while True:
    event, values = window.read()

    if event in (sg.WIN_CLOSED, '-EXIT-'):
        break

    if event == '-SUBMIT-':
        search_term = values['-TERM-']

        # 入力が空の場合
        if not search_term:
            sg.popup_error('用語が入力されてないじゃない! あんたバカァ?')
            continue

        # 調査中はフィードバックを返す
        window['-OUTPUT-'].update(value='Wikiに接続中...\n情報のベクトル化を開始。\nちょっと待ってなさいよね!')
        window.refresh() # これで表示を即時更新

        # RAG関数を呼び出して、答えを得る
        answer = run_nerv_rag(search_term)

        # 結果を画面に表示
        window['-OUTPUT-'].update(value=answer)

window.close()
  • PKM教育の本格化
  • AI×法学を使った社会福祉サービスの設計開発
    • 目的→「複雑な社会制度を、誰でも“使いこなせる”ものにアップデートしたい」
    • 縦割り行政に関わる諸問題の解決支援

Discussion