从零开始:前端转型AI agent直到就业第十八天-第五十六天

0 阅读14分钟

前言

接近8.9年老前端了,34岁,双非普本,坐标广州,25年底被裁员,然后这三个月内也有去投简历,也有面试,有一些推进到二面然后就没有下文,不禁感叹现在的大环境实在不怎么样,而且前端在AI的冲击下也是最受影响的,除了音视频,图形化方面还能蹦跶一下,AI已经能完成80-90%的前端工作,在学历以及就业背景都不是特别强的情况下,一般的前端哪怕你技术还不错,你也很缺竞争力;在失业这三个月经历了持续学习、迷茫到看到曙光,决定要转型自学做AI agent;

大纲

  • 心路历程

  • 时间分配(不限于学习,也会有运动)

  • AI agent实践项目总结

    • 成果展示
    • 项目总结
  • 个人博客(催更途径)

  • 帮助

    • 学习
    • 求职

心路历程

真没跑路,哈哈,最近停更了一段时间,是因为都在实践项目,现在项目成果出来了,不就来了吗兄弟们 说说停更了快一个月都在做什么吧

  1. 锻炼
  2. 炒股
  3. 学习
  4. 打打小丑牌

锻炼的话是间歇性,很多时候隔一天锻炼1-2个小时,效果还是很好的,最起码精神状态会因为锻炼而更饱满,精气神很重要啊

炒股的话就别问了,本来这个月行情是应该大赚的但是又亏回去了,这个月不赚不亏,亏了些时间

学习的话就是把第一个AI agent项目给做了,所以也就有了这篇文章出来

打打小丑牌🤡:这个游戏真的很上头,别看它简单,有时候想放松一下,直接放松一下就是2个小时起步,所以后面果断删了

时间分配

停更这段时间,学习的时间其实并没有十分饱满,可能占到一半吧,事情有点多,有时候也浮躁了,在这个时候我们应该让心静下来,慢慢规律的学习增强自身,提高技能以及心态

AI agent实践项目总结

项目展示

RentAgent.AI

项目动机:之前跟朋友聊天它准备开展澳洲那边的房屋租赁业务,那么这个业务要是发展起来,一个可以智能回答的智能体就可以节省很多人力了,所以就有了这个项目

访问地址: rent-agent-fronted.vercel.app/ 需要🪜

基于 AI 驱动的轻量级澳洲房源智能分析与检索系统,致力将复杂的自然语言选房需求转化为精准的房源数据展现。

核心技术:Text-to-SQL

人话理解:人类语言->机器语言->SQL->获取关键数据->机器语言->人类可理解(语言/图像)

PC效果展示图:

微信图片_20260526194449_270_179.png

移动端效果展示图:

微信图片_20260526194535_271_179.png

tokens使用查询展示图: 微信图片_20260526215708_272_179.png

全盘业务流程解析

整个 RentAgent 从用户提问到拿到最终数据,经历了以下宏观业务闭环:

  1. 用户输入:用户在前端输入“帮我找悉尼价格在600左右的公寓”。
  2. API 接收:FastAPI /api/query 接收到请求,并交由 QueryService 处理。
  3. 图引擎启动 (LangGraph):将用户的问题作为初始状态 (State) 注入图执行环境。
  4. 元数据召回 (混合检索):在图中,Agent 自动根据关键词去 Elasticsearch 查“悉尼”,去 Qdrant 查“价格”。
  5. SQL 生成与执行:大模型结合找出的字段拼接生成真实的 SQL,并去 dw (数据仓库) 执行。
  6. SSE 流式返回:在上述每一个节点执行完毕时,通过 Server-Sent Events (SSE) 向前端推送实时进度(“正在召回字段...”、“正在生成SQL...”),最后将数据结果一并推给前端渲染表格。

根据上述业务流程描述的几个功能体验:

  1. 显示当前的所有的租赁信息
  2. 生成一个新的随机租赁信息(这个时候你就可以去问智能体询问这个新的租赁信息了,主线为了显示实时性,新加入的信息数据智能体也可以通过SQL查出来)
  3. 问询智能体,查询你想要知道的租赁信息, 示例:帮我找一下可以在Sydney CBD养宠物的房子"
  4. 控制台显示,这个时候你可以通过控制台查看到每个节点的执行日志
  5. 查看tokens使用情况,有部分节点是有使用到LLM大模型的,完成了一次问询之后你就可以通过右上角的token使用情况按钮去查看那些节点的token使用情况,因为是使用你的ip作为查询条件,所以只会显示你的操作记录
