🤝

アサイン支援エージェント:ナレッジグラフで人材アサインの暗黙知を形式化する

に公開

はじめに

本記事では、東京エレクトロンデバイス様主催の Microsoft Agent Hackathonにおいて、弊社 ヘッドウォータースプロフェッショナルズチームが取り組んだ内容についてご紹介します。

この記事のサマリー

SES営業の現場では、新しいプロジェクト案件が舞い込むたびに、営業担当者の頭の中で似たような問いが繰り返されています。「この案件に合う人は誰だろうか」「あのメンバーは確かこういう経験があったはず」「今月稼働が空く予定の人はいたか」。こうした問いに答えるため、担当者は経歴書のPDFを開き、メンバープロフィールを参照し、稼働管理表を確認し、過去の類似案件の記憶をたどることになります。

このプロセスは確かに機能しています。ただし、機能しているのは「ベテラン営業担当者の経験と勘」が支えているからに他なりません。情報は社内のあちこちに点在し、判断ロジックは個人の中に閉じています。組織が大きくなるほど、この属人性が組織全体のボトルネックとして顕在化していきます。

本稿では、この課題に対する解決策として構築した「アサイン支援エージェント」の技術検証結果をご報告します。Microsoft Fabric IQ上にナレッジグラフを構築し、さらにAzure AI Searchによるベクトル検索で意味ベースの類似案件検索を組み合わせることで、自然言語で人材推薦・候補比較・アサイン理由生成を実行できるAIエージェントを実装しました。


1. 課題背景:アサイン業務の属人化と非効率

1.1 現状のアサイン決定プロセス

現在、新規案件に対する人材アサインは概ね以下のフローで行われています。

  1. 案件情報の受領(要求スキル、期間、ロール、業界等)
  2. 営業担当者が候補者を検討
  3. 経歴書(PDF/Word)で個別メンバーのスキル・経験を確認
  4. メンバープロフィール管理システムで属性情報を確認
  5. 稼働管理表で参画可能時期を確認
  6. 最終的には担当者の経験と勘で候補者の適性を判断し、選定

このプロセスを支えているのは、複数の情報源を横断的に確認する担当者の労力と、各担当者が持つ過去案件や各メンバーのスキルレベルなどといった暗黙知です。いずれもスケールしない要素であると言えます。

1.2 顕在化している課題

実務の中で繰り返し直面する課題は、以下に集約されます。

  • 情報が分散しており、確認に時間がかかる:
    経歴書はファイルサーバー、プロフィールはHRシステム、稼働状況は別の管理表に存在しています。一人の候補者を評価するために3〜4のシステムを往復することになります。
  • 判断基準が属人化し、再現性が低い:
    「Aさんは金融案件に強い」「Bさんはこういう要件で前にうまくいった」という知識が個人の中にしかなく、担当者が変わると同じ判断は再現できません。
  • 担当者以外のメンバーが何を知っているかわからない:
    営業担当が普段関わるメンバーは限られており、隣のチームに最適な人材がいても気付けないことがあります。組織が大きいほど、この情報の死角は広がっていきます。
  • 最適候補者の見落としリスク:
    情報を網羅的に検索する手段がないため、「知っているメンバーの中で最善」を選ぶしかないのが実情です。本当の最適解にたどり着けているかを検証する手段がありません。
  • プロジェクト開始までのリードタイムが長くなる:
    情報収集、候補比較、調整のすべてが手動であるため、案件受領から提案までに数日を要することも珍しくありません。スピード感のある競合に案件を奪われる要因にもなります。

1.3 課題の本質

これらの課題の根本にあるのは、社内に存在する「人材に関する情報」が、構造化された知識として統合されていないという点です。経歴書、プロフィール、稼働状況、過去のアサイン履歴、これらはすべて貴重な情報資産ですが、データソースとして分散しているため、横断的な検索や関係性に基づく推論ができません。

加えて、過去案件のような自由記述の情報は、構造化が難しい性質を持ちます。「金融系のリアルタイム取引基盤の刷新案件」のような案件概要は、スキル名のキーワード一致だけでは類似案件として見つけ出すことが困難です。

つまり、本質的な問題は「データ不足」ではなく、「構造化情報の統合不在」と「非構造化情報の意味的検索の不在」という二重の知識化の不在だと考えています。


2. 解決アプローチ:ナレッジグラフとベクトル検索を組み合わせたAIエージェント

2.1 全体構想

