Courses
Kimi K2.6 是 Moonshot AI 最新的开源模型,专为编码、长程任务执行、工具使用和代理工作流设计。该模型可通过 Kimi.com、Kimi 应用、Kimi Code 和 API 使用,适合构建需要推理、工具调用和结构化输出的实用型 AI 应用。
在本教程中,您将构建JobFit AI,一款由 AI 驱动的求职助理。它会读取候选人的简历,搜索在招职位,查看选定的职位页面,并生成按匹配度排序的报告。Kimi K2.6 很适合该项目,因为它通过 Kimi API 平台支持长上下文工作流、工具调用,以及思考与非思考两种模式。
本项目将使用:
- Kimi K2.6 作为推理模型
- Olostep 用于实时网页搜索与职位页面抓取
- pypdf 从候选人简历中提取文本
- OpenAI Agents SDK 构建可调用工具的代理
- Gradio 将工作流封装为简单的 Web 应用
完成本教程后,您将拥有一个可用的应用:用户上传简历、描述求职偏好,便可在一分钟内生成相关职位的排序报告。
如果您刚开始接触代理式 AI,强烈推荐参加我们的 AI Agents Fundamentals 技能路径。课程涵盖设计模式基础、MCP 和多代理系统。
教程准备
开始前,请确保您具备:
- Python 3.11+
- 一个 Kimi API 密钥
- Moonshot AI 账户中至少$5 余额
- 一个 Olostep API 密钥
- 一份 PDF 简历
- 基础 Python 知识
1. 设置 Python 环境
创建新项目文件夹:
mkdir JobFit-AI
cd JobFit-AI
然后安装所需依赖:
pip install gradio openai pypdf openai-agents
主要依赖包括:
-
gradio:创建 Web 界面 -
openai:连接到兼容 OpenAI 的 API -
pypdf:从 PDF 文件中提取文本 -
openai-agents:创建可调用工具的 AI 代理
接着,创建账户并生成 API 密钥:
- 创建免费的 Olostep 账户,并在 Olostep 仪表板生成 API 密钥。您也可订阅每月 $9 的 Starter 套餐,包含5,000 次请求,足以完成测试与部署。
- 前往 Kimi 平台,充值至少$5,并生成 API 密钥。
将 Kimi 与 Olostep 的 API 密钥设置为环境变量。MOONSHOT_API_KEY 用于访问 Kimi K2.6 API,而 OLOSTEP_API_KEY 用于搜索和抓取在线职位页面。
2. 定义项目配置
启动 Jupyter Notebook,新建一个单元格,加入所需的导入与项目配置。
import json
import os
import requests
from agents import Agent, AsyncOpenAI, ModelSettings, OpenAIChatCompletionsModel, RunConfig, Runner, function_tool, set_tracing_disabled
from IPython.display import Markdown, display
from pypdf import PdfReader
现在定义模型名称、API 端点、代理最大轮数、简历路径和求职偏好。
KIMI_MODEL = "kimi-k2.6"
KIMI_BASE_URL = "https://api.moonshot.ai/v1"
OLOSTEP_SEARCH_URL = "https://api.olostep.com/v1/searches"
OLOSTEP_SCRAPE_URL = "https://api.olostep.com/v1/scrapes"
MAX_AGENT_TURNS = 25
cv_path = "abid-resume.pdf"
preferences = """
Remote data science, AI writer, or technical writer roles in AI, machine learning, data science, or cloud.
Prefer technical content, tutorials, developer education, research writing, and AI product storytelling.
""".strip()
set_tracing_disabled(True)
KIMI_MODEL 和 KIMI_BASE_URL 告诉应用通过 Moonshot AI 的兼容 OpenAI 的 API 端点使用 Kimi K2.6。Olostep 的 URL 则用于实时职位搜索和页面抓取。
变量 cv_path 指向候选人的简历 PDF。请确保 PDF 保存在同一项目文件夹中;若位于其他位置,请更新路径。
变量 preferences 告诉代理要搜索的职位类型。您可根据目标岗位、行业、地点、级别或偏好的工作方式进行更新。
我们通过 set_tracing_disabled(True) 禁用 tracing,因为 tracing 是 OpenAI Agents SDK 默认启用的功能。由于本项目通过兼容 OpenAI 的端点使用 Kimi,禁用 tracing 可简化本地设置,并避免与第三方模型提供商相关的 tracing 问题。
3. 连接 Kimi K2.6 API
然后,使用先前保存为环境变量的 API 密钥来设置 Kimi 客户端。
kimi_client = AsyncOpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url=KIMI_BASE_URL,
)
这将创建 Kimi 的 API 客户端。api_key 从 MOONSHOT_API_KEY 加载,base_url 指向 Moonshot AI 的兼容 OpenAI 的端点。
接着,封装 Kimi 模型,使其可用于 OpenAI Agents SDK:
kimi_model = OpenAIChatCompletionsModel(
model=KIMI_MODEL,
openai_client=kimi_client,
)
现在定义模型设置:
model_settings = ModelSettings(
tool_choice="auto",
parallel_tool_calls=True,
extra_body={"thinking": {"type": "disabled"}},
)
tool_choice="auto" 允许代理自行决定何时调用工具。parallel_tool_calls=True 允许在需要时并行调用多个工具。
我们通过 extra_body={"thinking": {"type": "disabled"}} 禁用 Kimi 的思考模式,以保持输出更简洁,适合结构化的职位匹配报告。
最后,创建运行配置:
run_config = RunConfig(
workflow_name="JobFit AI Kimi Search",
tracing_disabled=True,
)
workflow_name 为此次运行提供清晰的标签。同时在此保持禁用 tracing,因为本项目通过兼容 OpenAI 的端点使用 Kimi,而非 OpenAI 的 tracing 后端。
4. 提取候选人简历文本
接下来使用 PdfReader 加载候选人简历,并提取各页文本。
reader = PdfReader(cv_path)
cv_text = "\n".join(page.extract_text() or "" for page in reader.pages)[:12000]
print(f"Loaded {len(cv_text):,} characters from {cv_path}")
这段代码读取 cv_path 指定的 PDF 文件,提取每一页的文本并合并为一个字符串。
[:12000] 的限制可使简历文本足够短,以便舒适地放入代理提示中,同时仍为模型提供关于候选人经历、技能和偏好的充分上下文。
输出类似如下,取决于您的简历名称和长度:
Loaded 2,946 characters from abid-resume.pdf
这确认了简历加载成功,并显示了从 PDF 提取的字符数。
5. 编写代理指令
接下来,定义指令以控制代理如何搜索、使用工具,以及如何格式化最终报告。
AGENT_INSTRUCTIONS = """
You are JobFit AI, a focused job-search agent.
Tool plan:
- Call search_jobs exactly once with limit 8.
- Read at most 3 direct job pages with read_job_page.
- After reading up to 3 pages, stop using tools and write the report.
- Search again only if the first search returns zero usable jobs.
- Avoid broad search pages, expired jobs, and LinkedIn unless no better source exists.
Report rules:
- Keep the report simple, clear, and practical.
- Use short bullets.
- Do not use em dashes.
- Do not use contractions.
- Do not add text before or after the report.
- End after the final Job Notes entry.
- Include at least 5 ranked jobs if the search results contain at least 5 usable jobs.
- If only 3 pages were scraped, use backup jobs from search results when they look usable.
- Every job must include a clickable Markdown link.
- Every job must have one apply decision: Apply, Maybe, or Do not apply.
Use exactly this Markdown structure:
# JobFit AI Report
## Best Match
- **Role:** <job title>
- **Company:** <company>
- **Apply decision:** Apply / Maybe / Do not apply
- **Fit score:** <score>/100
- **Link:** [Apply here](<job url>)
**Why this is the best match:**
- <specific reason>
- <specific reason>
- <specific reason>
## Ranked Jobs
| Rank | Role | Company | Apply? | Fit | Link |
| --- | --- | --- | --- | --- | --- |
| 1 | <role> | <company> | Apply / Maybe / Do not apply | <score>/100 | [Apply here](<url>) |
## Job Notes
### 1. <Role> at <Company>
- **Apply decision:** Apply / Maybe / Do not apply
- **Fit score:** <score>/100
- **Link:** [Apply here](<job url>)
**Why it fits:**
- <bullet>
- <bullet>
**Concerns:**
- <bullet>
- <bullet>
**Application angle:**
- <how the person should position their CV/application>
""".strip()
这些指令使代理保持聚焦。它将流程限制为一次职位搜索、最多三次职位页面读取,并采用固定的 Markdown 报告结构。
报告规则还通过要求短要点、可点击链接、匹配度评分以及每个职位的清晰投递决策,使输出更易于浏览。
6. 构建运行时提示
定义好代理指令后,创建在每次运行时传递给代理的提示模板。
RUN_PROMPT_TEMPLATE = """
Find current job postings for this candidate and rank them by fit.
Keep the run simple:
- one search
- up to three page reads
- final report
The final report must follow AGENT_INSTRUCTIONS exactly.
Use simple wording. Do not use em dashes. Do not use contractions.
Candidate CV:
{cv_text}
Preferences:
{preferences}
""".strip()
此提示会在运行时组合候选人的简历文本与求职偏好。
cv_text 占位符填入提取的简历内容,preferences 占位符填入之前定义的目标岗位偏好。二者结合为代理提供足够的上下文,以搜索相关职位并按匹配度排序。
7. 使用 Olostep 添加实时网页搜索
在准备好代理指令和运行时提示后,添加两个工具,让代理使用 Olostep 搜索网页并读取职位页面。
第一个工具用于搜索职位列表,并返回精简的结果列表。
@function_tool
def search_jobs(query: str, limit: int = 8) -> str:
"""Search the web for job listings and return compact JSON results."""
response = requests.post(
OLOSTEP_SEARCH_URL,
headers={"Authorization": f"Bearer {os.environ['OLOSTEP_API_KEY']}", "Content-Type": "application/json"},
json={"query": query},
timeout=60,
)
response.raise_for_status()
links = response.json().get("result", {}).get("links", [])[:limit]
results = [
{"title": item.get("title", "Untitled"), "url": item.get("url"), "description": item.get("description", "")}
for item in links
if isinstance(item, dict) and item.get("url")
]
return json.dumps(results, ensure_ascii=False)
@function_tool 装饰器使该 Python 函数作为可调用工具提供给代理。
当代理需要职位列表时,会以搜索查询调用 search_jobs。该函数将查询发送至 Olostep 搜索端点,收集顶部结果,并以 JSON 返回。
每条结果包含:
- 职位名称
- 职位链接
- 简短描述
第二个工具允许代理打开并读取指定的职位页面。
@function_tool
def read_job_page(url: str) -> str:
"""Scrape one job listing URL and return markdown text."""
response = requests.post(
OLOSTEP_SCRAPE_URL,
headers={"Authorization": f"Bearer {os.environ['OLOSTEP_API_KEY']}", "Content-Type": "application/json"},
json={"url_to_scrape": url, "formats": ["markdown"]},
timeout=120,
)
response.raise_for_status()
markdown = response.json().get("result", {}).get("markdown_content") or ""
return markdown[:8000]
此函数将职位 URL 发送至 Olostep 抓取端点,并以 Markdown 格式返回页面内容。
[:8000] 的限制使抓取的页面内容足够短,便于代理处理,同时仍能涵盖最有用的职位信息,如职责、要求与公司简介。
8. 创建 JobFit AI 代理
现在创建代理,并连接先前定义的各个组件:Kimi 模型、模型设置、Olostep 工具以及代理指令。
agent = Agent(
name="JobFit AI",
model=kimi_model,
model_settings=model_settings,
tools=[search_jobs, read_job_page],
instructions=AGENT_INSTRUCTIONS,
)
Agent 对象是此工作流的主控制器。
它使用:
kimi_model作为推理模型model_settings控制工具使用与输出行为search_jobs搜索实时职位列表read_job_page抓取选定职位页面AGENT_INSTRUCTIONS遵循精确的搜索与报告规则
至此,代理已准备好搜索职位、对照候选人简历进行比较,并生成结构化的 JobFit AI 报告。
9. 运行代理工作流
现在使用提取的简历文本与之前定义的求职偏好来运行 JobFit AI 代理。
首先,格式化运行时提示:
prompt = RUN_PROMPT_TEMPLATE.format(cv_text=cv_text, preferences=preferences)
这会将候选人的简历与目标职位偏好填入提示模板。
接着,启动流式代理运行:
print("Starting agent run")
result = Runner.run_streamed(
agent,
prompt,
max_turns=MAX_AGENT_TURNS,
run_config=run_config,
)
Runner.run_streamed() 方法会启动代理工作流,并在事件发生时流式输出。这有助于观察代理何时调用工具、接收工具输出以及创建最终消息。
现在添加流式循环:
async for event in result.stream_events():
if event.type == "agent_updated_stream_event":
print(f"Agent: {event.new_agent.name}")
elif event.type == "run_item_stream_event":
item = event.item
if event.name == "tool_called":
raw = item.raw_item
tool_name = raw.get("name") if isinstance(raw, dict) else getattr(raw, "name", "tool")
arguments = raw.get("arguments") if isinstance(raw, dict) else getattr(raw, "arguments", "")
arguments = str(arguments).replace(chr(10), " ")[:500]
print(f"Tool call: {tool_name}")
if arguments:
print(f"Parameters: {arguments}")
elif event.name == "tool_output":
print(f"Tool output: {len(str(item.output)):,} chars")
elif event.name == "message_output_created":
print("Final message ready")
该循环会在代理运行时打印有用的进度更新。例如,显示代理何时搜索职位、读取职位页面或完成报告生成。
最后,将最终输出保存到名为 report 的变量:
report = result.final_output
globals()["report"] = report
print("Run complete")
print(f"Model responses: {len(result.raw_responses)}")
print(f"Run items: {len(result.new_items)}")
print(f"Final output: {len(str(report)):,} chars")
report 变量存储最终的 JobFit AI 报告,您可以展示、保存,或在 Gradio 应用中使用。
输出大致如下:
Starting agent run
Agent: JobFit AI
Tool call: search_jobs
Parameters: {"query":"remote data science writer technical writer AI machine learning content editor","limit":8}
Tool output: 2,445 chars
Tool call: read_job_page
Parameters: {"url":"https://www.indeed.com/q-data-science-writer-jobs.html"}
Tool output: 8,000 chars
Tool call: read_job_page
Parameters: {"url":"https://www.builtinnyc.com/jobs/remote/data-analytics/data-science"}
Tool output: 8,000 chars
Tool call: read_job_page
Parameters: {"url":"https://www.virtualvocations.com/jobs/q-data+scientist+remote+jobs/c-writing/d-336"}
Tool output: 5,075 chars
Final message ready
Run complete
Model responses: 5
Run items: 13
Final output: 5,931 chars
该输出表明代理已完成职位搜索、读取选定页面,并成功生成最终报告。
10. 展示生成的 JobFit 报告
代理运行完成后,以 Markdown 格式展示最终报告。
display(Markdown(report))
这会在笔记本中直接渲染生成的 JobFit AI 报告,比纯文本更易阅读。
报告包含最佳匹配职位、排序职位、匹配度评分、投递决策、顾虑点和申请策略。