项目总结(前端部分)
工作流程
  1. 输入:用户输入自然语言选房需求(例如:“帮我找一下价格在 500 到 600 的房子,且能养宠物的”)。
  2. 理解与规划:AI Agent (由 LangGraph 驱动的后端) 接收需求,通过 12 个完整的智能处理节点进行链路推理与决策决策:
    • 抽取关键字 ➔ 召回字段 ➔ 召回指标 ➔ 召回值 ➔ 合并召回信息 ➔ 过滤指标 ➔ 过滤表格 ➔ 添加额外上下文信息 ➔ 生成SQL ➔ 验证SQL ➔ 校正SQL(验证不通过时执行) ➔ 执行SQL
  3. 输出:前端实时展现工作流执行日志(Developer Console Logs)与查询到的澳洲房源卡片/列表,直观呈现数据指标(KPI卡片)以及 Token 消耗审计。
技术栈
分类选型说明
框架React 18 + Vite 5现代化前端工程构建 & 极速热更新
样式Tailwind CSS v4现代 Web3 风格,深色渐变与玻璃态微光质感
AI 代理后端LangGraph + FastAPI实现高度智能的 SQL 生成与自愈逻辑 (远程服务器部署)
图标Lucide React提供一致性高的高品质图标集
数据监控Vercel Web Analytics实时跟踪并记录网页访问量及转化数据
核心技术要点
  • 实时执行状态追溯 (Developer Console Logs):前端内建仿真开发控制台,记录并滚动显示 LangGraph 后端各个节点的执行轨迹与状态反馈,方便分析流程。
  • 全平台自适应响应式设计 (Responsive Layout)
    • 桌面端:沉浸式多栏 Dashboard,房源列表与 AI 助手左右分屏,保持工作流饱满。
    • 移动端:布局自动流式向下堆叠,智能隐藏次要表格列,并配备一键开启控制台的悬浮按钮 (FAB),结合物理阻尼滑入与淡入遮罩动效,完美适配小屏阅读。
  • 多维度统计与 Token 消耗审计:自动统计当前符合筛选条件的房源数据(包括平均租金、平均租约、总营收流水等 KPI),并集成明细弹窗,详尽展示每个智能节点所使用的 LLM 模型、输入/输出 Token 数量、预计折算费用等。
  • 配置一致的接口路由代理:配置 Vite Proxy(本地开发)与 vercel.json rewrite(生产部署),将所有 API 路由收归为相对路径 /api,确保前后端分离模式下无 CORS 跨域困扰。
后端部分
RentAgent 智能数据分析引擎与架构知识图谱

RentAgent 是一个基于大模型 (LLM) 驱动的垂直领域 (澳洲租房) 智能数据分析 Agent。它致力于将用户的自然语言查询(如"悉尼可以养宠物的两居室平均周租金多少?")通过一系列严密的图灵完备逻辑流转,转化为精准的 SQL 并在数据仓库中执行,最终实时返回结构化数据给用户。

本文档将系统性地梳理该项目所涉及的业务逻辑、系统架构、AI 核心技术点,并提供由浅入深的深度剖析。


核心技术栈全景图
技术领域选型核心作用与优势说明
Agent 框架LangGraph提供带状态的有向图执行引擎,支持容错与循环重试(相较于传统 LangChain 单向流更加灵活且稳定)
后端框架Python 3.12+ / FastAPI提供高性能的异步 API 接口服务,以及对 AI 生态的原生最佳支持。选用 3.12 以获取更好的运行性能。
底层大模型DeepSeek-V3 / GPT-4o / Claude核心推理引擎,用于理解意图、分解步骤以及生成高质 SQL
向量化模型 (Embedding)bge-large-zh-v1.5 + TEI使用 HuggingFace 的 Text Embeddings Inference (TEI) 暴露 REST API,配合 BGE 模型进行极速的中文语义向量化,完全私有化部署。
关系型数据库MySQL 8.0dw (数据仓库,存储租房业务数据);meta_db (元数据库,存储表结构、列信息和指标定义)
向量数据库Qdrant用于存储和检索元数据的 Embedding,支持语义相似度检索 (Semantic Search)
全文搜索引擎Elasticsearch (ES)用于处理基于倒排索引的精确关键词匹配和值召回 (Keyword Search)
包管理工具uv替代传统 pip,提供极速的依赖解析与虚拟环境管理