本検証では、社内に分散する人材データを統合してナレッジグラフとして表現し、さらに過去案件の概要をベクトル検索可能な形で整備したうえで、両者をAIエージェントのコンテキストレイヤーとして提供する方式を採用しました。これにより、以下の機能を自然言語インターフェースで提供する「アサイン支援エージェント」を構築します。

  • プロジェクト要件に対する最適人材の推薦:案件の要求スキル・期間・ロールから候補者をスコア付きでリストアップします
  • 類似案件の意味ベース検索:新規案件の概要から、過去の類似案件をベクトル検索で発見し、その経験者を候補に含めます
  • 候補者のスキル・稼働状況・過去実績の自動比較:複数候補を横並びで定量比較します
  • アサイン理由の説明生成:「なぜこの人物を推薦するか」を根拠プロジェクトと共に自然言語で生成します
  • 代替案の提示:完全一致の候補が不足する場合、隣接スキル保有者や類似経験者を代替案として提示します

2.2 なぜナレッジグラフなのか

人材アサインは本質的に「関係性を辿る」タスクだと捉えています。

「Pythonの経験がある人」を検索するだけであれば、テーブル検索で済みます。ところが実務では「Pythonと機械学習を両方持ち、金融業界のプロジェクト経験があり、PMロールで動ける人」のような複合条件を、「なぜそう判断したか」の根拠付きで返す必要があります。これはMember → WORKED_ON → Project → REQUIRES_SKILL → Skillのようなパス探索であり、関係性を構造化して保持するナレッジグラフが本質的に適しています。

加えて、ナレッジグラフでは「派生関係」を明示的に表現できます。生のプロジェクト参画履歴(WORKED_ON)と、各プロジェクトの必要スキル(REQUIRES_SKILL)から、社員のスキル保有状況(HAS_SKILL)を派生的に集約することが可能です。エージェントは集約済みの指標でランキングし、根拠が必要なときは生履歴に降りて具体的なプロジェクト名を提示できます。

2.3 なぜベクトル検索を組み合わせるのか

ナレッジグラフは構造化された関係性の検索に強い反面、自由記述の意味的な近さを捉えるのは苦手です。例えば「リアルタイムデータ処理基盤の構築案件」と「ストリーミング分析プラットフォームの開発案件」は、使われるキーワードが異なっていても本質的に類似した案件と言えます。こうした意味ベースの類似性は、テキストをベクトル化して類似度を計算するアプローチが最も適しています。

そこで本検証では、Azure AI Searchのベクトルインデックスを用いて、過去のプロジェクト概要を埋め込みベクトルとして保持する補完レイヤーを構築しました。新規案件の概要をクエリベクトルに変換し、過去の類似案件を意味的に検索することで、ナレッジグラフだけでは捉えきれない「経験の質的な類似性」を補完します。

ナレッジグラフとベクトル検索を組み合わせる狙いは明確です。ナレッジグラフが「条件で絞り込む」役割を担い、ベクトル検索が「意味で広げる」役割を担うという分業構造です。「Pythonの経験者」のような明示的条件はグラフが扱い、「過去にこの案件と似たことをやった人」のような暗黙的類似性はベクトル検索が扱います。両者を組み合わせることで、構造的な精度と意味的な広がりの双方を備えた検索が可能になります。

2.4 なぜAIエージェントなのか

ナレッジグラフを構築し、ベクトル検索を整備しても、それを使うのが営業担当者である以上、利用者がグラフクエリ言語を書いたりベクトル検索APIを叩いたりする必要があってはなりません。自然言語で問いかけ、自然言語で答えが返る体験が不可欠です。

Microsoft Fabric IQのData Agent機能は、複数のデータソースを統合して扱えるよう設計されています。Ontology(ナレッジグラフ)とAzure AI Searchのインデックスを同一エージェントの参照先として登録することで、エージェントは質問の意図に応じて適切なデータソースを選択し、必要に応じて両者の結果を統合して回答できます。

2.5 期待される効果

本エージェントの導入により、以下の効果を見込んでいます。

観点 現状 導入後
候補者検索の所要時間 数十分〜数時間 数秒
検索の網羅性 担当者が知るメンバーのみ 全社員
判断の再現性 個人依存 集計指標で説明可能
推薦理由の説明 担当者が手動作成 自動生成
隣接候補の発見 困難 代替案として自動提示
類似案件の参照 担当者の記憶頼み ベクトル検索で意味的に発見

検索スピードと精度の向上は当然のこととして、特に重視しているのは「判断プロセスの形式知化」です。エージェントが返す推薦には、必ずスコアと根拠プロジェクトが付随します。これは「なぜこの人を推薦したか」を、ベテランの経験ではなくデータで説明可能にすることを意味します。属人化からの脱却こそが、最も大きな価値だと位置付けています。


