ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

AI应用开发入门:从API调用到构建第一个后端接口

AI应用开发入门:从API调用到构建第一个后端接口

今天是我死磕AI应用开发的第二天。昨天我把环境搭好了,Python、IDE、API密钥都齐了,但说实话心里还是虚的——因为我不知道从哪一步开始,才能真正让大模型变成我能掌控的东西,而不是只在网页对话框里聊几句。今天这一整天,我集中做了一件事:把AI应用开发的几个核心问题彻底想明白,并且亲手写出了第一个能跑的后端接口。这篇文章就是Day02的完整笔记,包括AI应用开发学习路线里的关键分岔、我踩进去又爬出来的坑,以及一个可以直接抄走的“最小AI应用”模板。如果你正在学大模型应用开发,或者准备转岗AI应用开发,这篇文章应该能帮你少走一周弯路。

1. 先搞清楚:AI应用开发到底在开发什么

1.1 不是训练模型,而是“使用模型”

我在第一天的笔记里说过一个观点,今天我要再强调一遍:大多数人学AI应用开发,根本不需要去训练模型。我们需要做的是把已经存在的GPT、通义、文心、豆包这类大模型,通过API集成到自己的业务系统里。整个过程更像是“配菜师”而不是“种菜的”——模型是别人种好的菜,我们的工作是怎么把它洗干净、切好、调味,最后端给用户。

听起来简单,但实际操作时很多人容易犯迷糊。我见过一个朋友,上来就研究Transformer结构、微调方法,一个月后还在理论里打转,连一个API请求都没发出去。这不叫AI应用开发,这叫模型训练。真正的AI应用开发,核心是把模型的输入输出接进业务流程,让模型在特定场景下解决具体问题。你需要懂的不一定是数学公式,而是API怎么调、Prompt怎么写、返回的结果怎么解析、出错怎么兜底。

今天我要做的第一件事,就是把这个认知彻底固化下来。我给自己规定了一个“应用开发者视角”:一切从调用开始,一切以需求结束。模型的内部原理,能跑通之后再去补课。

1.2 从“问答”到“Agent”的能力分层

最近AI应用开发领域最火的关键词,非“AI Agent”莫属。今天的热搜里也堆满了AI Agent相关词。但我研究了一圈之后发现,很多人对Agent的理解是模糊的,以为只要调一次大模型接口,再返回结果,就是Agent。这里我先把能力分个层级,方便后续学习对标。

第一层是单轮问答。我给它取名叫“一锤子买卖”。用户说一句话,你把它原封不动发给模型,模型返回一句话,你展示给用户。这是最基础的API调用,但也是最容易被忽略的地基。

第二层是多轮对话加工具调用。模型不再只是“嘴上说说”,它可以去查天气、查数据库、调用外部API,然后把结果用自己的话讲给你听。这就像是给一个知识渊博但不动手的人,装上了手和脚。实现方式通常是让模型识别用户意图,然后你根据意图去执行对应工具,再把结果拼进Prompt里让模型生成最终回答。

第三层才是真正意义上的Agent。模型自己有目标拆解能力:你说“帮我安排一条周末旅游路线”,它会自己规划成几个子任务:查天气、查交通、查景点、查美食,然后依次调用工具,最后汇总成一个完整方案。这个过程中模型扮演的是“策划者”,而代码负责的是“执行平台”。

我的建议是:学习路线必须严格按这个层次走。第一天调通API,第二天实现多轮对话,第三天再加一个简单工具调用,全部跑顺了再碰Agent。直接一步到位学Agent,很容易被模型的“规划幻觉”打崩溃——它看起来是在思考,实际上在瞎编步骤。

1.3 选型思考:为什么我选“大模型API+Python”组合

现在的AI应用开发栈五花八门,有LangChain、LlamaIndex这种框架,有Dify、扣子这类低代码平台,还有各种模型厂商的SDK。我今天实际动手时,没有直接用框架,而是用最原始的requests和Python脚本做了一轮调用。这个选择背后是有原因的。

