基于Kimi Work构建300并发AI Agent系统,实现就业市场智能侦察
1. 项目缘起:一个志愿填报引发的“技术执念”
每年高考季,最让考生和家长头疼的,除了分数,就是填志愿。选什么学校?挑什么专业?毕业了能去哪工作?这些问题像一团乱麻,理不清,剪不断。传统的做法是翻看厚厚的报考指南,或者上网搜索各种“热门专业排行榜”、“XX大学就业率”,但这些信息要么是宏观的、滞后的,要么就是零散的、带有营销性质的。我们很难从一个具体的专业,比如“软件工程”,直接看到这个专业毕业五年后的学长学姐们,真实地分布在哪些公司、哪些城市、拿着什么样的薪资。
我自己当年填志愿就吃过信息不对称的亏,所以今年家里有亲戚孩子高考,找我参谋时,我就想,能不能用点技术手段,把这件事做得更“实”一点?我不想再空谈“这个专业前景好”,我想看到数据:这个专业对应的岗位,在真实的招聘市场上,需求有多大?头部公司是哪些?这些公司的业务状况、融资情况、甚至工作氛围怎么样?这些信息,散落在招聘网站、企业信息查询平台(如天眼查)、股票软件(如同花顺)里,但手动去一个个查,无异于大海捞针。
于是,一个想法冒了出来:能不能写一个程序,自动去这些地方抓取、分析信息,然后生成一份针对某个具体专业的“就业市场扫描报告”?这个程序要足够智能,能理解我的查询意图,能自动规划查询路径,能并行处理海量请求。这不就是当下热门的AI Agent(智能体)吗?一个能自主完成复杂任务的智能程序。而我需要的,是让几百个这样的Agent同时出动,去“侦察”就业市场。最终,我利用Kimi Work这个平台,结合一些公开数据接口,真的搞出了一个能调动近300个并行Agent的查询系统。我把它称为一个Skill——一个能解决特定复杂问题的自动化技能。
这个过程,与其说是在帮人填志愿,不如说是一次将Agent技术应用于现实生活信息整合的极限压榨测试。它涉及对多个数据源的协同调度、对非结构化数据的解析,以及如何让数百个“数字劳动力”高效、稳定地协同工作。接下来,我就把这个从想法到实现的完整过程,包括技术选型、架构设计、踩过的坑和最终的效果,毫无保留地分享出来。
2. 核心逻辑拆解:Agent如何“查公司”
这个项目的核心目标很明确:输入一个大学专业名称,输出与该专业相关的、有价值的公司列表及深度信息。听起来简单,但拆解开来,每一步都需要Agent的参与。这里的“查公司”不是简单的关键词搜索,而是一个多步骤、有逻辑的侦察链条。
2.1 任务分解:从专业到公司的四层漏斗
我设计的Agent工作流,主要分为四个阶段,像一个层层过滤的漏斗:
岗位关键词提取(1个主Agent):首先,需要将“软件工程”、“金融学”、“生物技术”这样的专业名称,转化为招聘市场上通用的岗位关键词。例如,“软件工程”可能对应“后端开发”、“Java工程师”、“前端开发”、“算法工程师”等。这个步骤需要一个有理解能力的Agent,通过访问招聘网站的搜索建议或行业知识库来完成。我让这个Agent去分析主流招聘平台中,该专业毕业生最常投递的5-8个岗位名称。
公司初筛(N个并行Agent):获得岗位关键词列表后,针对每一个关键词,启动一批并行Agent。每个Agent的任务是:去一个指定的招聘平台(如某直聘、某聘),用这个关键词搜索,并抓取前N页(比如前5页)的招聘公司列表。这里的关键是去重和标准化公司名称。一个“腾讯科技(深圳)有限公司”可能被写成“腾讯”、“腾讯公司”等,需要初步归一化。
深度信息采集(M个并行Agent):对上一步骤合并去重后的公司列表,进行深度信息挖掘。这是最耗资源的一步,需要调用多种数据源。我设计了三类Agent分工合作:
- 工商信息Agent:访问天眼查、企查查等平台的公开接口或页面,抓取公司的注册资本、成立时间、融资轮次(A轮/B轮/C轮等)、经营范围、法律风险等。融资轮次是判断公司发展阶段和稳定性的重要指标。
- 市场表现Agent(针对上市公司):如果公司是上市公司,则启动这类Agent。它们会访问同花顺、东方财富等数据源,获取股票代码、当前股价、市值、近期财报关键数据(如营收、净利润增长率)。这里需要处理
marketid之类的股票市场标识符,用于精准定位。 - 舆情与评价Agent:访问职场社区、社交媒体,尝试抓取关于该公司的员工评价、面试经验、薪资爆料(需注意数据合规与隐私)。这部分信息噪音大,但有时能反映真实工作体验。
信息整合与报告生成(1个汇总Agent):所有并行Agent完成任务后,将数据汇集到一个中心节点。这个汇总Agent负责数据清洗(解决不同来源的数据冲突)、结构化,并按照预设的权重模型进行评分。例如,一个“成立5年、完成B轮融资、薪资范围中上、员工评价偏正面”的公司,会比一个“成立20年、未融资、薪资透明低、有较多劳动纠纷”的公司排名更高。最后,生成一份结构化的报告,可以是JSON、Excel,或直接渲染成一份简易的网页。
2.2 为什么选择Agent架构?而不是传统爬虫?
你可能会问,这不就是高级爬虫吗?为什么非要扯上AI Agent?这里有几个关键区别:
- 处理非结构化与动态内容:传统的定向爬虫对付结构固定的网页很拿手,但招聘网站和企查查这类平台反爬策略复杂,页面结构也经常变动。更重要的是,很多信息需要“理解”才能提取。比如,从一段公司描述中判断其所属行业,从融资历史中解析出“B+轮”,这需要一定的自然语言处理能力。Agent可以集成小模型(或调用大模型API)来处理这类语义理解任务。
- 任务规划与决策:一个简单的例子:如果“天眼查Agent”在查询时发现公司不存在(可能是名称不准确),它应该有什么备用方案?是尝试用简称再查一次,还是标记为“信息缺失”并转向下一个数据源?这需要简单的决策逻辑。Agent可以内置这些
if-else规则,形成工作流。 - 容错与自适应:当某个数据源暂时不可用或返回异常时,Agent可以记录错误、暂停或切换至备用源,而不是让整个流程崩溃。这对于需要长时间、大批量运行的系统至关重要。
- 协同与通信:在我的设计里,负责“Java工程师”的初筛Agent和负责“后端开发”的初筛Agent,发现“腾讯”后,需要知道这家公司已经被列入待深度查询列表,避免重复劳动。这需要Agent之间有简单的状态共享或消息传递机制。
所以,这个项目中的每一个“查询单元”,不仅仅是一个爬虫脚本,而是一个具备感知(解析网页)、决策(判断下一步)、执行(抓取数据)能力的轻量级智能体。
3. 技术实现:基于Kimi Work的Agent工厂
明确了逻辑,接下来就是技术选型和实现。我的核心平台是Kimi Work。
3.1 为什么是Kimi Work?
在项目初期,我评估过几种方案:
- 纯代码开发(如Scrapy + Celery):灵活性最高,但开发成本也最高,需要自己管理任务队列、分布式调度、异常处理,对于快速验证想法来说太重了。
- 低代码/无代码平台:一些RPA工具也能实现自动化,但在处理复杂逻辑和动态内容解析上能力有限,且并行扩展能力弱。
- 新兴的AI Agent平台:如Kimi Work、Coze等。它们的特点是原生支持将大模型能力与自动化工作流结合,提供了可视化的编排工具和相对简单的并发控制。
我选择Kimi Work,主要基于以下几点考虑:
- 内置浏览器自动化能力:它的Agent可以模拟真人操作浏览器,轻松应对JavaScript渲染的页面,这对于招聘网站和天眼查这类重度依赖JS的站点是刚需。无需自己处理Selenium和WebDriver的种种麻烦。
- 易于编排复杂工作流:通过拖拽节点就能设计出“判断-分支-循环”的逻辑,比如“查询成功则存储,失败则重试或换源”。这大大降低了实现多步骤Agent逻辑的门槛。
- 并发控制相对直观:虽然达不到专业分布式系统的精细度,但Kimi Work提供了任务并行化的选项,我可以将一个公司列表拆分成多个子任务,同时投递给多个Agent实例去执行,从而实现“300个Agent同时查”的效果。
- 快速集成与调试:对于需要调用外部API(如获取股票数据)或进行简单数据处理的环节,可以方便地插入代码节点(支持Python),整个流程的调试和迭代速度很快。
注意:Kimi Work这类平台通常有使用限制,比如并发数、单次运行时长等。在设计大规模任务时,必须将任务合理切分,避免触达平台限制导致运行失败。我的策略是将“深度信息采集”这步的公司列表,按每10-20家公司一组进行拆分,分批提交运行。
3.2 Agent的“技能”编码与配置
在Kimi Work中,每一个功能单元都可以看作一个Skill。我需要创建多个Skill,并组合成一个完整的工作流。
关键词提取Skill:这个Skill相对简单。我配置的提示词(Prompt)大概是:“你是一个职业规划专家。请根据输入的专业名称,列出在中文招聘市场上,该专业毕业生最可能应聘的5-8个具体岗位名称。只输出岗位名称列表,用逗号分隔。” 然后让这个Skill去调用Kimi的大模型能力,得到结果。
公司初筛Skill:这是一个需要浏览器自动化的Skill。我创建了一个Skill,其核心动作是:
- 输入:一个岗位关键词(如“Java工程师”)。
- 动作:打开指定的招聘网站,在搜索框输入关键词,点击搜索。
- 循环:滚动页面,使用“拾取”工具,定位并提取每个招聘职位下方的公司名称元素。
- 输出:一个去重后的公司名称列表。 我将这个Skill保存为一个模板。当需要并行处理多个关键词时,我就复制这个Skill模板,仅修改输入的关键词,然后让它们同时运行。
深度信息采集Skill组:这是最复杂的一簇Skill。
- 工商信息Skill:配置浏览器访问天眼查,输入公司名,提取“基础信息”、“融资历史”、“风险信息”等板块的文本。这里最大的挑战是页面结构的稳定性。天眼查的DOM结构偶尔会变,导致定位失败。我的应对策略是:采用相对宽松的文本匹配和多重选择器备用。比如,不绝对依赖某个
div的class,而是同时尝试通过标签路径和附近的特征文本来定位“注册资本”所在的区域。 - 市场表现Skill:对于上市公司,我需要其股票代码。我首先会用一个Skill,通过公司全名去财经网站搜索,获取其股票代码和
marketid。然后,另一个Skill会利用marketid,构造请求去获取更详细的股价K线数据或财务摘要。这里涉及到对同花顺等网站数据接口的简单分析。一个重要技巧是:使用浏览器开发者工具的“网络(Network)”选项卡,观察页面加载时发出的XHR或Fetch请求,直接找到返回结构化数据(往往是JSON格式)的API,这比解析HTML页面要稳定和高效得多。 - 数据清洗与合并Skill:这是一个纯数据处理的Skill(通常用Python代码节点实现)。它接收来自不同渠道的、关于同一家公司的原始数据,进行冲突解决。例如,天眼查显示注册资本1000万,企查查显示500万,则以更权威或更新日期更近的为准。同时,将散乱的数据整理成固定的JSON格式。
- 工商信息Skill:配置浏览器访问天眼查,输入公司名,提取“基础信息”、“融资历史”、“风险信息”等板块的文本。这里最大的挑战是页面结构的稳定性。天眼查的DOM结构偶尔会变,导致定位失败。我的应对策略是:采用相对宽松的文本匹配和多重选择器备用。比如,不绝对依赖某个
3.3 实现300并发:工作流编排与任务分片
“300个Agent同时查”是一种形象的说法,在Kimi Work中,并非真正同时启动300个独立的浏览器实例(资源不允许),而是通过工作流并行分支和批量任务来实现高并发感。
我的主工作流是这样设计的:
- 开始节点:输入专业名称。
- 节点A(关键词提取):调用第一个Skill,得到岗位列表
[kw1, kw2, kw3, kw4, kw5]。 - 节点B(并行初筛):这里使用Kimi Work的“并行分支”功能。为列表中的每一个关键词
kwi创建一个分支,每个分支内部调用公司初筛Skill模板,输入为kwi。这样,5个关键词的初筛工作就近乎同时开始了。假设每个关键词能搜到100家公司,去重后得到300家独特公司。 - 节点C(公司列表分片):将300家公司列表,按每15家一组,切分成20个分片
[slice1, slice2, ..., slice20]。 - 节点D(并行深度查询):再次使用“并行分支”,为20个分片创建20个分支。每个分支内部,是一个顺序执行的子工作流:对于分片内的15家公司,依次执行“工商信息查询”、“市场表现查询”(如果是上市公司)、“舆情抓取”(可选)。虽然这15家是顺序查的,但20个分片之间是并行的。这就相当于有20个“查询小组”在同时工作,每个小组负责15家公司。在资源层面,Kimi Work可能会排队或限制同时活跃的浏览器实例数,但从任务调度上看,这300家公司的查询任务是被同时推进的。
- 节点E(汇总与生成报告):所有并行分支结束后,将结果汇总到最后一个节点,进行最终的数据清洗、评分和报告生成。
通过这种“外层并行(分片间)+ 内层串行(分片内)”的架构,我有效地模拟了大规模并发查询,在平台资源限制内,最大化地提升了整体侦察效率。一次针对一个专业的完整侦察,从启动到生成报告,大约需要30-50分钟,其中大部分时间花在深度查询的浏览器模拟操作上。
4. 实战踩坑与稳定性优化
理想很丰满,现实很骨感。让几百个自动化Agent在复杂的网络环境里稳定运行,充满了挑战。下面是我遇到的主要问题及解决方案。
4.1 数据源的反爬与容错机制
这是最大的不稳定因素。招聘网站和天眼查都有很强的反爬虫策略。
- 问题表现:频繁遇到验证码、IP被封禁、页面返回“加载异常”或完全非预期的内容。
- 解决方案:
- 速率限制(Rate Limiting):即使在并行模式下,我也在每个Agent的请求之间加入了随机延时(1-3秒),模拟人类操作间隔。这是最基本的道德和技术要求。
- 自动重试与降级:我为每个查询步骤设置了最多3次重试。如果连续失败,则将该公司标记为“查询失败”,并记录失败原因。对于工商信息,我准备了天眼查和企查查两个数据源作为备份,主源失败则自动切换至备用源。
- 动态元素定位:不要依赖绝对不变的CSS选择器。我大量使用了通过“文本内容包含”和“XPath轴”的相对定位方式。例如,寻找“注册资本”时,先找到包含“注册资本”文本的标签,再定位其相邻的下一个
<td>或<span>。这样即使外层div的class变了,只要页面文案没变,就能找到。 - 关键数据验证:每次成功提取数据后,进行简单的合理性验证。比如,如果提取的“成立日期”是一个未来的时间,或者“注册资本”是一个非数字字符串,则判定本次提取可能失败,触发重试或标记异常。
4.2 数据清洗中的冲突解决
不同来源的数据对同一家公司的描述可能不同。
- 问题案例:公司“北京字节跳动网络技术有限公司”,在某招聘网站被简写为“字节跳动”,在天眼查是完整名称,在职场社区可能被叫做“字节”。如何认定它们是同一家公司?
- 解决方案:
- 名称标准化:建立一个小型的“公司名称-标准名”映射表。对于知名公司,我手动维护了这个映射。对于未知公司,则使用模糊字符串匹配算法(如Python的
difflib库),计算相似度。当相似度超过某个阈值(如0.8),且所在城市、行业关键词匹配时,则判定为同一家公司。 - 唯一标识符优先:如果能在某个数据源(如天眼查)找到公司的统一社会信用代码,则以此作为唯一ID进行数据聚合,这是最准确的方式。
- 置信度权重:在最终报告中,我会标注每条信息的来源。对于冲突信息,我会根据数据源的公认权威性(如工商信息以天眼查为准,股价以同花顺为准)和数据的时效性来决定采纳哪一个,并在报告中以注释形式说明。
- 名称标准化:建立一个小型的“公司名称-标准名”映射表。对于知名公司,我手动维护了这个映射。对于未知公司,则使用模糊字符串匹配算法(如Python的
4.3 Kimi Work平台本身的限制与应对
- 运行时长限制:单个工作流或Skill有最长运行时间限制。对于深度查询这种长任务,必须分片。我的分片大小(15家公司)就是通过测试得出的平衡点:既能保证一个分片能在限制时间内完成,又让分片数量不至于太多(超过并行分支数上限)。
- 并发数限制:平台对同时运行的浏览器实例或任务数有上限。我的20个并行分片设计,是在测试了平台极限后确定的稳定值。有时需要排队,但总体吞吐量可以接受。
- 环境隔离与状态残留:Kimi Work的每次运行环境并非完全隔离。偶尔会出现上一个任务的浏览器Cookie或缓存影响到下一个任务的情况。我的应对方法是,在关键Skill的开始阶段,强制执行“清除浏览器缓存”或“打开新的无痕窗口”操作(如果平台支持),确保每次查询都在干净的环境中进行。
5. 成果应用与价值反思
经过多次调试和优化,这个系统已经能够稳定运行。我输入“电子信息工程”,大约40分钟后,得到了一份包含约200家公司详情的报告。报告不仅列出了公司名,还附带了成立年限、融资阶段、招聘岗位数量、薪资范围中位数(来自招聘信息),以及是否为上市公司、市值规模等维度。
这份报告的价值是立体的:
- 对学生和家长:他们能清晰地看到,读这个专业,未来最可能进入哪些类型的公司(是初创公司多还是巨头多?是硬件厂多还是互联网公司多?),这些公司的基本面如何(融资到B轮以上的公司,通常比天使轮的公司更稳定)。这比单纯看学校就业率数字要直观得多。
- 对志愿填报本身:如果报告显示某个专业对应的头部公司地域集中度很高(比如大部分优质公司都在长三角),那么学生在选择学校地域时,就可以有所侧重。
- 对技术人:这个项目本身是一次精彩的Agent技术应用示范。它证明了,利用现有的AI Agent平台,个人开发者完全有能力构建出处理复杂、多步骤现实任务的自动化系统。其中的任务分解、并行调度、容错处理等思路,可以迁移到很多其他领域,比如竞品分析、市场调研、舆情监控等。
当然,这个系统也有其局限性。数据的全面性和准确性受限于公开数据源和反爬策略;对公司的评价维度还比较量化,缺乏更感性的文化氛围判断;系统的运行成本(主要是Kimi Work等平台的资源消耗)也不低,不适合完全免费公开服务。
但无论如何,这次实践让我深刻体会到,当AI Agent技术从演示走向实干,它能爆发的生产力是惊人的。它不再是一个聊天玩具,而是一个可以定制、可以编排、可以大规模协同的“数字军团”。高考填志愿只是一个起点,信息过载时代的精准侦察,或许正是Agent们大显身手的战场。如果你也对自动化解决复杂问题感兴趣,不妨从一个小痛点开始,设计你的第一个Skill,调度你的第一个Agent,这个过程本身,就是最好的学习。
