Prompt 在 NLP 中的应用——从一条 HTTP 请求说起
Prompt 在 NLP 中的应用——从一条 HTTP 请求说起
前言
NLP(Natural Language Processing,自然语言处理) 听起来很高大上,但放到大模型时代,它可以粗略分成两类事情:
- 文本理解类:情感推断、信息提取、文本分类……给一段文字,让模型"读懂"并输出结论。
- 多模态生成类:文生图、文生视频、图片编辑……输入文字(甚至多张图片),让模型"生成"新的内容。
这两类任务看起来完全不同,但它们共用同一套工作模式:你设计一段 Prompt(提示词),模型根据 Prompt 输出结果。以前做 NLP,每个任务要单独训练一个模型;现在同一个基础大模型,换不同的 Prompt,就能在不同的 NLP 任务之间切换。Prompt 成了人和模型之间的通用接口。
这篇文章以图片生成为例,先看看 Prompt 在多模态任务里长什么样,然后一路拆到底层 HTTP 请求,搞清楚一段 Prompt 到底是怎么送到模型手里的。
一张图片生成 Prompt 长什么样
给模型三张参考图 + 一句文字指令,让它生成一张新图片。
图1:一个女生的照片
图2:一件衣服的照片
图3:一个坐姿的参考图
指令:图1中的女生穿着图2中的衣服,按照图3中的姿势坐下
这就是多模态 Prompt——它的内容不只有文字,还可以包含图片。最终这段 Prompt 在代码里会变成什么样的数据结构?往下看。
首先扒开 SDK 的壳,看一次 LLM API 调用到底长什么样
刚开始接触大模型开发的时候,我们通常会直接用官方 SDK:几行代码,传个 prompt,结果就回来了,很爽。但用久了会好奇——SDK 到底帮我做了什么?如果不调 SDK,我自己能写吗?
这次以阿里云百炼的多模态图片生成接口为例,从 SDK 写法一路拆到最底层的 HTTP 请求,把 LLM API 调用的本质搞清楚。
先看 SDK 写法
假设我们用 DashScope 的 Node.js SDK 来生成一张图片:
import dashscope from 'dashscope';
const res = await dashscope.multimodalGeneration.call({
apiKey: process.env.OPENAI_API_KEY,
model: 'qwen-image-2.0-pro',
input: {
message: [{
role: 'user',
content: [
{ image: 'https://xxx/input1.png' },
{ image: 'https://xxx/input2.png' },
{ image: 'https://xxx/input3.png' },
{ text: '图1中的女生穿着图2中的衣服,按照图3中的姿势坐下' }
]
}]
}
});
很简洁对吧?你只关心两件事:用什么模型、传什么内容。URL 是啥、header 怎么拼、body 怎么序列化——统统不用管。
这其实就是 SDK 的核心价值:把 HTTP 的细节封装掉,让你专注于业务逻辑。
扒掉 SDK,用原生 fetch 写
现在我们不用任何 SDK,用 Node.js 原生的 fetch 来发同样的请求:
import dotenv from 'dotenv';
dotenv.config();
async function generateImage() {
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
const res = await fetch(
'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation',
{
method: 'POST',
//请求头
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${OPENAI_API_KEY}`
},
//请求体
body: JSON.stringify({
model: 'qwen-image-2.0-pro',
input: {
message: [{
role: 'user',
content: [
{ image: 'https://xxx/input1.png' },
{ image: 'https://xxx/input2.png' },
{ image: 'https://xxx/input3.png' },
{ text: '图1中的女生穿着图2中的衣服,按照图3中的姿势坐下' }
]
}]
}
})
}
);
}
代码多了一些,但结构非常清晰,我们会发现SDK版本的model``input.message原封不动的出现在body(请求体)中,只是外面套了一层http请求的外壳。我们来逐块拆解。
一次 LLM API 请求的四个组成部分
不管是 OpenAI、Claude、通义千问,还是文生图、文生视频——只要调的是远程大模型服务,本质上都是一次 HTTP POST 请求。这个请求由以下四个部分组成:
1. URL 地址 —— 请求发给谁
https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation
这是阿里云百炼的多模态生成接口地址。不同厂商的地址不同,比如:
- OpenAI:
https://api.openai.com/v1/chat/completions - 通义千问文本对话又是另一个地址
但形式都一样:一个 HTTPS 的 URL,指向某个 API 端点。
2. method: POST —— 怎么发
method: 'POST'
为什么用 POST 而不是 GET?因为我们要提交的数据(图片链接、文字指令)可能很长,POST 把数据放在 body 里传输,不会像 GET 那样拼在 URL 后面。两个好处:
- 更安全:API Key 和数据都不会暴露在 URL 里
- 容量更大:URL 有长度限制,body 没有
3. headers 请求头 —— 告诉服务端"我是谁、我发的啥"
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${OPENAI_API_KEY}`
}
两个关键字段:
- Content-Type:告诉服务端我发的是 JSON 格式,服务端才知道怎么解析。
- Authorization:身份鉴权。
Bearer后面跟 API Key,服务端校验这个 Key 是否有效、有没有额度。这就是为什么调用 API 需要先去平台申请 Key。
4. body 请求体 —— 真正的"指令"
body: JSON.stringify({
model: 'qwen-image-2.0-pro',
input: {
message: [{
role: 'user',
content: [
{ image: '...' },
{ image: '...' },
{ image: '...' },
{ text: '图1中的模特穿着图2中的衣服,按照图3中的姿势坐下' }
]
}]
}
})
这是整个请求的核心,包含了你要让模型做什么的所有信息:
- model:用哪个模型。这里指定的是通义千问的图片 2.0 Pro 版本。
- input.message:对话消息数组。
role: 'user':表示这是用户发的消息。content:消息内容,这里是一个数组,可以同时包含图片(image)和文字(text)——这就是"多模态"的体现。
注意最后要用 JSON.stringify() 把对象转成 JSON 字符串,因为 HTTP 协议传输的是文本,不是 JavaScript 对象。
SDK、fetch总结
SDK 和原生 fetch 的关系,就像外卖 App 和自己买菜做饭的关系:
- SDK(外卖 App):打开、点餐、等送达。方便,但你不关心菜是怎么做的、骑手怎么送的。
- 原生 fetch(自己做饭):买菜(准备 API Key)→ 看菜谱(查 API 文档里的 URL)→ 下锅(拼 method、headers、body)→ 出锅(等响应)。
初学者建议先用 SDK 快速上手,但理解底层的 HTTP 请求结构有两个好处:
- 排错更方便:报 401 你知道是 API Key 的问题(headers),报 404 你知道是 URL 写错了。
- 不再被 SDK 绑定:换个模型、换个厂商,你不需要再学一套新 SDK,直接看 API 文档找到 URL、拼请求即可。所有 LLM 服务说到底都遵循同一个模式:
总结:Prompt 是接口,HTTP 是通道
回到标题——Prompt 在 NLP 中的应用。
不管是情感推断(发一段文字,让模型判断情绪),还是图片生成(发三张图 + 一句话,让模型出图),工作模式都是一样的:
你设计 Prompt → 拼成 HTTP 请求 → 发给模型 → 模型返回结果
- Prompt 是你和模型之间的"接口":你设计什么样的 Prompt,模型就完成什么样的 NLP 任务。同一套模型,换 Prompt 就能从"情感分析"切换到"图片生成"。
- HTTP 是 Prompt 的"传输通道":不管用 SDK 还是原生 fetch,本质都是把 Prompt 塞进 POST 请求的 body 里,带上 API Key,发到模型的 API 地址。
POST {API地址}
Headers: Content-Type + Authorization
Body: { model, messages }
万变不离其宗。