重要知识点:
LangGraph 核心编排

这是整个数据大脑的“神经中枢”。它通过节点(Node)与边(Edge)的定义,实现了遇到 SQL 报错时自我纠错并循环重试的机制:

# 节选自: app/agent/graph.py
graph_builder = StateGraph(state_schema=DataAgentState, context_schema=DataAgentContext)

# 1. 挂载所有处理节点 (工人)
graph_builder.add_node("recall_column", recall_column)
graph_builder.add_node("generate_sql", generate_sql)
graph_builder.add_node("validate_sql", validate_sql)
graph_builder.add_node("correct_sql", correct_sql)
graph_builder.add_node("run_sql", run_sql)

# 2. 编排流水线顺序
graph_builder.add_edge("generate_sql", "validate_sql")

# 3. 条件边判断:纠错机制的灵魂
def validate_sql_result_condition(state: DataAgentState) -> str:
    # 只要验证不通过(有错误信息),就把状态传给 correct_sql 节点,否则直接运行 SQL
    return "run_sql" if state["error"] is None else "correct_sql"

graph_builder.add_conditional_edges(
    "validate_sql", 
    validate_sql_result_condition, 
    ["correct_sql", "run_sql"]
)
graph_builder.add_edge("correct_sql", "run_sql") # 纠错后重新尝试运行

data_agent_graph = graph_builder.compile()
底层高性能并发封装

在处理上万个维度的向量化时,LangChain 原生的 OpenAIEmbeddings 组件容易在并发时触发 502 Bad Gateway。项目中直接抛弃了重度封装,转而使用异步 Http 客户端对接私有化 TEI 模型接口:

# 节选自: app/clients/embedding_client_manager.py
async def embed(self, text: str) -> list:
    """直接调用 TEI REST API,每次新建连接,避免连接复用导致的 502"""
    import httpx
    async with httpx.AsyncClient(timeout=60.0) as http:
        resp = await http.post(
            self._embed_url,
            json={"model": self._model, "input": text},
            headers={"Authorization": "Bearer -"},
        )
        resp.raise_for_status()
        return resp.json()["data"][0]["embedding"]
物理数仓转知识语义仓

这是把普通关系型数据库转化为能被大模型“检索”和“理解”的 Meta 库的魔法脚本:

# 节选自: app/services/meta_knowledge_service.py
async def _save_embddding_to_qdrant(self, column_infos: list[ColumnInfo]):
    points = []
    for column_info in column_infos:
        # 为每一个物理列的名称、描述、甚至别名单独建立检索目标
        points.append({
            "id": uuid.uuid4(),
            "embedding_text": column_info.name,
            "payload": asdict(column_info),
        })
        points.append({
            "id": uuid.uuid4(),
            "embedding_text": column_info.description,
            "payload": asdict(column_info),
        })

    # 通过我们刚刚编写的异步客户端获取语义向量
    embeddings = []
    for text in [p['embedding_text'] for p in points]:
        embedding = await self.embedding_client.embed(text)
        embeddings.append(embedding)

    # 存入 Qdrant 向量库,供后续 RAG 环节使用
    ids = [point['id'] for point in points]
    payloads = [point['payload'] for point in points]
    await self.column_qdrant_repository.upsert(ids, embeddings, payloads)
系统防御提示词

提示词是控制大模型的准绳。在 SQL 生成节点中,我们需要极度严格地限定大模型的权限和输出格式:

【任务要求】
1. 仅允许使用数据表信息中真实存在的表与字段名称,禁止编造、猜测或引入未提供的表和字段。
2. 若指标信息中存在相关指标定义,必须严格遵循其业务口径、计算逻辑、过滤规则与时间口径。
3. 生成的SQL只能用于查询,不能涉及数据写入、更新、删除等操作(绝对安全隔离)。
...
8. 当用户查询意图是列出或查询某种实体时,SELECT 投影列中应当且仅应当返回该实体的 8 个核心维度属性且必须全部都返回,不可以缺少其中任何一个(即 product_id, product_name, property_type, bedrooms, bathrooms, price, is_pet_friendly 及其关联的 region_name)。

核心架构与技术解析 (深入浅出)
状态机驱动的 LangGraph 节点工作流