3. システム全体構成

ナレッジグラフ・ベクトル検索を中核としつつ、営業担当者が日常的に利用できるよう、シンプルなチャットインターフェースを備えたWebアプリケーションとして実装しました。アプリケーション全体の構成は以下の通りです。

3.1 フロントエンド:Next.js

フロントエンドはNext.jsで実装し、シンプルなチャットUIとしました。営業担当者が自然言語で問い合わせを入力し、エージェントからの回答をリアルタイムに受け取れる構成としています。ビジネスユーザーでも直感的に扱えることを最優先としました。

3.2 バックエンド:FastAPI & Microsoft Agent Framework

バックエンドはFastAPIで構築し、エージェントの処理結果をストリーミング形式でフロントエンドに返します。

バックエンド内部では、リクエストを受け取ったOrchestratorに処理を委譲し、Orchestratorがスレッド管理とReAct ループを担います。実際の推薦ロジックはMain Agentが担当し、必要に応じてTool経由でFabric Data Agentを呼び出す構成です。

3.3 エージェント層:Fabric Data Agent

Microsoft Fabric側には、目的別に2つのData Agentを配置しています。

Knowledge Graph Agentは、Lakehouse上に構築したナレッジグラフを参照し、構造化された人材検索を担当します。「Pythonの経験者をTop10で」「PMロールでクラウド系プロジェクトを経験した人」のような明示的な条件検索が中心です。

Vector Search Agentは、Azure AI Searchのベクトルインデックスを参照し、意味ベースの類似案件検索を担当します。「この提案文に似た過去案件」「リアルタイム処理系の経験を持つ人」のような、自由記述の意味的類似性を扱います。

バックエンドのMain Agentは、ユーザーの質問内容に応じてこれら2つのエージェントを使い分け、必要に応じて両者の結果を統合して最終回答を生成します。この役割分担により、構造化検索と意味検索の双方の強みを活かせる構成となっています。

3.4 認証と運用基盤

Azure環境の各種リソースへのアクセスは、Managed Identity(DefaultAzureCredential)を用いて統合的に認証しています。アプリケーションコード内に認証情報を埋め込む必要がなく、運用上のセキュリティリスクを最小化しています。

監視・ロギングはApplication Insightsに集約し、エージェントの応答時間、エラー率、トークン消費量等を可視化しています。本番運用に向けて、応答品質の継続的な観測と改善ループを回せる基盤としています。

3.5 構成上の設計意図

本アプリケーション構成は、**「データレイヤー層をFabric側、エージェントオーケストレーションをアプリ側」**とし、実装上の責任境界を明確にしています。データ統合、ナレッジグラフ管理、ベクトル検索といった重量級の処理はすべてFabric内に閉じ込め、アプリケーション側はそれらを呼び出すオーケストレーションとUI提供に専念する構成です。

データの構造やインデックスの更新があってもアプリケーション側の改修は最小限で済み、逆にUI/UXの改善もデータ層に影響を与えません。レイヤー分離によって、それぞれの関心事を独立して進化させられることが、長期運用において大きな利点になると考えています。

4. Fabric IQによるコンテキストレイヤーの実装

4.1 ナレッジグラフの構成

人材アサインに必要な情報をFabric IQのOntology / Graph上に表現するにあたり、3つのエンティティと3つの関係でナレッジグラフを設計しました。

3つのエンティティを実線2本と破線1本で結ぶ構造です。HAS_SKILLを破線で表しているのは、これが直接入力されるデータではなく、WORKED_ONREQUIRES_SKILLから派生計算される関係であることを示しています。

スキーマ詳細

Member(dim_member)

社員の基本情報を保持するエンティティ。

カラム 説明
engineer_id string 社員一意ID(Primary Key)
full_name string 氏名
full_name_kana string 氏名カナ
joined_at date 入社日
age integer 年齢
employee_type_label string 雇用形態
enployment_state_label string 稼働状態
career_summary string プロフィール(自由記述)

Project(dim_project)

社員が過去に従事したプロジェクトを表現するエンティティ。

カラム 説明
project_id long プロジェクト一意ID(Primary Key)
title string プロジェクト名
description string プロジェクト詳細(自由記述)
team_size integer チーム人数
begin_date date 開始日
end_date date 終了日(NULL=継続中)

Skill(dim_skill)

正規化済みのスキルマスタ。