第一,门槛足够低。只要电脑能装Python,会写一点点HTTP请求,哪怕完全不懂机器学习,也能把核心流程跑通。这样可以把注意力集中在理解“应用架构”上,而不是被框架抽象概念带偏。

第二,生态成熟。无论你接OpenAI兼容接口、通义千问还是豆包,它们的API范式几乎都是“POST一个JSON过去,拿回一个JSON”,差异只在字段名和鉴权方式。当你手写过一次调用之后,再换任何一家厂商,你只需要看文档改请求体就行。

第三,方便排查问题。一旦接口报错或返回内容不对,你能直接看到原始请求和原始响应,能快速定位是哪一步出了问题。如果用框架,报错信息会绕好几层,新手很容易懵。

第四,低代码平台可以辅助快速验证想法。比如热词里提到的“扣子”这类Agent开发平台,特别适合做原型验证,连代码都不用写。但我始终觉得,低代码是结果验证工具,不是学习工具。你只有明白了底层逻辑,才能在低代码平台里合理地编排节点。否则出了问题,你连故障方向都说不清。

2. 动手写代码前必须吃透的几个核心概念

2.1 Prompt工程:你与模型之间的“编程语言”

今天一整天我其实有一半时间都花在调Prompt上。很多人有个误区,认为写Prompt就是随便说句话。实际上,Prompt就是你给程序员的“需求说明书”,你描述得越精准,模型产出的质量越高。

我总结了一套最基础但极其管用的Prompt四要素写法:

  • 角色设定。让模型知道你希望它以什么身份回答问题。比如“你是一名Python性能优化专家”就比“帮我看看代码”效果好得多。
  • 明确指令。告诉模型具体要做什么,不做什么。比如“只输出优化后的代码,不要解释理由”。
  • 提供约束和格式。比如“用JSON返回,字段包括标题、摘要、关键词”。
  • 给出示例。一个两个示例,胜过一百句口头描述。

我拿一个实战例子说明。昨天我让模型写一个冒泡排序算法,我是这么问的:“用Python写冒泡排序。”结果确实返回了代码,但还附带了一大堆解释和测试代码,非常啰嗦。今天我把Prompt改成:“你是一个高效的算法工程师。请用Python实现冒泡排序函数,函数名为bubble_sort,输入是列表,返回值是排序后的新列表。只输出代码,不输出任何解释。参考示例:输入[3,1,2],返回[1,2,3]。”这次输出的代码干净利落,直接就能往文件里贴。

关键在于,模型不是你肚子里的蛔虫,它只能根据你给的文字去猜需求。Prompt写得好,后面所有步骤都轻松;Prompt写不好,你后面写再多解析代码都是在补救。

2.2 上下文管理与Token计算

这一步是新手最容易忽略,但真正决定应用能否落地的环节。先说Token。Token是模型计费和处理的基本单位,可以简单理解成“字片”。中文环境下,1个Token约等于0.5到0.7个汉字,具体看分词方式。模型对所有输入和输出都按Token计量,所以你得有个概念:调一次API,发出去的Prompt越长,花的钱越多,模型的思考负担也越大。

上下文窗口就是模型能记住的Token总量。比如某模型的上下文窗口是128K,你一次性最多能喂给它那么多内容。这本身没什么,关键在于“多轮对话记忆”的实现。很多新手第一次做聊天机器人时,只把当前用户问题发过去,结果模型完全没有记忆,因为他把历史消息全丢了。要实现记忆,你需要把之前的会话历史作为一组消息,连同当前问题一起发给模型。

