从零搭建一个完整的ai-agent小项目

我们要做的是一个包含前后端完整可运行的小 Agent 产品:

🎨 AI 服装灵感设计师
功能 :用户输入一句话:

Agent 会自动完成 5 个步骤:

1️⃣ 拆解子查询

2️⃣ 联网搜索

3️⃣ 总结趋势

4️⃣ 生成文生图 Prompt

5️⃣ 生成图片

通过这个小项目,你可以了解到:

  • 怎么使用langchain搭建简单agent流程
  • 如何进行搜索、文生图等工具调用
  • 怎么将搭建的agent流程部署到一个简单的后端
  • 如何添加一个简单的前端入口

完整代码在链接

博主会一步步拆解任务,跟着进行你也可以跑起来!

目录

  • [Step0 先从请求一次LLM开始](#Step0 先从请求一次LLM开始)
  • [Step1 升级为langchain调用](#Step1 升级为langchain调用)
  • [Step2 任务分解执行](#Step2 任务分解执行)
  • [Step3 从最简单的后端开始](#Step3 从最简单的后端开始)
  • [Step4 流式返回结果](#Step4 流式返回结果)
  • [Step5 加一个简单的前端](#Step5 加一个简单的前端)
  • 总结

Step0 先从请求一次LLM开始

在谈 Agent 之前,我们先做一件非常朴素但关键的事:

👉 直接请求大模型帮我们把一句话拆成多个"子查询"。

如果你已经对此很熟悉,可以直接跳到下一步~

所谓请求大模型,就是把我们日常从网页端输入问题问各种大模型得到回答的过程,变成用代码直接发送你的请求到大模型提供的接口,然后拿到输出结果的过程。

比如输入:

复制代码
赛博朋克风金属反光外套

我们希望模型输出:

复制代码
{
  "sub_queries": [
    "赛博朋克风服装风格",
    "金属反光材质 外套 设计",
    "未来感 女装 外套 趋势"
  ]
}

各家大模型的调用方式大差不差,以seed为例:

替换为你自己的KEY之后,运行这段代码,就可以看到模型针对我们的问题"将以下服装设计主题拆解为3-6条可搜索的子query:赛博朋克风格女外套"进行的回答

python 复制代码
from openai import OpenAI
# 直接调用
client = OpenAI(
    base_url=OPENAI_API_BASE, 
    api_key=OPENAI_API_KEY )
completion = client.chat.completions.create(
    # Replace with Model ID . 
    model="doubao-seed-1-6-251015", 
    messages = [
        {"role": "user", "content": "将以下服装设计主题拆解为3-6条可搜索的子query:赛博朋克风格女外套"},
    ],
)
print(completion.choices[0].message.content)

Step1 升级为langchain调用

OK 经过Step0 我们已经可以成功的请求到一次LLM了,而整个agent就建立在多次调用LLM的基础之上~

但是,在继续进行之前,我们要了解一下Langchain

LangChain 是一个用于开发由语言模型驱动的应用程序的框架。他主要拥有 2 个能力:

可以将 LLM 模型与外部数据源进行连接

允许与 LLM 模型进行交互

可能有人会问,像上面这样直接调用不也能拿到结果吗?为什么还要加别的方式?

像上面这种直接请求的方式能跑,但有 3 个硬伤:

复制代码
  messages = [
        {"role": "user", "content": "将以下服装设计主题拆解为3-6条可搜索的子query:赛博朋克风格女外套"},
    ],

1️⃣ Prompt 写在字符串里,不好维护

2️⃣ 没法复用逻辑

3️⃣ 后面步骤一多,代码逻辑会变得很难看==

---> 升级为langchain的方式调用:

可以统一的修改sysprompt 每次调用的时候 不同的query可以像参数一样传进去,而整个代码都不用变

python 复制代码
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate
from langchain_classic.chains import LLMChain
# langchain调用
llm = ChatOpenAI(model="doubao-seed-1-6-251015", temperature=0.4, api_key=OPENAI_API_KEY, openai_api_base=OPENAI_API_BASE)

# 系统指令
sub_sys = """
将以下服装设计主题拆解为3-6条可搜索的子query。只返回JSON格式数据,json_key为sub_queries,value为list格式
     主题:{query}
"""
sub_query_prompt = ChatPromptTemplate.from_messages([
SystemMessagePromptTemplate.from_template(sub_sys),
  HumanMessagePromptTemplate.from_template('{query}')
])
sub_query_chain = LLMChain(
    llm=llm,
    prompt=sub_query_prompt
)
# 每次调用 query可以通过参数传进去
sub_queries = sub_query_chain.run({"query": "赛博朋克风格女外套"})
print(sub_queries)

升级为langchain后

✅ 可复用 Chain

✅ Prompt 与逻辑分离

✅ 后面可以无限接新步骤

✅ 每个步骤都可以单测 / 替换模型

Step2 任务分解执行

在Step1之后,我们只要按照类似的方式,就可以多次请求大模型,上一步的输出可以作为下一步的输入,比如我们的主体逻辑就可以浓缩为这样一个函数:

python 复制代码
def run_fashion_agent(user_query):
   # Step1 拆解子query
    sub_query_raw = sub_query_chain.run({"query": user_query})
    sub_queries = json.loads(sub_query_raw)['sub_queries']
    print("get {} sub queries".format(len(sub_queries)))
    # Step2 web search 
    search_results = []
    for q in sub_queries:
        print("searching {}".format(q))
        search_results.append(web_search.run(q))
    print("search result [0], type:{} content:{}".format(type(search_results[0]), search_results[0]))
    # Step3 总结搜索结果
    summary = summary_chain.run({
        "result": search_results
    })
    if summary:
        summary = summary.strip()

    print('get summary :{}'.format(summary))

    # Step4 根据总结的搜索信息构建图像prompt 
    final_prompt = prompt_builder_chain.run({
        "summary": summary
    })
    print("#### 文生图 prompt ####")
    print(final_prompt)

    # Step5 文生图
    image_url = generate_image.run(final_prompt)

1)拆分子query

python 复制代码
sub_sys = """
将以下服装设计主题拆解为3-6条可搜索的子query。只返回JSON格式数据,json_key为sub_queries,value为list格式
     主题:{query}
"""
sub_query_prompt = ChatPromptTemplate.from_messages([
SystemMessagePromptTemplate.from_template(sub_sys),
  HumanMessagePromptTemplate.from_template('{query}')
])

sub_query_chain = LLMChain(
    llm=llm,
    prompt=sub_query_prompt
)

2)搜索子query

大模型本身并不能直接联网搜索(截至目前),我们需要调用外部工具来进行web search。

SerpAPI/Tavily API等许多api都可以

这里使用Tavily为例子 摘自知乎

Tavily Search 是一个专为大型语言模型(LLM)和 AI Agent 优化的搜索引擎 API。

Tavily Search 不仅仅是一个简单的搜索接口,更是一个智能的信息处理层。当一个查询被发送到 Tavily 时,它会在后台执行复杂的搜索、抓取、过滤和信息提取流程,最终将最核心、最相关的内容整合起来 ,以一种对 LLM 友好的格式返回。

使用前需要获取Tavily API 官网

使用起来则很简单

python 复制代码
from tavily import TavilyClient
tavily = TavilyClient(api_key=TAVILY_API_KEY)
# 搜索
tavily.search(query=query, max_results=5)

3) 总结搜索信息

和拆分子query类似 将搜索结果给到大模型进行总结(prompt可以自由发挥)

python 复制代码
summary_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是服装设计趋势分析师"),
    ("user", """请根据以下搜索结果,总结:
    - 风格关键词
    - 色彩
    - 材质
    - 廓形
    - 情绪氛围
    - 标志性主题
    
    搜索结果:
    {result} """)

])

summary_chain = LLMChain(llm=llm, prompt=summary_prompt)

4)根据搜索结果凝练文生图prompt