カラム 説明
skill_id long スキル一意ID(Primary Key)
skill_name string 正規化された標準スキル名

WORKED_ON(fact_worked_on)

社員のプロジェクト参画履歴を表す関係。Member → Projectの方向。

カラム 説明
worked_on_id string レコード一意ID
engineer_id string 社員ID(Source)
project_id long プロジェクトID(Target)
role string プロジェクト内ロール
responsibilities string 担当業務記述
project_process_str string 担当工程
contribution_level string 貢献度
begin_date date 参画開始日
end_date date 離任日(NULL=継続中)

REQUIRES_SKILL(fact_required_skill)

プロジェクトが必要としたスキルを表す関係。Project → Skillの方向。

カラム 説明
required_skill_id string レコード一意ID
project_id long プロジェクトID(Source)
skill_id long スキルID(Target)

HAS_SKILL(fact_has_skill)

社員のスキル保有状況を表す派生関係。Member → Skillの方向。

カラム 説明
has_skill_id string レコード一意ID
engineer_id string 社員ID(Source)
skill_id long スキルID(Target)
month_of_experience double 関連プロジェクト在籍期間の合計月数
evidence_project_count long 根拠プロジェクト数
computed_at timestamp 集計実行日時

4.2 派生関係の活用:HAS_SKILLの事前集約

設計上もっとも工夫した点は、HAS_SKILL派生関係として事前集約する戦略です。

HAS_SKILL.month_of_experienceは、WORKED_ON × REQUIRES_SKILLの経路から「そのスキルを必要としたプロジェクトに在籍した期間の合計月数」として計算し、今回はこれをメンバーが持つスキルレベルの指数として定義しました。

fact_has_skill = (
    fact_worked_on
    .withColumn(
        "effective_end_date",
        F.coalesce(F.col("end_date"), F.current_date())
    )
    .withColumn(
        "months_worked",
        F.months_between(F.col("effective_end_date"), F.col("begin_date"))
    )
    .filter(F.col("begin_date").isNotNull() & (F.col("months_worked") >= 0))
    .join(
        fact_required_skill.select("project_id", "skill_id"),
        on="project_id",
        how="inner"
    )
    .groupBy("engineer_id", "skill_id")
    .agg(
        F.round(F.sum("months_worked"), 2).alias("month_of_experience"),
        F.countDistinct("project_id").alias("evidence_project_count")
    )
)

この事前集約戦略には2つの狙いがあります。ランキング性能の確保と、根拠提示能力の保持です。

ランキング時に毎回WORKED_ON × REQUIRES_SKILLの経路を集計するのは計算コストが高くなります。事前に集約してエッジ属性として保持することで、「Pythonの経験者Top10」のようなクエリは集約済みインデックスを参照するだけで完結します。一方で、根拠が必要なときには元のWORKED_ONに降りて具体的なプロジェクト名を取得できます。この 「集約済みエッジでランキング、生履歴で根拠提示」という2段階構造が、構造化検索と説明可能性を両立させる鍵となっています。

4.3 スキル抽出パイプラインの設計

fact_required_skillは、プロジェクト概要(dim_project.description)の自由記述からそのプロジェクトに必要なスキルを抽出する必要がありましたが、Fabric Notebookが提供するAI Functionsを使用することでLLMによるワード抽出を簡単に実装することができました。

from pyspark.sql import functions as F
project_skills = project_df.withColumn("skills", F.concat_ws("\n", F.col("architecture"), F.col("language"))).select("project_id", "skills")
from synapse.ml.spark import aifunc
project_skills_extract = project_skills.ai.extract(
    labels=[aifunc.ExtractLabel(
        label="extract_skills", 
        description="プロジェクト記述から、使用されている、または必要とされている技術スキルを抽出してください。バージョン情報は含めず、一般的な技術名で抽出すること。誤字と思われる部分は補完してください",
        type="string",
    )],
    input_col="description",
).withColumn("skill", F.explode(F.col("extract_skills")))

4.4 スキル正規化

IT領域のスキル名は表記揺れが多く、「k8s」「Kubernetes」「クバネティス」がすべて同じ概念を指すといった現象が日常的に発生します。これを吸収するため、以下のような対策を取りました。

  1. grepによる正規化処理
  2. AI FunctionsによるLLMベースでの名寄せ
  3. dim_skillにスキルに登録のない場合、新規スキル登録パイプラインの実行

5. Data Agentのinstruction設計

ナレッジグラフを構築しただけでは、自然言語での質問に対して安定した回答は得られません。Data Agentに与えるinstructionの設計が、エージェント全体の品質を決定づける要素となります。