这里涉及一个经典问题:历史消息不能无限往上堆。当对话超过上下文窗口,或者超过你设置的成本上限时,你需要做截断或者摘要。我今天的实现里写了一个简单策略:只保留最近5轮对话,更早的内容全部丢弃。如果你的业务需要记住更久以前的事,可以定期把历史对话丢给模型做一次总结,把总结放回上下文里代替原始内容。这招叫做“上下文压缩”,是低成本高收益的技巧。

还值得注意一点:你发的每条消息,系统都会附带角色标签,通常有system、user、assistant三种。system用来放全局指令,user是用户输入,assistant是模型之前的输出。上下文管理就是维护好这个三元组的列表。

2.3 模型参数:temperature、top_p、max_tokens

光会发请求还不够,你要知道几个关键参数的含义。举个最直观的例子:temperature控制随机性。数值范围通常是0到2,数值越大,回答越天马行空;数值越小,回答越保守。代码生成、梗概提取这种要求精确的任务,我习惯调到0.2到0.3;写广告语、故事这种创意类任务,我会调到0.8以上。

top_p是核采样参数,控制模型在候选词集合里取多大的概率范围。它和temperature有类似作用,但原理不同。官方文档的建议是,改temperature就别动top_p,改top_p就别动temperature,否则结果会乱。

max_tokens限制生成的最大长度。比如你让模型写一篇文章,如果不设上限,它可能编到天荒地老;但设太小又会截断完整答案。我一般会估算答案长度再加上余量,宁可长一点,不能截断逻辑。

今天我做了一个很重要的实操:把temperature从默认值调到0.3,并且在Prompt里加了“如果不确定就直接说不知道”。这一下子就解决了模型“一本正经胡说八道”的问题。所以遇到模型输出质量差,建议先检查参数和Prompt,而不是立刻换模型。

3. 手把手写第一个AI应用:本地知识问答助手

3.1 项目结构设计

把基础概念过完,就该上手了。我今天的项目是一个“本地知识问答助手”,目标是对接一个在线大模型API,实现多轮对话,并且能通过HTTP接口被前端或其他系统调用。

我没有一上来就搭复杂目录,而是保持一个最小但五脏俱全的结构:

day02/ ├── app.py # 主程序,FastAPI服务 ├── prompt.py # Prompt模板 ├── memory.py # 对话记忆管理 ├── config.py # 配置项 └── requirements.txt # 依赖

为什么要拆成这样?因为每个文件职责单一,后面好扩展。比如以后想换模型,只改config.py和app.py里的调用逻辑;想调Prompt,只动prompt.py。如果你把所有逻辑都堆进一个main.py,后面改起来会非常痛苦。

requirements.txt内容很简单:

fastapi==0.115.0 uvicorn==0.30.0 openai==1.30.0 python-dotenv==1.0.1

注意,这里我用的是openai的SDK,但连接的是兼容OpenAI协议的国内模型服务,只需要改base_url和api_key就行,非常方便。

3.2 用FastAPI包一层HTTP接口

我的目标是跑起来一个服务,让任何客户端都能POST一段文本,然后拿回AI生成的回答。代码如下:

# config.py import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") BASE_URL = os.getenv("BASE_URL", "https://api.openai.com/v1") MODEL = os.getenv("MODEL", "gpt-3.5-turbo-instruct")

密钥绝不能写死在代码里。我吃过这个亏,有一次把测试密钥推到了自己的公开仓库里,半小时后就收到警告邮件说密钥被滥用。所以现在一律用环境变量管理。

主程序:

# app.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from openai import OpenAI import config app = FastAPI() client = OpenAI(api_key=config.API_KEY, base_url=config.BASE_URL) class ChatRequest(BaseModel): message: str class ChatResponse(BaseModel): reply: str @app.post("/chat", response_model=ChatResponse) async def chat(req: ChatRequest): try: resp = client.chat.completions.create( model=config.MODEL, messages=[ {"role": "system", "content": "你是一个简洁的AI助手,回答尽量控制在200字以内。"}, {"role": "user", "content": req.message} ], temperature=0.3, max_tokens=500 ) return ChatResponse(reply=resp.choices[0].message.content) except Exception as e: raise HTTPException(status_code=500, detail=f"模型调用异常: {str(e)}")