与1) 3)类似 请求一次LLM

python 复制代码
# 文生图prompt 构建
prompt_builder_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是专业文生图 Prompt工程师,而且非常了解时尚和服装设计领域"),
    ("user", """根据以下服装设计总结,生成一个高质量的文生图prompt。
    要求:时尚杂志风格,摄影级画面,秀场风格,中文prompt
    设计总结:{summary} 
    请直接输出文生图prompt,不需要其他内容""")
])

prompt_builder_chain = LLMChain(llm=llm, 
prompt=prompt_builder_prompt)

5)调用文生图

支持文生图的模型也很多,这里简单用了seedream,和调用LLM的方式很类似:

python 复制代码
image_client = OpenAI( 
    base_url=OPENAI_API_BASE, 
    api_key=OPENAI_API_KEY, 
) 
 result = image_client.images.generate( 
    model="doubao-seedream-4-5-251128", 
    prompt=prompt,
    size="2K",
    response_format="url",
    extra_body={
        "watermark": True,
    },
    )

以上就是我们agent中执行的全部操作了,其实并没有很多代码对不对?可以放到chain.py 和tool.py中方面上面的整个流程run_fashion_agent中按顺序调用

Step3 从最简单的后端开始

既然我们agent的逻辑基本理清,每一步的agent都执行什么操作已经验证过了,现在可以考虑将我们的agent逻辑封装为小型后端服务了。

先从最简单的开始:

现在我们做第一版后端,只干一件事:

接收 query → 调用 sub_query_chain → 返回结果

python 复制代码
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

app = FastAPI(title="Fashion Design Agent")
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)
# 调用LLM的逻辑
llm = ChatOpenAI(model="doubao-seed-1-6-251015", temperature=0.4, api_key=OPENAI_API_KEY, openai_api_base=OPENAI_API_BASE)