[官方描述] LangGraph 是一个用于构建带状态的、多参与者 Agent 的库。它基于图理论建模,相较于 LangChain 的单向流,它原生支持循环(Cycles),允许我们在遇到错误时进行自我修正。

[生活比喻] 你可以把 LangGraph 想象成一家高级餐厅的标准化后厨流水线。点菜单放在托盘(State)上传递: 配菜工 (召回节点) 去冷库拿菜 -> 主厨 (生成节点) 炒菜 -> 质检员 (SQL验证)。如果质检员发现太咸(SQL有语法错误),他不会端给客人,而是把菜打回给主厨(纠错节点/循环),要求重新炒。

[代码示例:纠错节点的自我演进逻辑]

# 节选自: app/agent/nodes/correct_sql.py
async def correct_sql(state: DataAgentState, runtime: Runtime[DataAgentContext]) -> DataAgentState:
    sql = state["sql"]
    error = state["error"] # 上一节点执行捕捉到的真实报错信息
    query = state["query"]
    
    # 组装包含报错信息的 Prompt,命令大模型修复
    prompt = PromptTemplate(template=load_prompt("correct_sql"), input_variables=["query", "metric_infos"])
    chain = prompt | get_llm("校正SQL") | StrOutputParser()

    result = await chain.ainvoke({
        "query": query,
        "sql": sql,
        "error": error,
        "table_infos": yaml.dump(state["table_infos"]),
        "db_info": yaml.dump(state["db_info"])
    })
    
    # 覆盖原状态的 sql 并重抛回循环
    return {"sql": result}
SSE 服务器发送事件 (Server-Sent Events)

[官方描述] SSE (Server-Sent Events) 是一种允许服务器在一个长连接中单向、实时向客户端流式推送事件的技术,非常适合解决 LLM 响应缓慢带来的前端假死问题。

[生活比喻] 普通的 HTTP 请求就像发电子邮件:发信后死等半小时才收到全量回复。 SSE 就像打电话转播足球赛:电话不挂断,对方不断汇报“现在在召回数据...”、“现在在纠正SQL...”、“找到了!”。你随时都能知道最新进展,毫无等待焦虑。

[代码示例:通过 astream 推送流数据]

# 节选自: app/services/query_service.py
async def query(self, query: str):
    context = DataAgentContext(...) # 注入所有的 Repository 资源
    state = DataAgentState(query=query)
    
    try:
        # 使用 astream 和 custom 模式,获取图流转过程中的每一个实时切片
        async for chunk in data_agent_graph.astream(input=state, context=context, stream_mode="custom"):
            # 以标准的 SSE 数据格式 yield 出去,确保前端能不断连接接收并实时渲染
            yield f"data: {json.dumps(chunk, ensure_ascii=False, default=str)}\n\n" 
    except Exception as e:
        yield f"data: {json.dumps({'type': 'error', 'message': str(e)})}\n\n"
后续想要推进的升级
探索 LlamaIndex 替代原生混合检索

原来的混合检索服务部署在云服务器太费内存了,而且较为embedding跟es混合检索的方式较为手动,学习是不错,但是真要在企业运用的话感觉LlamaIndex会更好

引入 LlamaIndex 重构底层的 RAG 检索引擎。LlamaIndex 提供了高度封装的 VectorStoreIndexKeywordTableIndex 以及高级的 RouterQueryEngine。它不仅能利用大模型进行智能路由(自动判断用什么检索),且内置丰富的后处理能力,能大幅削减 MetaKnowledgeService 和 Node 中的样板代码。

个人博客(催更途径)

jerryq1.github.io/press/

因为发文章到掘金还要把知识文档进行二次整理,需要耗费不少时间,在没有更新的情况下,大家可以关注我的博客,一般我学习完会把学习到的知识点当天就总结到博客,同时大家可以在对应的博客文档下面发起评论喊我更新也可以哈哈哈

微信图片_20260526222018_275_179.png

微信图片_20260526222006_274_179.png

微信图片_20260526221957_273_179.png

目标

成为AI agent工程师并且就业

帮助

需要大家的关注跟点赞,你们的关注点赞就是对我最大的鼓励,或许以后待以后我技术成熟时,你们中间的大佬还可以捞一捞我,感谢

如果有大佬有不错的就业机会请联系我,坐标广州,保险的话可以找我当个高级前端开发,要是用人比较大胆的话可以把我放在AI agent的方向或者全栈的方向,感谢