5.1 instructionの全体構造

instructionは以下の11セクションで構成しました。

1. エージェントの役割
2. ナレッジグラフのスキーマ説明
3. クエリ戦略の選択ルール
4. スキル名の取り扱い(表記揺れ・略称展開)
5. 時系列検索のルール
6. ランキングロジック
7. 回答の構造
8. 提案マッチングの特別フロー
9. やってはいけないこと
10. クエリ例(Few-shot)
11. 補足

NL2GQL機能だけでは対応しきれない、業務固有の表記揺れや略称、時系列の解釈ルール、ランキングの選び方を明示的に指定することで、回答品質を安定化させています。

5.2 工夫1:3つのクエリ戦略の使い分け

instructionの中核は「3つのクエリ戦略の使い分け」です。ユーザーの質問内容に応じて、適切な経路を選択するようエージェントに明示的に指示しています。

戦略1:直接スキル検索HAS_SKILLの集約済み属性を使います。「Pythonの経験者Top10」のようなランキング型クエリに最速で応答します。

MATCH (m:Member)-[h:HAS_SKILL]->(s:Skill)
WHERE s.canonical_name = 'Python'
RETURN m.name, h.month_of_experience
ORDER BY h.month_of_experience DESC
LIMIT 10

戦略2:プロジェクト経由の経験検索WORKED_ON + REQUIRES_SKILLの経路を使います。「いつ」「どんなプロジェクトで」「どんな役割で」という時系列・文脈条件が問われる場合に使います。

MATCH (m:Member)-[w:WORKED_ON]->(p:Project)-[:REQUIRES_SKILL]->(s:Skill)
WHERE s.canonical_name = 'Python'
  AND w.end_date >= date('2023-12-01')
  AND w.role = 'PM'
RETURN m.name, p.name, w.role, w.begin_date, w.end_date
ORDER BY w.end_date DESC

戦略3:複合検索はランキングと根拠提示を両立させます。HAS_SKILLでTop-Nに絞ってから、根拠プロジェクトをWORKED_ONから収集する2段階構成です。

MATCH (m:Member)-[h1:HAS_SKILL]->(s1:Skill {canonical_name: 'Python'}),
      (m)-[h2:HAS_SKILL]->(s2:Skill {canonical_name: 'AWS'})
WITH m, h1.month_of_experience + h2.month_of_experience AS total_months
ORDER BY total_months DESC
LIMIT 5
MATCH (m)-[w:WORKED_ON]->(p:Project)-[:REQUIRES_SKILL]->(s:Skill)
WHERE s.canonical_name IN ['Python', 'AWS']
RETURN m.name, total_months,
       collect(DISTINCT {project: p.name, role: w.role}) AS evidence

エージェントに「質問の意図に応じてどの戦略を選ぶか」を判断させるため、各戦略に対応する典型的な質問例をFew-shotとして大量に提示しています。

5.3 工夫2:略称展開ルールの明示

IT業界の略称は文脈依存で、エージェントが学習データから推測すると不正確になります。そこで業務固有の略称展開ルールを明示的にinstructionに含めました。

k8s → Kubernetes
AWS → Amazon Web Services
ML → 機械学習 / Machine Learning
DL → 深層学習 / Deep Learning
LLM → 大規模言語モデル / Large Language Model
PM → プロジェクトマネジメント

これにより、「k8sの経験者」という入力に対しても、エージェントは内部でKubernetesに展開してから検索を実行します。逆方向の対応(「Kubernetesの経験者」と聞かれたとき「k8s」表記の案件も拾える)も、aliases列との組み合わせで自動的に成立します。

5.4 工夫3:「やってはいけないこと」の明示

エージェントの暴走を防ぐため、明示的な禁止事項をinstructionに含めることが効果的でした。

  • スキーマに定義されていない関係を推論で補わない
  • month_of_experienceを「習熟度」と言い換えない(在籍月数の合計であり、習熟度ではない)
  • 根拠なしの推薦をしない
  • 大量の候補を一度に返さない(デフォルト10件まで)

特に2つ目は重要です。「経験月数が長い = スキルが高い」と短絡的に解釈されるとミスマッチ推薦の原因になるため、エージェントには指標の定義を正確に伝える責務があります。指標の正確な定義をinstructionで宣言することで、エージェントの回答も指標の意味を踏まえたものになります。

5.5 工夫4:2つのエージェントの役割分離

第3章で説明した通り、Fabric側には2つのData Agentを配置しています。Knowledge Graph Agentはナレッジグラフを参照する構造化検索を担当し、Vector Search AgentはAzure AI Searchを参照する意味ベース検索を担当します。