# 系统指令
sub_sys = """
将以下服装设计主题拆解为3-6条可搜索的子query。只返回JSON格式数据,json_key为sub_queries,value为list格式
     主题:{query}
"""
sub_query_prompt = ChatPromptTemplate.from_messages([
SystemMessagePromptTemplate.from_template(sub_sys),
  HumanMessagePromptTemplate.from_template('{query}')
])
sub_query_chain = LLMChain(
    llm=llm,
    prompt=sub_query_prompt
)

@app.post("/design")
async def design(req: dict):
    query = req.get("query", "")
    result = sub_query_chain.run({"query": query})
    return result
if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=9111)

可以看到design函数中调用的sub_query_chain.run()就是我们在Step2中的内容

安装相应依赖后

复制代码
python -m main

就可以启动后端项目了,如果正常启动,会显示一个地址,可以通过curl命令验证

Step4 流式返回结果

复制代码
/backend_app
  /agent
    - __init__.py
    - tools.py
    - chains.py
    - runner.py
  - main.py

按照项目目录,我们可以把上面所有的agent逻辑都放在runner中的run_fashion_agent函数中,然后在main中进行调用,那么会等到所有步骤都完成后一次性拿到结果

python 复制代码
def run_fashion_agent(user_query):
   # Step1 拆解子query
    sub_query_raw = sub_query_chain.run({"query": user_query})
    sub_queries = json.loads(sub_query_raw)['sub_queries']
   # 中间步骤
   ......

    # Step5 文生图
    image_url = generate_image.run(final_prompt)

但这样等待时间会很长......

更好的方式是流式返回,每一个步骤完成后立即返回

后端可以进一步修改为fast AP i+ SSE流式返回

main函数中:

python 复制代码
@app.get("/design/stream")
async def design(query: str = Query(...)):
    return StreamingResponse(
        fashion_agent_stream(query),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        }
    )

SSE返回:

python 复制代码
def sse_event(event_name: str, data: dict):
    """格式化 SSE 事件"""
    return f"data: {json.dumps({'step': event_name, 'payload': data}, ensure_ascii=False)}\n\n"

agent逐步返回数据:

python 复制代码
async def fashion_agent_stream(user_query):
    """SSE流式返回
    """
    # step1 
    yield sse_event("status", {"step":1, "message": "Generating sub queries..."})
    sub_query_raw = sub_query_chain.run({"query": user_query})
    sub_queries = json.loads(sub_query_raw)['sub_queries']
    print("get {} sub queries".format(len(sub_queries)))
    yield sse_event("step1", {
        "step": 1,
        "sub_queries": sub_queries
    })
    # Step2: seach
    yield sse_event("status", {"step":2, "message": "Searching web..."})
    search_results = []
    for q in sub_queries:
        print("searching {}".format(q))
        search_results.append(web_search.run(q))
    print("finish search, search 0:", search_results[0])
    yield sse_event("step2", {
        "step":2,
        "search_results": search_results
    })

    .......

    yield sse_event("done", {"message": "All steps completed"})

那么到现在为止,你可以得到一个可以完整执行agent全部逻辑,逐步返回每一步结果,最终生成图片链接的后端项目了!

Step5 加一个简单的前端

前端只做 3 件事:

1️⃣ 发送 query

2️⃣ 监听 SSE

3️⃣ 根据 step 更新 UI

核心代码(极简版)

javascript 复制代码
const BACKEND_URL = "http://127.0.0.1:9111/design/stream";

const url = `${BACKEND_URL}?query=${encodeURIComponent(query)}`;
    const es = new EventSource(url);
    esRef.current = es;

    es.onmessage = (e) => {
      try {
        const data = JSON.parse(e.data);
        const eventType = data.step;
        const payload = data.payload;

        // 映射后端步骤名到前端步骤名
        const stepMapping: Record<string, string> = {
          "step1": "sub_queries",
          "step2": "search_results",
          "step3": "summary",
          "step4": "final_prompt",
        };

具体可以看链接 frontend就是前端项目,在后端启动之后,启动前端,点击按钮就会执行后端的任务

总结

如果你一路看到这里,你应该已经大致了解了:

✅ 如何用 LLM 拆解任务

✅ 如何用 LangChain 组织多步骤逻辑

✅ 如何用 FastAPI 做 Agent 服务

✅ 如何用 SSE 做实时流式返回

✅ 如何用前端可视化 Agent 思考过程

可以尝试运行[完整项目] (https://github.com/JoJoJun/ai_agent_for_clothes_design/tree/main)整体感受一下 (顺便点个star👍)

后面也许可以扩展成:

🧳 旅行规划 Agent

📈 投资研究 Agent

🧠 学习助理 Agent

🛍 电商选品 Agent

结构都是类似的~

相关推荐
AngelPP3 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年3 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼4 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS4 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区5 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈5 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang5 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx
shengjk17 小时前
NanoClaw 深度剖析:一个"AI 原生"架构的个人助手是如何运转的?
人工智能
西门老铁9 小时前
🦞OpenClaw 让 MacMini 脱销了,而我拿出了6年陈的安卓机
人工智能