OpenAI API 初体验:ChatGPT 背后的接口是什么样的

2022 年 11 月底,ChatGPT 上线,刷屏了所有技术圈的朋友圈。作为工程师,第一反应自然是——这东西能怎么用在项目里? 基础概念 OpenAI 的核心接口是 Chat Completions API,接受一个消息列表,返回模型的回复。 from openai import OpenAI client = OpenAI(api_key="your-api-key") response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "你是一个 Python 专家"}, {"role": "user", "content": "解释一下 Python 的 GIL"} ] ) print(response.choices[0].message.content) 消息列表里有三种角色: system:给模型设定人格和行为准则 user:用户输入 assistant:模型历史回复(多轮对话时需要带上) Token 是什么 模型按 token 计费,而不是按字符。英文大约 4 个字符 = 1 token,中文大约 1-2 个字符 = 1 token。 # 用 tiktoken 计算 token 数 import tiktoken enc = tiktoken.encoding_for_model("gpt-3.5-turbo") tokens = enc.encode("Hello, world!") print(len(tokens)) # 4 max_tokens 控制回复的最大长度,temperature 控制随机性(0 最确定,2 最随机)。 多轮对话的实现 模型本身是无状态的,多轮对话需要客户端维护历史消息: history = [] def chat(user_input): history.append({"role": "user", "content": user_input}) response = client.chat.completions.create( model="gpt-3.5-turbo", messages=history ) reply = response.choices[0].message.content history.append({"role": "assistant", "content": reply}) return reply 历史越长,消耗的 token 越多,成本越高。实际项目里需要做历史截断或摘要。 ...

2022-12-10 · 1 min · Kada Liao

FastAPI 入门:用 Python 快速构建现代 Web API

Django REST Framework 太重,Flask 太裸。FastAPI 在这两者之间找到了一个很好的平衡点。 为什么是 FastAPI 快:基于 Starlette,性能接近 Node.js 自动文档:自动生成 Swagger UI 和 ReDoc 类型驱动:用 Pydantic 做数据校验,写一次模型,校验和文档都有了 原生异步:完整支持 async/await 5 分钟上手 uv pip install fastapi uvicorn # main.py from fastapi import FastAPI app = FastAPI(title="我的 API", version="1.0.0") @app.get("/") def read_root(): return {"message": "Hello, World!"} @app.get("/users/{user_id}") def get_user(user_id: int, include_orders: bool = False): return {"user_id": user_id, "include_orders": include_orders} uvicorn main:app --reload # 访问 http://localhost:8000/docs 看自动生成的文档 Pydantic 模型:请求/响应的核心 from pydantic import BaseModel, EmailStr, Field from datetime import datetime class UserCreate(BaseModel): name: str = Field(..., min_length=2, max_length=50) email: EmailStr age: int = Field(..., ge=0, le=150) class UserResponse(BaseModel): id: int name: str email: str created_at: datetime class Config: from_attributes = True # 支持从 ORM 对象创建 @app.post("/users", response_model=UserResponse, status_code=201) def create_user(user: UserCreate): # FastAPI 自动解析请求体、校验字段、返回时过滤多余字段 db_user = save_to_db(user) return db_user Pydantic 的 Field 支持的校验相当丰富:字符串长度、数字范围、正则表达式……不需要手写校验逻辑。 ...

2022-03-28 · 2 min · Kada Liao

RESTful API 设计规范:我总结的一些原则

在做了几年后端开发之后,我发现 API 设计的好坏对前后端协作效率影响很大。这篇文章把我总结的一些原则写下来。 URL 设计 用名词,不用动词 # 不好 GET /getUser POST /createOrder DELETE /deleteProduct?id=1 # 好 GET /users/{id} POST /orders DELETE /products/{id} 层级关系用路径表达 GET /users/{userId}/orders # 某个用户的所有订单 GET /users/{userId}/orders/{id} # 某个用户的某个订单 用复数名词 GET /users # 不是 /user GET /products # 不是 /product HTTP 方法的语义 方法 语义 幂等 GET 读取资源 是 POST 创建资源 否 PUT 全量替换资源 是 PATCH 部分更新资源 否 DELETE 删除资源 是 幂等意味着重复调用和调用一次效果相同,这对网络重试很重要。 状态码要用对 200 OK - 成功 201 Created - 创建成功(POST 之后返回) 204 No Content - 成功但无响应体(DELETE 常用) 400 Bad Request - 客户端参数错误 401 Unauthorized - 未认证(没登录) 403 Forbidden - 无权限(登录了但没权限) 404 Not Found - 资源不存在 409 Conflict - 资源冲突(如重复创建) 422 Unprocessable Entity - 参数格式正确但业务校验失败 500 Internal Server Error - 服务器内部错误 最常见的错误:把所有错误都返回 200,在响应体里用 code 区分。这让客户端必须解析响应体才能判断是否成功,无法用 HTTP 层面的工具(代理、监控)做处理。 ...

2021-07-14 · 1 min · Kada Liao