この分離により、各エージェントのinstructionをそれぞれの強みに特化させることができました。SES Sales Agentのinstructionには上記のグラフクエリ戦略を詳細に記述し、General Search Agentのinstructionには類似案件の発見と要点抽出に特化したルールを記述しています。バックエンド側のMain Agentが、ユーザー質問の意図に応じて両者を使い分けます。


6. 期待される応答例

実装したエージェントが、典型的な質問にどのように応答するかをいくつかの例で示します。

6.1 シンプルなスキル検索

ユーザー:Pythonの経験が長い人をTop5で教えて

エージェント:Pythonの経験月数が長いメンバーTop5は以下の通りです。

順位 名前 経験月数 根拠プロジェクト数
1 山田太郎(E001) 64.5ヶ月 8件
2 佐藤花子(E045) 52.0ヶ月 6件
3 鈴木一郎(E012) 41.8ヶ月 5件
4 田中次郎(E089) 38.2ヶ月 4件
5 高橋三郎(E023) 32.5ヶ月 5件

経験月数は「Pythonを必要としたプロジェクトに在籍した期間の合計」を示しています。具体的にどのプロジェクトでPythonを使用したかの詳細を知りたい方がいれば、お知らせください。

6.2 複合条件での検索

ユーザー:直近2年で金融業界のプロジェクトを経験した、機械学習スキルがある人を探して

エージェント:直近2年(2023年12月以降)に金融業界プロジェクトに参画し、機械学習スキルを持つメンバーは3名見つかりました。

山田太郎さん(E001)

  • 機械学習経験月数:28.5ヶ月
  • 該当プロジェクト:「○○銀行 与信スコアリングモデル開発」(2024年1月〜2024年9月、リードエンジニア)

佐藤花子さん(E045)

  • 機械学習経験月数:18.0ヶ月
  • 該当プロジェクト:「△△証券 不正取引検知システム」(2024年3月〜2025年2月、データサイエンティスト)

鈴木一郎さん(E012)

  • 機械学習経験月数:15.2ヶ月
  • 該当プロジェクト:「××生命 顧客行動予測基盤」(2024年6月〜継続中、機械学習エンジニア)

候補をさらに絞りたい場合は、ロールや具体的な機械学習タスク(分類・回帰・NLPなど)でお絞りいただけます。

6.3 提案文からのマッチング

ユーザー:「リアルタイムでセンサーデータを処理する分析基盤を構築するプロジェクト。AWSとPythonを中心に、データパイプラインの設計と実装を行う。期間は6ヶ月、PM含めて5名体制」という案件にマッチする人を推薦して

エージェント:ご提案案件の要件を以下のように整理しました。

  • 必須スキル:AWS、Python、データパイプライン
  • 関連領域:リアルタイム処理、ストリーミング、センサーデータ
  • 期間:6ヶ月、5名体制(PM含む)

まず、必須スキルを満たすメンバーをランキングしたうえで、類似案件の経験者も含めて推薦します。

第一推薦:山田太郎さん(E001)
必須スキル合計経験:92ヶ月(AWS: 27.5ヶ月、Python: 64.5ヶ月)。過去に「IoTセンサーデータ収集基盤」案件をリードエンジニアとして担当した実績があり、本案件と技術構成・データ特性が類似しています。PMロール経験もあるため、本件のリードに適任です。

第二推薦:佐藤花子さん(E045)
必須スキル合計経験:68ヶ月。過去案件「リアルタイム広告配信プラットフォーム」でAWS Kinesisを用いたストリーミング処理を実装した経験があり、リアルタイム要件への適合度が高いと判断しました。

第三推薦:鈴木一郎さん(E012)
必須スキル合計経験:54ヶ月。データパイプライン構築経験が豊富で、特にApache AirflowとAWS Glueの組み合わせでの実装実績が複数あります。

5名体制とのことですので、追加候補として隣接スキル保有者を提示することも可能です。ご希望の場合はお知らせください。

6.4 候補不足時の代替案提示

ユーザー:Rustで分散システムを開発した経験のある人を探して

エージェント:Rust + 分散システムの両方の経験を持つメンバーを検索しましたが、該当者は1名のみでした。

田中次郎さん(E089):Rust経験18ヶ月、分散システム経験24ヶ月

候補が少ないため、隣接スキル保有者を代替案として提示します。

