我们的 AI 招聘平台如何在无需代码更改的情况下变得更智能
Source: Dev.to
介绍
上个月,我们的 AI 招聘平台只能处理 PDF 简历。
本周,它可以处理 PDF、Word 文档以及带 OCR 的扫描图像。
我们没有更改简历处理代理的任何代码。我们只是将新的提取器部署到集群——LLM 驱动的代理自动开始使用它们。
这就是在 MCP Mesh 上构建的感受。
平台
我们在 Kubernetes 上构建了一个多代理招聘平台:
┌─────────────────────────────────────────────────────────────────────────┐
│ MCP Mesh Registry │
│ (Discovery + Topology + Health) │
└─────────────────────────────────────────────────────────────────────────┘
▲ ▲ ▲ ▲ ▲
│ │ │ │ │
┌────┴────┐ ┌─────┴─────┐ ┌──────┴──────┐ ┌────┴────┐ ┌─────┴─────┐
│ Resume │ │ Job │ │ Interview │ │ Scoring │ │ LLM │
│ Agent │ │ Matcher │ │ Agent │ │ Agent │ │ Providers │
│ (LLM) │ │ │ │ (LLM) │ │ (LLM) │ │ │
└────┬────┘ └───────────┘ └─────────────┘ └─────────┘ └───────────┘
│
│ dynamically discovers extractors
▼
┌───────────────────────────────────────────────────────────────────┐
│ Extractor Tools │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ PDF │ │ DOC │ │ Image │ │ Future │ │
│ │Extractor│ │Extractor│ │ (OCR) │ │ ... │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ tags: [extractor, pdf] [extractor, doc] [extractor, ocr] │
└───────────────────────────────────────────────────────────────────┘
关键洞察: 由 @mesh.llm 提供动力的代理没有硬编码的依赖关系。它们在运行时发现工具,并智能地选择使用哪些工具。
简历代理
以下是我们简历处理逻辑的核心:
@mesh.llm(
provider={"capability": "llm", "tags": ["+claude"]},
filter=[{"tags": ["extractor"]}], # Discover all extractors
system_prompt="""You process uploaded resumes.
Available tools let you extract text from different file formats.
Choose the appropriate extractor based on the file type.
Then analyze the extracted text and return structured candidate data.""",
max_iterations=3,
)
@mesh.tool(
capability="process_resume",
tags=["resume", "ai"],
)
async def process_resume(
file_path: str,
file_type: str,
llm: MeshLlmAgent = None
) -> CandidateProfile:
return await llm(f"Process this {file_type} resume: {file_path}")
魔法就在 filter=[{"tags": ["extractor"]}] 中。LLM 会看到所有标记为 extractor 的工具,并根据文件类型决定调用哪个。
第一天:仅 PDF
When we launched, we had a single extractor:
# pdf_extractor.py
@mesh.tool(
capability="extract_pdf",
tags=["extractor", "pdf"],
description="Extract text content from PDF files"
)
async def extract_pdf(file_path: str) -> ExtractedText:
# PDF extraction logic
return ExtractedText(content=text, metadata={...})
The Resume Agent’s LLM sees: Available tools: [extract_pdf]
User uploads resume.pdf → LLM reasons: “This is a PDF, I’ll use extract_pdf” → extracts text → returns a structured profile.
第 30 天:添加 Word 支持
产品方要求支持 Word 文档,于是我们新增了一个提取器:
# doc_extractor.py
@mesh.tool(
capability="extract_doc",
tags=["extractor", "doc", "docx"],
description="Extract text content from Word documents (.doc, .docx)"
)
async def extract_doc(file_path: str) -> ExtractedText:
# Word extraction logic
return ExtractedText(content=text, metadata={...})
部署到 Kubernetes:
helm install doc-extractor oci://ghcr.io/dhyansraj/mcp-mesh/mcp-mesh-agent \
--version 0.7.12 \
-n mcp-mesh \
-f doc-extractor/helm-values.yaml
在 10 秒内,简历代理的 LLM 能看到:Available tools: [extract_pdf, extract_doc]
用户上传 resume.docx → LLM 推理:“这是一个 Word 文档,我将使用 extract_doc” → 正常工作。
无需对简历代理的代码进行任何更改。无需重启。无需更新配置。
第 60 天:扫描简历的图像 OCR
HR 报告说,候选人有时会上传扫描的 PDF 或照片。我们添加了一个 OCR 提取器:
# image_extractor.py
@mesh.tool(
capability="extract_image_ocr",
tags=["extractor", "image", "ocr", "scan"],
description="Extract text from images or scanned documents using OCR"
)
async def extract_image_ocr(file_path: str) -> ExtractedText:
# OCR logic (Tesseract, Cloud Vision, etc.)
return ExtractedText(content=text, confidence=0.92, metadata={...})
部署:
helm install image-extractor oci://ghcr.io/dhyansraj/mcp-mesh/mcp-mesh-agent \
--version 0.7.12 \
-n mcp-mesh \
-f image-extractor/helm-values.yaml
现在简历代理的 LLM 能看到:Available tools: [extract_pdf, extract_doc, extract_image_ocr]
用户上传 resume_scan.jpg → LLM 推理:“这是图像,我将使用 extract_image_ocr” → 正常工作。
处理扫描的 PDF
当用户上传的 PDF 实际上是扫描的图像(没有可选文本)时,LLM:
- 尝试
extract_pdf→ 获得空的或乱码的文本。 - 识别出失败并回退到
extract_image_ocr。 - 通过 OCR 成功提取文本并继续进行候选人分析。
要点
通过 tag‑driven discovery 和 runtime tool selection,我们的平台可以瞬间演进其功能——无需触及核心代理代码。这就是基于 MCP Mesh 构建的力量。
Source: …
代理变得更聪明
它在没有任何人编写相应逻辑的情况下学会了一种新的恢复策略。
我们没有告诉简历代理(Resume Agent)关于 OCR 的事。我们也没有更新它的提示。
我们只部署了一个带有良好标签和清晰描述的提取器——LLM 自动判断何时使用它。
为什么有效
传统的微服务需要显式的接线:
# 传统方式 – 硬编码路由
def process_resume(file_path: str, file_type: str):
if file_type == "pdf":
text = call_pdf_service(file_path)
elif file_type in ["doc", "docx"]:
text = call_doc_service(file_path)
elif file_type in ["jpg", "png"]:
text = call_ocr_service(file_path)
else:
raise UnsupportedFormatError(file_type)
# …
每新增一种格式都需要改代码、重新部署并进行测试。
MCP Mesh 使用 @mesh.llm 颠倒了这一过程:
| 功能 | 描述 |
|---|---|
| 工具自我描述 | 每个提取器都有标签和描述 |
| LLM 发现工具 | filter=[{"tags": ["extractor"]}] 广播意图 |
| LLM 推理工具 | 根据上下文选择,而不是硬编码规则 |
| Mesh 处理路由 | 工具调用会自动路由到正确的代理 |
简历代理的代码保持不变。平台的能力随着每一次 Helm 安装而扩展。
企业现实
| 方面 | 传统方式 | MCP Mesh |
|---|---|---|
| 添加新文件格式 | 代码改动 + 部署 + 测试 | helm install |
| 路由配置文件 | 按服务划分 | 0 |
| 边缘情况的恢复逻辑 | 手动 if/else | LLM 自动处理 |
| 添加能力所需时间 | 小时/天 | 几分钟 |
基础设施
# 一次性集群搭建
helm install mcp-core oci://ghcr.io/dhyansraj/mcp-mesh/mcp-mesh-core \
--version 0.7.12 \
-n mcp-mesh --create-namespace
# 部署:Registry + PostgreSQL + Redis + Tempo + Grafana
相同的代理代码可以本地运行(meshctl start)、在 Docker Compose 中运行,也可以在 Kubernetes 中运行——只需更换基础设施。
LLM 所看到的内容
当简历代理的 LLM 运行时,它会收到如下工具列表:
{
"tools": [
{
"name": "extract_pdf",
"description": "Extract text content from PDF files",
"tags": ["extractor", "pdf"],
"input_schema": {"file_path": "string"}
},
{
"name": "extract_doc",
"description": "Extract text content from Word documents (.doc, .docx)",
"tags": ["extractor", "doc", "docx"],
"input_schema": {"file_path": "string"}
},
{
"name": "extract_image_ocr",
"description": "Extract text from images or scanned documents using OCR",
"tags": ["extractor", "image", "ocr", "scan"],
"input_schema": {"file_path": "string"}
}
]
}
LLM 读取描述,理解各自的能力,并做出智能选择。新增工具?它会在几秒钟内出现在此列表中。
LLM 故障转移(附加)
我们运行两个 LLM 提供商:
helm install claude-provider oci://ghcr.io/dhyansraj/mcp-mesh/mcp-mesh-agent \
-f claude-provider/helm-values.yaml -n mcp-mesh
helm install openai-provider oci://ghcr.io/dhyansraj/mcp-mesh/mcp-mesh-agent \
-f openai-provider/helm-values.yaml -n mcp-mesh
简历代理的 provider={"capability": "llm", "tags": ["+claude"]} 偏好 Claude。
当 Claude 的 API 宕机时:
- Mesh 检测到不健康(心跳丢失)
- 拓扑更新
- 下一次请求路由到 OpenAI
- Claude 恢复后,流量重新回归
零代码实现故障转移——这就是 Mesh 的工作方式。
接下来
本文展示了我们构建的 什么——一个随着能力添加而真正变得更聪明的 AI 平台。
下一篇文章将解释 为什么 我们选择 MCP 而不是 REST 作为基础,以及这一选择为何比你想象的更重要。
👉 [下一篇:MCP vs REST — 为什么 MCP 是更好的微服务协议]
资源
Source: …
yansraj/mcp-mesh)**