启动服务:

uvicorn app:app --host 0.0.0.0 --port 8000

我用curl测试:

curl -X POST http://localhost:8000/chat \ -H "Content-Type: application/json" \ -d '{"message": "用一句话说明什么是Agent"}'

返回结果:

{"reply": "Agent是大语言模型驱动的智能体,能够自主规划任务并调用工具完成复杂目标。"}

到这一步,一个完全没有AI实战经验的人也能跑通的“AI后端”就出现了。很多框架里那些花哨的Agent编排,最底层也是这样一个请求-响应循环。

3.3 加入流式输出与对话记忆

单纯返回完整结果,在网络慢的时候体验很糟糕。用户会看到接口转圈几秒钟,然后突然蹦出整段话。为了优化体验,我加上了流式输出。传输层还是同一个接口,但请求时加上stream=True,然后不断从响应里取增量token,通过FastAPI的StreamingResponse把内容一点一点推给前端。

# 流式请求核心逻辑 stream = client.chat.completions.create( model=config.MODEL, messages=all_messages, stream=True ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: yield delta

同时,我把memory.py里维护的对话列表也接进来。核心代码如下:

# memory.py MAX_HISTORY = 5 class Memory: def __init__(self): self.history = [] def add_user(self, content): self.history.append({"role": "user", "content": content}) def add_assistant(self, content): self.history.append({"role": "assistant", "content": content}) def get_messages(self): # 只保留最近MAX_HISTORY轮完整对话 recent = self.history[-(MAX_HISTORY * 2):] return [{"role": "system", "content": "你是一个知识问答助手。"}] + recent

这样当用户持续提问时,模型就能“记住”前面聊了什么。注意,这里多轮记忆是“伪记忆”,本质上是把历史文本一起发给模型重新推理,并没有真正的状态存储。这个认知很重要,因为到Agent阶段,你还需要引入外部存储和记忆检索,才能实现更复杂的长程规划。

3.4 低代码平台“扣子”快速验证Agent想法

手写代码固然能学原理,但实际工作里有些场景用低代码平台效率更高。我今天下午专门花了一个小时研究热词里反复出现的“扣子开发AI Agent智能体应用”。扣子这类平台最大的价值是让你在拖拽节点、配置插件的过程中,快速验证一个Agent逻辑。

我在扣子上创建了一个“旅行规划助手”Bot。流程是:用户提出需求,Agent节点拆解任务,插件节点搜索景点和天气,最后用大模型节点汇总回答。整个过程不需要写后端代码,模型调用、工具调用、上下文管理都被平台封装好了。对一个刚学AI应用开发的人来说,用扣子搭一个原型来理解Agent的“规划-执行-响应”流程,比硬啃代码要直观得多。

但我也要说句大实话:低代码平台能做70分的产品,很难做到95分的产品。原因是高度封装让你失去对底层行为细节的控制,比如自定义截断策略、精确的异常捕获、深度调优Prompt。所以我给出的建议是:学习阶段,用低代码理解思路;实战阶段,手写代码掌握细节。两者不是二选一,而是前后衔接的关系。

4. 从Demo到能用:避坑与进阶

4.1 效果评测:别靠感觉打分

Demo跑通后,我面临一个新的问题:这个AI助手到底好不好用?如果光靠我自己问几个问题,感觉“还行”,那是不够的。今天我盘了一下自己踩过的坑,整理出一套最低成本的效果评测方法。

第一步,建立测试集。我准备了20个问题,覆盖四类:常见业务问题、边界问题(一句话说不清的问题)、对抗性问题(故意诱导模型出错的问题)、完全超出知识范围的问题。第二步,给每次输出打分,维度包括:准确率、完整性、语气自然度、安全性。每天让同一个模型跑一遍测试集,分数对比就能看出改动是变好还是变坏。这个习惯可能比调参本身更有价值。