代替案1:Go + 分散システム経験者

  • 高橋三郎さん(E023):Go経験36ヶ月、分散システム経験42ヶ月
  • 中村四郎さん(E067):Go経験28ヶ月、分散システム経験30ヶ月

代替案2:Rust + バックエンド開発経験者(分散システム経験なし)

  • 伊藤五郎さん(E102):Rust経験24ヶ月、バックエンド開発65ヶ月

Rust必須の度合いや、分散システムの規模感によって最適な候補が変わります。ご要件の詳細をお聞かせいただければ、より精度の高い推薦が可能です。


7. 業務へ与える影響の試算

本エージェントを実運用に投入した場合、業務にどの程度の効果が見込めるかを仮定値ベースで試算します。

7.1 候補者検索作業の所要時間削減

現状、1案件あたりの候補者検索(情報収集、比較、絞り込み)にかかる時間は、平均して約1〜2時間と想定されます。エージェント導入後は、対話を通じた候補絞り込みと根拠確認を含めても約10〜15分で完了する見込みです。

観点 現状 導入後 削減率
1案件あたりの検索時間 1〜2時間(平均1.5時間) 10〜15分(平均12.5分) 約86%減
1人月あたりの処理可能案件数(1人日8時間・20営業日換算) 約107案件 約768案件 約7倍

仮に営業担当者が月20時間をアサイン業務に割いている場合、削減される時間は月あたり約17時間になります。営業担当者が10名いれば、組織全体で月約170時間の業務時間が他の活動に振り向けられる計算です。

7.2 候補発見の網羅性向上

現状、営業担当者が把握しているメンバーは経験的に全社員の20〜30%程度と仮定されます。エージェント導入後は、データ化されたメンバー全員が検索対象になるため、**実質的に100%**の網羅性が確保されます。

この網羅性向上は、最適候補の見落としリスクを下げるだけでなく、「隣のチームに最適な人材がいたのに気付けなかった」という機会損失を減らす効果があります。具体的な金額換算は困難ですが、本来アサインされるべき人材がアサインされることで、プロジェクト成功率の向上、顧客満足度の向上、メンバーのキャリア機会の最適化、といった複次的な効果が期待できます。

7.3 新人営業の立ち上がり期間短縮

現状、新人営業担当者が独り立ちするまでには6〜12ヶ月程度を要します。これは、社内メンバーの顔と名前と得意分野を覚え、過去案件の傾向を把握するのに時間がかかるためです。

エージェント導入後は、新人でもエージェントに質問することで、ベテランと同等の人材情報にアクセスできます。判断ロジックも回答に含まれる根拠から学習できるため、立ち上がり期間は2〜3ヶ月に短縮できると見込んでいます。属人化した暗黙知を形式知として共有できる効果が、組織のスケーラビリティに直結します。

7.4 リードタイム短縮による案件獲得力向上

案件受領から提案提出までのリードタイムが1〜2日から数時間に短縮されることで、競合に対するスピード優位性が生まれます。SES業界では「最速で良質な提案を出す」ことが案件獲得の決め手になることが多く、リードタイム短縮は直接的な売上向上要因になりえます。

仮に月10案件のうち、リードタイム差で受注確度が10%上がると仮定すると、月1件分の追加受注機会が見込まれます。1案件の平均規模を仮定すれば、年間で具体的な売上インパクトが試算できる構造です。

7.5 試算のまとめ

効果 定量効果 主な恩恵
検索時間削減 1案件あたり約86%減 営業担当者の生産性向上
候補網羅性 把握率20〜30% → 100% 機会損失の削減
新人立ち上がり 6〜12ヶ月 → 2〜3ヶ月 組織スケーラビリティ向上
提案リードタイム 1〜2日 → 数時間 案件獲得力強化

これらは「個別の業務改善」というより、営業組織全体のオペレーションモデルを変える可能性を秘めた効果だと捉えています。


8. 今後の展望

今後の社内への展開・運用に向けては以下の方向で機能拡張を進めていく予定です。

8.1 データソースの拡張

現時点ではエンジニアプロフィール、過去プロジェクト履歴、スキルマスタの3つを統合しています。今後は以下のデータソースを順次取り込み、より多角的な人材判断が可能なナレッジグラフへと発展させます。

  • 稼働状況管理データ:誰がいつまで稼働中か、いつ空きが出るかを統合し、「アサイン可能性」を加味した推薦を実現します

  • 資格・認定情報:AWS認定、PMP、各種ベンダー認定を取り込み、客観的な資格ベースでの絞り込みを可能にします

  • 単価情報:エンジニアの単価情報を追加し、プロジェクトベースの提案において、スキルだけどはなく、売り上げや利益といったコスト面での合理性を考慮したチーム体制の提案を可能にします

  • 評価・面談情報:本人の希望キャリアパスや得意領域に関する評価情報を統合し、本人の成長機会も考慮した推薦に進化させます

  • 組織情報:所属部署・チーム情報を追加し、組織横断での協業可能性を可視化します

