Prompt 在 NLP 中的应用——从一条 HTTP 请求说起

前言

NLP(Natural Language Processing,自然语言处理) 听起来很高大上,但放到大模型时代,它可以粗略分成两类事情:

  1. 文本理解类:情感推断、信息提取、文本分类……给一段文字,让模型"读懂"并输出结论。
  2. 多模态生成类:文生图、文生视频、图片编辑……输入文字(甚至多张图片),让模型"生成"新的内容。

这两类任务看起来完全不同,但它们共用同一套工作模式:你设计一段 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 请求结构有两个好处:

  1. 排错更方便:报 401 你知道是 API Key 的问题(headers),报 404 你知道是 URL 写错了。
  2. 不再被 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 }

万变不离其宗。