11. 将工作流封装为 Gradio Web 应用
在笔记本中测试工作流后,您可以将其封装为简易的 Gradio Web 应用。创建一个 app.py 文件,然后从 GitHub 项目中的 JobFit-AI/app.py 文件复制代码,粘贴到本地文件。
运行应用:
python app.py

然后在浏览器中打开本地 URL(此示例为 http://127.0.0.1:7860/):

该 Gradio 应用提供了一个用于生成职位匹配报告的简洁界面,包括:
- 简历 PDF 上传区,用户可上传自己的简历。
- 职位偏好文本框,用户可描述目标职位类型、行业、地点、级别与偏好话题。
- “生成 JobFit 报告”按钮,启动代理工作流。
- 隐藏的进度日志区域,在运行期间显示应用正在执行的操作,如读取简历、调用工具与接收工具输出。
- 最终的 Markdown 报告区域,在代理完成后显示排序的职位匹配报告。
在后台,应用会读取上传的简历、提取文本,将简历与偏好发送给 JobFit AI 代理,并通过 Olostep 搜索在线职位。它会读取至多三份职位页面,并返回包含排序职位、匹配度评分、投递决策、顾虑点和申请策略的结构化 Markdown 报告。
12. 上传简历并生成报告
现在通过上传一份简历或 PDF,并点击“生成 JobFit 报告”来测试该 Web 应用。
本示例中,我上传了一份约三年经验的简历,以检验应用能否根据候选人的画像与偏好找到相关职位。报告在一分钟内生成。
在应用运行期间,进度日志会显示工作流的每个步骤,包括:
- 读取简历
- 从每页提取文本
- 启动代理运行
- 调用职位搜索工具
- 返回工具输出

运行完成后,应用会以 Markdown 格式显示最终报告。
报告以最佳匹配开始,其后是排序职位表。随后为每个职位提供更详细的备注,包括匹配度评分、投递决策、匹配原因、可能的顾虑以及申请策略。

在此示例中,排名第一的是 NannyML 的高级数据科学写作者岗位。鉴于其与候选人在数据科学、技术写作与 AI 内容方面的背景相匹配,看起来非常合适。
您可以点击报告中的“Apply here”链接打开职位页面,在决定是否投递前查看完整职位信息。

注意:如果您在本地运行项目时遇到问题,请查看 GitHub 仓库:kingabzpro/JobFit-AI。仓库包含笔记本、app.py 文件和安装依赖及本地运行的说明。
结语
JobFit AI 使用 Kimi K2.6、Olostep 和 OpenAI Agent SDK,帮助正在转岗或积极求职的人解决两个常见问题。
第一个问题是弄清该投哪里。职位网站、平台和公司招聘页很多,但并不总是清楚哪些岗位值得投入时间。该应用基于候选人的简历与偏好,帮助缩小范围,找到与其经历更相关的职位。
第二个问题是职位信息过载的筛选。代理会搜索实时职位、读取选定职位页面,并生成结构化报告:最佳匹配、排序职位、匹配度、顾虑点和申请策略,帮助您聚焦真正值得投递的岗位。
Kimi K2.6 API 在此代理式工作流中的表现也很出色。它速度快、稳定,并能有效遵循结构化指令。测试中,当代理允许最多 25 轮时,会更深入地搜索并抓取多个页面,但运行耗时约五分钟。为平衡质量与速度,我将流程限制为一次搜索与至多三次页面读取,使报告能在一分钟内生成。
您可以通过增加允许的步骤数、搜索结果数或页面读取数来提升报告质量。例如,将代理上限提高到 30 轮并允许读取更多职位页面,可生成更深入的报告,包含更多岗位与更有力的建议。不过,这也会增加运行时长与 API 用量。
如果您有兴趣构建类似的代理式工具,欢迎查看我们的其他 API 教程:
Kimi K2.6 常见问题
Kimi K2.6 是什么?
Kimi K2.6 是 Moonshot AI 于 2026 年 4 月发布的最新开权重代理式模型。其基于专家混合(MoE)架构,拥有约 1 万亿总参数,每次前向激活 320 亿参数,并针对编码、工具使用和长程代理任务进行了优化。
Kimi K2.6 的上下文窗口多大?
Kimi K2.6 支持 262,144 个 token(256K)上下文窗口。非常适合在单次会话中处理完整代码库、长文档或多步骤代理运行。
通过 API 使用 Kimi K2.6 的费用是多少?
通过 Kimi API 直接调用时,输入 token 价格为 $0.95/百万(未命中缓存)与 $0.16/百万(命中缓存),输出为 $4.00/百万 token。部分第三方提供更低价格,输入约 $0.60/百万,输出约 $2.80/百万起。
Kimi K2.6 是否支持思考模式?
是的,Kimi K2.6 支持思考模式(扩展推理)与即时模式(更快的非思考响应)。在本教程中,通过 extra_body={"thinking": {"type": "disabled"}} 明确禁用思考模式,以保持输出更简洁、更快速。
Kimi K2.6 在代理式编码基准中的表现如何?
Kimi K2.6 在 SWE-Bench Verified 上得分 80.2,成为该层级最强的开源模型,表现仅次于闭源模型 Claude Opus 4.6(80.8%)与 Gemini 3.1 Pro(80.6%)。在 BrowseComp 上得分 83.2,启用 Agent Swarm 模式后提升至 86.3,位列 GPT-5.5 Pro(90.1)与未发布的 Claude Mythos Preview(86.9)之后。