这一步千万不能省。很多AI应用真正上线后口碑崩掉,不是因为模型不行,而是因为没做评测,光靠开发者的自我感动。

4.2 AI测试开发:关注鲁棒性和异常场景

既然提到了测试,就必须说说“AI测试开发”这个方向。传统软件测试关注功能逻辑,AI应用测试还要多关注一层:模型输出是概率性的,同样的输入两次结果可能不一样。所以测试不能只断言“返回了什么”,还要设计容错策略。

我今天在代码里加了两个测试用例,用来验证异常输入:

import pytest from fastapi.testclient import TestClient from app import app client = TestClient(app) def test_empty_input_returns_400(): response = client.post("/chat", json={"message": ""}) assert response.status_code == 400 def test_normal_input_returns_200(): response = client.post("/chat", json={"message": "你好"}) assert response.status_code == 200 assert "reply" in response.json()

这只是最原始的用例,真正做AI测试开发还需要覆盖:模型接口超时、第三方API限流、并发请求下是否会串号、用户恶意输入是否会被拦截。这些场景今天我没有全部实现,但先列成清单,后续逐步补充。

4.3 安全与合规:绕不开的底线

我刻意把安全放在最后一部分,不代表它最不重要,而是因为它是所有工作的前提。做一个大模型应用,如果只追求“输出看起来聪明”,不考虑安全,那上线就是给自己埋雷。

几个每天都要对自己喊一遍的原则:

  • 用户输入不要直接拼进系统提示词里而不做隔离。否则用户可以通过“忽略以上指令”等方式劫持你的系统设定。我今天的实现里其实就存在这个隐患,只是开发阶段没触发。正确做法是把用户输入作为独立的user消息传入,而不是拼接进system里。
  • 输出内容需要做敏感词过滤或人工审核机制。尤其是公开面向用户的场景。大模型有时候会生成看似合理但实际有害的内容,单纯靠模型自身安全对齐是不够的。
  • 隐私数据不能发送给外部模型。用户手机号、身份证、内部业务数据,一旦发到第三方模型接口,你无法控制数据流向,这是红线问题。
  • 保留操作日志。谁在什么时间发了什么请求,模型返回了什么,都要有记录。否则出了问题,你连排查的依据都没有。

这些不是空话,而是我见过太多项目因为不做安全控制,上线第二天就收到投诉甚至更严重的后果。所以今天哪怕是写这个最小应用,我也在代码里加了异常日志输出,并且用mock数据测试了明显敏感的输入,确保系统不会被一句话引爆。

5. Day02的复盘与明天计划

今天这一整天的实践,我最大的体会是:AI应用开发没有想象中那么玄,但也绝对不只是“调用一个接口”。它的核心复杂度在于两点,一是把模糊的业务需求翻译成模型能理解的Prompt和上下文结构,二是围绕模型这个“概率引擎”设计出确定性高的工程框架。

我今天踩的最大的坑,是花了一个小时试图让模型“记住”用户之前提到的所有细节,最后发现根本原因是上下文长度不够,而不是模型不开窍。后来我会主动控制对话轮次,才正常起来。这个过程也让我意识到,学习和调试AI应用,最重要的能力是“定位边界”:模型的能力边界在哪里,程序的边界在哪里,你输入的数据边界在哪里。

明天我计划把工具调用跑通,也就是让模型在回答问题时,能够根据用户意图去查询本地文件或者调用一个天气API。这正好是通往AI Agent的关键一步。如果你也在学AI应用开发,我建议你也找一个小的应用场景,比如“AI周报总结助手”或者“AI商品描述生成器”,哪怕只写二十行脚本,也比看十篇教程有用得多。把第一个能跑的小项目挂在你的仓库里,之后的路会越走越顺。

返回列表