8.2 スキル抽出ロジックの高度化

現状はLLMを中心とした方式でfact_required_skillを生成していますが、再現率を上げるために辞書マッチング方式を組み合わせた2段階方式に拡張します。辞書マッチング(高精度)とLLM抽出(高再現率)の和集合を取ることで、抽出漏れを減らしつつ、信頼度スコアを各レコードに付与する設計を検討中です。

また、month_of_experienceという単純指標を、役割重み時間減衰を考慮した加重スコアに発展させます。PMロールと開発者ロールでスキルへの接触深度が異なる点、10年前の経験と直近の経験で価値が異なる点を、ランキングロジックに反映していきます。

8.3 提案資料の自動生成

現状は候補者の推薦と理由生成までを担っていますが、エージェントが生成した推薦内容をベースに、提案資料(候補者プロフィール、推薦理由、過去実績まとめ)を自動生成する機能を追加します。Word/PowerPoint形式での出力により、営業担当者の最終アウトプット作業まで支援する構成を目指します。

8.4 フィードバックループの構築

エージェントの推薦結果と、最終的にアサインされた人材を突合することで、推薦精度を継続的に改善するフィードバックループを構築します。「推薦上位に挙がったが最終的にアサインされなかった候補者」「推薦されなかったが実際にアサインされた候補者」を分析することで、ランキングロジックや略称展開ルールの改善に役立てます。

8.5 マルチエージェント化と業務統合

将来的には、アサイン支援エージェントを起点として、関連する業務エージェント群との連携を進めます。

  • 提案書作成支援エージェント
  • 顧客情報分析エージェント
  • プロジェクト進捗管理エージェント

これらをFabric Data AgentやSemantic Kernelで連携させることで、SES営業業務全体をAIエージェントが支援する基盤へと発展させていく構想です。


9. 使用したMicrosoft技術一覧

本検証で使用したMicrosoft関連技術を以下にまとめます。

9.1 データ・知識基盤

技術 用途
Microsoft Fabric 統合データプラットフォーム(ベース)
Fabric OneLake データレイクストレージ
Fabric Lakehouse テーブル形式データの管理レイヤー
Fabric Data Pipeline ETLパイプライン構築
Fabric Notebook(PySpark) スキル抽出・集約パイプライン実装
Fabric IQ Ontology(プレビュー) エンティティ・関係の定義レイヤー
Fabric IQ Graph(プレビュー) ナレッジグラフの構築・クエリ実行
Fabric Data Agent 自然言語インターフェース、NL2GQL

9.2 AI・検索基盤

技術 用途
Azure OpenAI Service LLM推論(Chat Completion)
Azure AI Search ベクトル検索・全文検索インデックス
Azure OpenAI Embeddings プロジェクト概要のベクトル化

9.3 アプリケーション基盤

技術 用途
Azure Container Apps バックエンドアプリケーションのホスティング
Azure AD(Entra ID) 認証基盤
Managed Identity アプリケーションからAzureリソースへの認証
DefaultAzureCredential クレデンシャル取得の統合インターフェース

9.4 監視・運用

技術 用途
Azure Monitor 監視基盤(ベース)
Application Insights ログ・メトリクス・分散トレース

おわりに

今回の取り組みでは、SES営業のアサイン業務における属人化と非効率という課題に対し、Microsoft Fabric IQによるナレッジグラフとAzure AI Searchによるベクトル検索を組み合わせ、AIエージェントとして利用可能なシステムを構築しました。

自然言語によるスキル検索、複合条件での候補抽出、根拠付きの推薦、代替案提示といった、人材アサインに必要な基本機能が実用レベルで動作することを確認できました。何より、判断プロセスがブラックボックスにならず、必ず根拠プロジェクトと指標が伴う応答を返せることが、業務適用において大きな価値になると実感しています。

今後はデータソースの拡充とエージェント機能の高度化を進めながら、SES営業の業務改革に貢献していけることを目指して開発を継続していきます。本記事が、同様の課題を抱える組織やナレッジグラフ × AIエージェントの実装を検討されている方々の参考になれば幸いです。

デモ動画

https://youtu.be/9gPp3vQoO6M

ヘッドウォータース

Discussion