用 Prompt 做 NLP:从零搭建一个情感分析与信息提取系统

前言:传统 NLP 任务------情感分类、信息提取、文本总结------往往需要熟练的机器学习工程师花费数天到数周来训练模型。而大语言模型时代的到来彻底改变了这一切:只需一份精心设计的 Prompt,几分钟就能构建出企业级的 NLP 系统。本文从 ES6 模块化架构搭建开始,用 OpenAI SDK 封装调用层,通过四个实战案例带你掌握 Prompt 驱动的 NLP 开发全流程。


目录

  1. [NLP 的 Prompt 时代](#NLP 的 Prompt 时代 "#%E4%B8%80nlp-%E7%9A%84-prompt-%E6%97%B6%E4%BB%A3")
  2. [ES6 模块化:三层架构搭建](#ES6 模块化:三层架构搭建 "#%E4%BA%8Ces6-%E6%A8%A1%E5%9D%97%E5%8C%96%E4%B8%89%E5%B1%82%E6%9E%B6%E6%9E%84%E6%90%AD%E5%BB%BA")
  3. [LLM 客户端的安全封装](#LLM 客户端的安全封装 "#%E4%B8%89llm-%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E5%AE%89%E5%85%A8%E5%B0%81%E8%A3%85")
  4. 实战一:情感分类
  5. 实战二:结构化信息提取
  6. 实战三:多聚焦文本总结
  7. 实战四:主题推断与批量处理
  8. 总结

一、NLP 的 Prompt 时代

NLP(Natural Language Processing,自然语言处理)曾是机器学习领域最具门槛的方向之一。要搭建一个情感分类系统,过去的标准流程是:标注数据 → 特征工程 → 模型训练 → 调参 → 部署。一个熟练的 ML 工程师可能需要数天到数周。

在大语言模型时代,这一切被简化为一段 Prompt

复制代码
你的任务是将以下产品评论的情感分类为正面或负面。
用一个单词回答。

评论文本:这个熊猫公仔很软很可爱,女儿很喜欢。

模型返回:正面

这不是魔法,而是 Prompt Engineering------用自然语言作为"程序指令",让 LLM 执行分类、提取、总结等 NLP 任务。几分钟替代数周,这是 NLP 的"iPhone 时刻"。


二、ES6 模块化:三层架构搭建

在动手写 Prompt 之前,先把项目架构搭好。ES6(ECMAScript 2015)带来的模块化系统(ESM)让 JavaScript 真正具备了企业级项目的组织能力。

一个清晰的 NLP 项目推荐采用三层架构

flowchart LR A[入口模块<br/>鉴权与路由] --> B[任务模块<br/>NLP 函数封装] --> C[客户端模块<br/>LLM 连接对象]
层级 职责 关键语法
客户端模块 创建并导出 LLM 连接对象 export default
任务模块 封装可复用的 NLP 函数 export async function
入口模块 调用任务函数,串联业务逻辑 import

ES6 模块的核心语法:

javascript 复制代码
// 默认导出 ------ 一个模块只有一个
export default client;

// 命名导出 ------ 可导出多个
export async function getCompletion(prompt) { ... }

// 导入
import client from './client.mjs';           // 接收默认导出
import { getCompletion } from './completion.mjs'; // 接收命名导出

这种组织方式带来了三个明显的好处:可维护 (每个文件职责单一)、可复用 (任务函数可跨项目使用)、可测试(每个模块独立验证)。

ES6 赋能大型项目的其他利器

除了模块化,ES6 还提供了几个让代码更简洁优雅的特性:

解构赋值 ------ 从对象/数组中"无痛"提取值:

javascript 复制代码
// 对象解构
let { name, city } = { name: "姚明", city: "上海" };
console.log(name);  // "姚明"

// 数组解构 + rest 运算符
let [coach, ...players] = ["范甘迪", "姚明", "麦迪", "穆托姆博", "弗朗西斯"];
console.log(coach);    // "范甘迪"
console.log(players);  // ["姚明", "麦迪", "穆托姆博", "弗朗西斯"]

rest / spread 运算符 ------ 收拢与展开:

javascript 复制代码
// rest:收拢剩余项
let [head, ...tail] = [1, 2, 3, 4, 5];  // head=1, tail=[2,3,4,5]

// spread:展开数组
let teamA = ["姚明", "麦迪"];
let teamB = ["科比", "费舍尔"];
let allStars = [...teamA, ...teamB];  // ["姚明","麦迪","科比","费舍尔"]

解构赋值不仅让代码更易读,在性能上也优于逐属性访问------引擎一次性完成属性定位,而非多次查找。


三、LLM 客户端的安全封装

与 LLM 交互的第一步是创建客户端对象。这里有两个关键实践:环境变量管理密钥 ,以及 async/await 处理异步调用

客户端模块

javascript 复制代码
import { OpenAI } from 'openai';
import dotenv from 'dotenv';

dotenv.config();  // 将 .env 文件中的变量注入 process.env

const client = new OpenAI({
    apiKey: process.env.DEEPSEEK_API_KEY,   // 密钥不硬编码
    baseURL: process.env.DEEPSEEK_BASE_URL
});

export default client;

安全红线 :API Key 绝对不能硬编码在源代码中,更不能提交到 Git 仓库。使用 dotenv + .env 文件管理,并确保 .env 已加入 .gitignore。一旦 Key 泄露到公开仓库,攻击者可以在几分钟内将其用于加密货币挖矿等恶意行为。

任务封装模块

javascript 复制代码
import client from './client.mjs';

export async function getCompletion(prompt) {
    const response = await client.chat.completions.create({
        model: process.env.DEEPSEEK_MODEL,
        messages: [
            { role: 'user', content: prompt }
        ]
    });
    return response.choices[0].message.content;
}

这里使用了 Completion 接口------LLM 交互的行业标准。chat.completions.create() 接受 messages 数组,每条消息包含 role(身份)和 content(内容)。对于单轮 NLP 任务,只需一个 user 角色即可。

入口模块

javascript 复制代码
import { getCompletion } from './completion.mjs';

async function main() {
    const prompt = `你的 Prompt 指令...`;
    const response = await getCompletion(prompt);
    console.log(response);
}

main();

入口文件保持极简------只负责导入和调用,具体任务逻辑封装在 Prompt 和任务函数中。


四、实战一:情感分类

情感分类(Sentiment Analysis)是 NLP 最基础也最广泛的应用场景。电商平台用它监控产品口碑,客服系统用它做预警升级,产品团队用它做质检分析。

场景:对一条灯具的产品评论进行情感判断。

javascript 复制代码
const lamp_review = `
我需要一盏漂亮的卧室灯,这款灯具有额外的储物功能,价格也不算太高。
我很快就收到了它。在运输过程中,我们的灯绳断了,但是公司很乐意寄送了一个新的。
几天后就收到了。这款灯很容易组装。我发现少了一个零件,于是联系了他们的客服,
他们很快就给我寄来了缺失的零件!
在我看来,这是一家非常关心顾客和产品的优秀公司!
`;

Prompt 的递进式设计

Prompt 不是一次写成的,而是逐步精化的。下面展示了同一任务从粗到细的 Prompt 演化:

版本 1 ------ 过于开放:

go 复制代码
以下用三个反引号分隔的产品评论的情感是什么?
评论文本:``` {评论} ```

模型可能返回一段冗长的解释,不便于程序处理。

版本 2 ------ 约束输出格式:

go 复制代码
以下用三个反引号分隔的产品评论的情感是什么?
用一个单词回答:正面 或 负面
评论文本:``` {评论} ```

添加"用一个单词回答"后,输出变为可控的 正面负面

版本 3 ------ 更细粒度的情绪识别:

go 复制代码
识别以下产品评论中作者表达的情感。
包含不超过 5 个项目。
将答案格式化为以逗号分隔的单词列表。
评论文本:``` {评论} ```

输出可能为:满意, 感谢, 开心, 信任------比简单的正负面更丰富。

版本 4 ------ 特定情绪检测:

go 复制代码
以下产品评论是否表达了愤怒?给出是或否的答案。
评论文本:``` {评论} ```

这种"是/否"判断在客服预警场景中非常实用------自动标记出愤怒用户,优先处理。

设计要点

原则 说明 示例
使用分隔符 用 ``````````` 或 """ 包裹输入文本 评论文本:```{text}```
约束输出格式 明确要求"一个单词""是或否""逗号分隔列表" 用一个单词回答:正面 或 负面
逐步精化 从宽泛到具体,按需增加约束 情感 → 正负面 → 多标签 → 愤怒检测

五、实战二:结构化信息提取

情感分类的输出是单一标签,但在实际业务中,往往需要从一段文本中同时提取多个字段,并以结构化格式(JSON)返回,方便后续程序处理。

javascript 复制代码
const prompt = `
从评论文本中识别以下项目:
- 情绪(正面或负面)
- 是否表达了愤怒?(是或否)
- 评论者购买的商品
- 制造该物品的公司

评论用三个反引号分隔。
将你的响应格式化为 JSON 对象,以 "sentiment"、"anger"、"product"、"brand" 为键。
如果信息不存在,请使用 "未知" 作为值。
将 anger 格式化为布尔值。
评论文本:\`\`\` ${lamp_review} \`\`\`
`;

模型返回的 JSON:

json 复制代码
{
    "sentiment": "正面",
    "anger": false,
    "product": "卧室灯",
    "brand": "未知"
}

结构化输出的关键技巧

  1. 明确键名和类型:"将 anger 格式化为布尔值"------不给模型自由发挥的空间。
  2. 兜底策略:"如果信息不存在,请使用 '未知'"------防止模型凭空捏造。
  3. JSON 格式指定:直接告诉模型输出 JSON,大多数现代 LLM 都能准确遵循。

信息提取是 RAG(检索增强生成)和 AI Agent 的基础能力。Agent 需要从用户输入中提取参数(商品名、日期、金额),然后调用相应的工具或 API。这个 Prompt 就是 Agent 工具调用链的雏形。


六、实战三:多聚焦文本总结

文本总结(Summarization)是另一个高频 NLP 任务。一段长评论文本,不同角色关注的信息完全不同:

角色 关注点
物流主管 运输速度、包装质量、快递体验
产品经理 价格竞争力、产品质量、尺寸感受
运营编辑 整体亮点、可用于营销的正面描述

同一个产品评论,三份 Prompt,三种聚焦:

通用总结:

go 复制代码
你的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多 30 个词汇。
评论文本:``` {评论} ```

聚焦运输:

go 复制代码
你的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多 30 个词汇,
并且聚焦在产品运输上。
评论文本:``` {评论} ```

聚焦价格和质量:

go 复制代码
你的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多 30 个词汇,
并且聚焦在产品价格和质量上。
评论文本:``` {评论} ```

同一个 Prompt 模板,只改动一句聚焦指令(聚焦在...),输出截然不同------这正是 Prompt 作为"软代码"的魅力:不需要重新训练模型,改一句话就换了任务视角


七、实战四:主题推断与批量处理

主题推断(Topic Inference)能从长文本中自动识别讨论的核心话题。这在舆情监控、客服工单分类、社交媒体分析等场景中非常实用。

场景:对一段政府调查报告进行主题提取。

javascript 复制代码
const story = `
在政府最近进行的一项调查中,要求公共部门的员工对他们所在部门的满意度进行评分。
调查结果显示,NASA 是最受欢迎的部门,满意度为 95%。
一位 NASA 员工 John Smith 表示:
"我对 NASA 排名第一并不感到惊讶。这是一个与了不起的人们共事的好地方。"
调查还显示,社会保障管理局的满意度最低,只有 45%的员工表示满意。
政府承诺解决调查中员工提出的问题,并努力提高所有部门的工作满意度。
`;

const prompt = `
确定以下给定文本中讨论的五个主题。
每个主题用 1-2 个单词概括。
输出时用逗号分隔。
给定文本:${story}
`;

模型输出:员工满意度, NASA, 政府调查, 工作环境, 社会保障

批量处理模式

在真实业务中,往往需要处理大量文本。利用循环 + async/await

javascript 复制代码
const reviews = [review_1, review_2, review_3, review_4];

for (let review of reviews) {
    const prompt = `
    你的任务是从电子商务网站上的产品评论中提取相关信息。
    请对三个反引号之间的评论文本进行概括,最多 20 个字符。
    评论文本:\`\`\` ${review} \`\`\`
    `;
    const response = await getCompletion(prompt);
    console.log(response, '\n');
}

注意循环中使用 await 是串行执行的------适合小批量任务。如果面对数百条以上的文本,可以改用 Promise.all() 并行调用,大幅提升吞吐量。


八、总结

从"需要 ML 工程师数周"到"写一段 Prompt 几分钟完成",NLP 的门槛已经被 LLM 彻底抹平。回顾本文的核心要点:

架构层面:

  1. ES6 模块化(import / export)让项目结构清晰,三层架构(客户端 → 任务 → 入口)职责分明。
  2. dotenv + 环境变量是 API Key 管理的安全基线,密钥永远不硬编码。

Prompt Engineering 层面: 3. 情感分类 ------ 使用分隔符隔离输入、约束输出格式、逐步精化指令。 4. 信息提取 ------ 指定 JSON 键名和类型、提供兜底策略、结构化输出便于程序消费。 5. 文本总结 ------ 通过"聚焦"指令实现同一文本的多视角摘要。 6. 主题推断 ------ 限制主题数量和输出格式,批量处理时注意串行与并行的选择。

一条核心心法把 Prompt 当成代码来迭代。 写代码需要版本管理、单元测试、Code Review------写 Prompt 也应该如此。从一个简单的指令开始,观察输出,逐步加约束,直到结果稳定可靠。


------ NLP 不再是资深人士的专利,而是一个 Prompt 工程师的日常。

相关推荐
暗不需求1 小时前
从路虎汽车小程序看微信小程序开发的最佳实践
前端·javascript·微信小程序
东风破_1 小时前
用原型实现一个队列:JS 面向对象的"不走寻常路"
javascript
向日的葵0061 小时前
vue路由(二)
前端·javascript·vue.js·vue
ejinxian1 小时前
Angular v22 正式发布:Signal Forms、Angular Aria 和 AI 开发工具全面生产化
前端·javascript·angular.js
sugar__salt1 小时前
基于Prompt的NLP项目实战:ES6模块化落地开发指南
javascript·自然语言处理·prompt·es6
小雨下雨的雨1 小时前
通过鸿蒙PC Electron框架技术完成-井字棋游戏 - 实现详解
前端·javascript·游戏·华为·electron·鸿蒙
冰暮流星2 小时前
javascript建立对象之构造函数
开发语言·javascript·ecmascript
小雨下雨的雨2 小时前
基于鸿蒙PC Electron框架技术完成的五子棋游戏 - 技术实现详解
前端·javascript·游戏·华为·electron·鸿蒙
老毛肚2 小时前
jeecgboot vue API 拆分02
前端·javascript·vue.js