AI模型基础认知——不用懂算法,但要懂"怎么用"

38 阅读39分钟

入门基础篇

第2章:AI模型基础认知——不用懂算法,但要懂"怎么用"

本章核心目标:帮助零基础/转岗开发者(特别是Java后端开发者)快速理解AI模型的分类、主流模型特点、调用方式,掌握关键概念,并通过实战案例完成第一个AI接口调用,为后续深入学习打下坚实基础。

image.png

2.1 常见AI模型分类与应用场景

2.1.1 为什么需要了解AI模型分类?

作为AI应用开发工程师,你不需要深入理解模型的训练原理,但必须清楚不同模型能解决什么问题。就像使用数据库时,你需要知道MySQL适合关系型数据、Redis适合缓存,使用AI模型时,你也需要知道什么场景用什么模型。

核心原则选对模型,事半功倍;选错模型,事倍功半。

2.1.2 四大主流AI模型类型

AI模型可以按照处理的数据类型和应用场景,分为四大主流类型:

1. 大语言模型(LLM - Large Language Model)

核心作用:理解和生成自然语言文本。

通俗理解:就像一个"超级智能的聊天机器人",能够理解你的问题,并生成相应的回答。

典型应用场景

  • 智能客服:用户问"如何退款?",模型自动回答退款流程
  • 内容生成:输入产品信息,自动生成产品描述文案
  • 代码生成:输入需求描述,自动生成代码片段
  • 文档总结:输入长文档,自动生成摘要
  • 翻译服务:输入中文,输出英文或其他语言

业务价值

  • 降低人工客服成本
  • 提升内容生产效率
  • 辅助开发人员编码
  • 提升用户体验

代表模型:GPT系列(GPT-3.5、GPT-4、GPT-5.x)、Claude code、文心一言、讯飞星火、ChatGLM

2. 图像识别模型

核心作用:识别和理解图像内容。

通俗理解:就像一个"超级眼睛",能够看懂图片里有什么,识别出物体、文字、人脸等。

典型应用场景

  • 商品识别:电商平台自动识别商品类别、品牌
  • 人脸识别:门禁系统、支付验证
  • OCR文字识别:扫描文档,自动提取文字内容
  • 医疗影像分析:辅助医生识别X光片、CT片中的异常
  • 自动驾驶:识别道路、车辆、行人等

业务价值

  • 自动化商品分类,提升运营效率
  • 提升安全性和用户体验
  • 降低人工录入成本
  • 辅助专业决策

代表模型:YOLO、ResNet、百度OCR、腾讯OCR

3. 语音处理模型

核心作用:处理语音数据,包括语音识别(ASR)和语音合成(TTS)。

通俗理解

  • 语音识别:把你说的话转换成文字(就像"语音输入法")
  • 语音合成:把文字转换成语音(就像"语音播报")

典型应用场景

  • 语音助手:智能音箱、手机语音助手(如Siri、小爱同学)
  • 语音转写:会议录音自动转成文字
  • 语音播报:新闻播报、导航播报
  • 语音客服:电话客服系统,用户说话自动识别并回复

业务价值

  • 提升交互体验,解放双手
  • 降低人工转写成本
  • 提升信息传达效率

代表模型:百度语音、讯飞语音、阿里云语音

4. 语义理解模型

核心作用:理解文本的语义、情感、意图等深层含义。

通俗理解:不仅能理解字面意思,还能理解"言外之意",比如识别用户是表扬还是投诉。

与LLM的区别

  • 语义理解模型:专门针对文本深层语义解析的轻量化模型,针对性强、成本低,适合特定任务(如情感分析、文本分类)
  • LLM(大语言模型):通用文本生成和理解模型,能力全面但成本较高,适合需要生成文本或复杂理解的场景
  • 选择建议:如果只需要做情感分析、文本分类等特定任务,选择语义理解模型更经济;如果需要生成文本或复杂理解,选择LLM

典型应用场景

  • 情感分析:分析用户评论是正面还是负面
  • 意图识别:识别用户是想购买、咨询还是投诉
  • 文本分类:自动将邮件分类为"重要"、"垃圾"等
  • 相似度计算:判断两段文本是否相似(用于去重、推荐等)

业务价值

  • 自动处理用户反馈,提升响应效率
  • 精准理解用户需求,提升转化率
  • 自动化内容分类,提升运营效率

代表模型:BERT、ERNIE、Text2Vec

2.1.3 模型选择决策树

在实际业务中,如何选择合适的模型?可以参考以下决策流程:

image.png

实际案例

案例1:电商智能客服系统

  • 需求:用户问"这个商品适合夏天穿吗?"
  • 模型选择:大语言模型(LLM)
  • 原因:需要理解自然语言问题,并生成回答

案例2:商品图片自动分类

  • 需求:上传商品图片,自动识别商品类别
  • 模型选择:图像识别模型
  • 原因:需要识别图像内容

案例3:语音订单查询

  • 需求:用户通过语音说"查询我的订单",系统识别并查询
  • 模型选择:语音识别模型(ASR)+ 大语言模型(LLM)
  • 原因:先识别语音转文字,再理解意图并查询

2.1.4 本节总结

核心要点

  1. 四大主流模型类型:大语言模型(LLM)、图像识别、语音处理、语义理解
  2. 模型分类边界:语义理解模型是LLM的细分方向,轻量化、针对性强;LLM通用能力强但成本更高
  3. 选择原则:根据业务需求的数据类型和应用场景选择模型
  4. 业务价值:不同模型解决不同问题,选对模型才能发挥最大价值

下一步:了解主流模型的具体特点和适用场景,为实际调用做准备。


2.2 主流模型介绍

2.2.1 为什么需要了解主流模型?

在实际开发中,你需要选择具体的模型来调用。不同的模型有不同的特点、优势和适用场景。了解主流模型,可以帮助你:

  • 快速选型:根据业务需求选择最合适的模型
  • 成本优化:选择性价比最高的模型
  • 开发效率:选择API友好、文档完善的模型

2.2.2 大语言模型(LLM)主流产品

1. GPT系列(OpenAI)

核心特点

  • 模型能力:GPT-3.5、GPT-4、GPT-5.x是目前最先进的大语言模型之一
  • 语言能力:英文能力极强,中文能力良好
  • 适用场景:国际化应用、英文场景、代码生成、复杂推理

API适配性:⭐⭐⭐⭐⭐

  • Java调用友好度:非常友好
  • API文档:完善,有详细的Java示例
  • 认证方式:API Key直接使用,简单直接
  • 调用示例
// OpenAI API调用示例(简化版)
String apiKey = "sk-xxx";
String url = "https://api.openai.com/v1/chat/completions";

Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "gpt-3.5-turbo");
requestBody.put("messages", Arrays.asList(
    Map.of("role", "user", "content", "你好")
));

// 发送HTTP请求...

优势

  • 模型能力强,生成质量高
  • API稳定,响应速度快
  • 文档完善,社区支持好

劣势

  • 国内访问需要代理/VPN
  • 费用相对较高(按Token计费)
  • 中文理解能力略逊于国产模型

适用场景

  • 国际化应用
  • 代码生成、技术文档编写
  • 需要强推理能力的场景

2. 文心一言(百度)

核心特点

  • 模型能力:百度自研的大语言模型,中文理解能力强
  • 语言能力:中文能力极强,英文能力良好
  • 适用场景:国内应用、中文场景、内容生成、智能客服

API适配性:⭐⭐⭐⭐⭐

  • Java调用友好度:非常友好
  • API文档:完善,有详细的Java示例
  • 认证方式:API Key + Secret Key → Access Token(两步认证)
  • 调用示例
// 百度文心一言API调用示例(简化版)
// 第一步:获取Access Token
String accessToken = getAccessToken(apiKey, secretKey);

// 第二步:调用API
String url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + accessToken;

Map<String, Object> requestBody = new HashMap<>();
requestBody.put("messages", Arrays.asList(
    Map.of("role", "user", "content", "你好")
));

// 发送HTTP请求...

优势

  • 国内可直接访问,稳定可靠
  • 中文理解能力强,适合国内业务
  • 有免费额度,成本可控
  • 文档完善,技术支持好

劣势

  • 英文能力略逊于GPT
  • 需要两步认证(相对复杂)

适用场景

  • 国内应用(电商、客服、内容生成等)
  • 中文场景为主的应用
  • 成本敏感的项目

3. 讯飞星火(科大讯飞)

核心特点

  • 模型能力:科大讯飞自研的大语言模型
  • 语言能力:中文能力强,语音相关能力强
  • 适用场景:国内应用、语音交互场景、多模态场景

API适配性:⭐⭐⭐⭐

  • Java调用友好度:友好
  • API文档:完善
  • 认证方式:API Key + Secret Key → Access Token

优势

  • 中文能力强
  • 语音相关能力强(结合讯飞语音技术)
  • 多模态能力(文本+语音+图像)

劣势

  • 模型能力略逊于GPT和文心一言
  • 社区支持相对较少

适用场景

  • 需要语音交互的应用
  • 多模态应用场景

4. ChatGLM(智谱AI)

核心特点

  • 模型能力:开源的大语言模型,可本地部署
  • 语言能力:中文能力良好
  • 适用场景:需要本地部署的场景、数据安全要求高的场景

API适配性:⭐⭐⭐

  • Java调用友好度:中等(需要本地部署)
  • API文档:有文档,但需要自行部署
  • 认证方式:本地部署,无需API Key

优势

  • 可本地部署,数据安全
  • 开源免费
  • 中文能力良好

劣势

  • 需要自行部署和维护
  • 模型能力略逊于商业模型
  • 对硬件要求较高

适用场景

  • 数据安全要求高的场景(金融、医疗等)
  • 需要离线使用的场景
  • 成本敏感且有能力维护的场景

2.2.3 图像生成模型

Stable Diffusion

核心特点

  • 模型能力:根据文本描述生成图像
  • 适用场景:内容创作、设计辅助、图像生成

API适配性:⭐⭐⭐

  • Java调用友好度:中等(需要自行部署或使用第三方服务)
  • API文档:有文档,但需要自行部署
  • 认证方式:根据部署方式而定

优势

  • 开源免费
  • 生成质量高
  • 可本地部署

劣势

  • 需要自行部署和维护
  • 对硬件要求高(需要GPU)
  • 生成速度较慢

适用场景

  • 内容创作平台
  • 设计辅助工具
  • 需要大量图像生成的场景

2.2.4 模型选择建议

选择决策表

场景推荐模型原因
国内中小项目(免费)文心一言(免费额度)满足基础需求,成本为0
国内大型项目(付费)文心一言(商用版)更高QPS、更稳定,有企业级技术支持
国内应用,中文为主文心一言国内访问稳定,中文能力强,成本可控
国际化应用,英文为主GPT系列英文能力强,模型先进
代码生成GPT系列代码生成能力强
成本敏感,国内应用文心一言有免费额度,成本低
数据安全要求高(金融/医疗)ChatGLM(本地部署)可本地部署,数据不出域,符合合规要求
语音交互场景讯飞星火语音能力强
图像生成Stable Diffusion开源免费,质量高

Java开发者优先推荐

  1. 文心一言:国内访问稳定,API友好,文档完善,适合大多数国内业务场景
  2. GPT系列:如果业务面向国际化,或需要强代码生成能力,优先选择GPT

2.2.5 本节总结

核心要点

  1. 主流LLM模型:GPT系列、文心一言、讯飞星火、ChatGLM各有特点
  2. 选择原则:根据业务场景(国内/国际、中文/英文)、成本、数据安全要求选择
  3. Java开发者推荐:国内应用优先选择文心一言,国际化应用选择GPT系列

下一步:了解模型调用的两种核心方式,为实际开发做准备。


2.3 模型调用的两种核心方式

2.3.1 为什么需要了解调用方式?

在实际开发中,你需要决定如何调用AI模型。不同的调用方式有不同的优缺点,选择合适的方式,可以:

  • 降低成本:选择性价比最高的调用方式
  • 保障安全:根据数据安全要求选择调用方式
  • 提升效率:选择最适合业务场景的调用方式

2.3.2 方式一:API调用(公有云)

什么是API调用?

通俗理解:就像使用第三方服务(如短信服务、支付服务),你通过HTTP请求调用AI平台的API,AI平台返回结果。

核心流程

image.png

API调用的优势

  1. 零部署成本:不需要购买服务器、GPU等硬件
  2. 快速接入:申请API Key即可使用,几分钟就能接入
  3. 自动升级:AI平台会自动升级模型,你无需关心
  4. 按需付费:按使用量付费,成本可控
  5. 稳定可靠:AI平台提供高可用服务,稳定性有保障

API调用的劣势

  1. 数据出域:数据需要发送到AI平台,可能存在数据安全风险
  2. 依赖网络:需要稳定的网络连接
  3. 成本累积:大量使用时,成本可能较高
  4. 功能受限:受限于AI平台提供的功能,无法自定义

适用场景

  • 大多数业务场景:智能客服、内容生成、文本理解等
  • 快速上线:需要快速接入AI能力的项目
  • 成本可控:使用量不大,或愿意按需付费的场景
  • 数据安全要求不高:不涉及敏感数据的场景

Java实现示例

@Service
public class AIService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 调用OpenAI API(示例)
     */
    public String callOpenAI(String question) {
        String url = "https://api.openai.com/v1/chat/completions";
        String apiKey = "sk-xxx"; // 从配置文件读取
        
        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        
        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", question)
        ));
        
        // 发送请求
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        Map<String, Object> response = restTemplate.postForObject(url, request, Map.class);
        
        // 解析响应
        List<Map> choices = (List<Map>) ((Map) ((List) response.get("choices")).get(0)).get("message");
        return (String) choices.get("content");
    }
    
    /**
     * 调用百度文心一言API(示例)
     */
    public String callWenxin(String question) {
        // 第一步:获取Access Token
        String accessToken = getAccessToken();
        
        // 第二步:调用API
        String url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + accessToken;
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", question)
        ));
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        
        Map<String, Object> response = restTemplate.postForObject(url, request, Map.class);
        
        // 解析响应
        return (String) response.get("result");
    }
    
    /**
     * 获取百度Access Token
     */
    private String getAccessToken() {
        String url = "https://aip.baidubce.com/oauth/2.0/token";
        String apiKey = "xxx"; // 从配置文件读取
        String secretKey = "xxx"; // 从配置文件读取
        
        String params = "grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey;
        Map<String, Object> response = restTemplate.postForObject(url + "?" + params, null, Map.class);
        
        return (String) response.get("access_token");
    }
}

2.3.3 方式二:本地化部署调用(私有模型)

什么是本地化部署?

通俗理解:就像自己搭建数据库服务器,你在自己的服务器上部署AI模型,通过内网调用。

核心流程

你的应用 → 内网HTTP请求 → 本地AI模型服务 → AI模型处理 → 返回结果 → 你的应用

本地化部署的优势

  1. 数据安全:数据不出域,完全可控
  2. 成本可控:大量使用时,成本可能更低(一次性投入)
  3. 可定制:可以自定义模型、参数等
  4. 离线可用:不依赖外网,可以离线使用
  5. 无API限制:不受AI平台的QPS、Token等限制

本地化部署的劣势

  1. 部署复杂:需要购买服务器、GPU,部署和维护成本高
  2. 技术要求高:需要了解模型部署、运维等技术
  3. 模型更新慢:需要手动更新模型,无法自动升级
  4. 初始成本高:需要一次性投入硬件成本

适用场景

  • 数据安全要求高:金融、医疗、政府等敏感数据场景
  • 大量使用:使用量非常大,本地部署成本更低
  • 离线场景:需要离线使用的场景
  • 定制需求:需要自定义模型、参数的场景

Java实现示例

@Service
public class LocalAIService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 调用本地部署的AI模型(示例)
     * 假设本地部署了ChatGLM模型,提供HTTP API
     */
    public String callLocalAI(String question) {
        // 本地模型服务的地址(内网地址)
        String url = "http://localhost:8000/v1/chat/completions";
        
        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "chatglm-6b");
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", question)
        ));
        
        // 发送请求(内网请求,无需认证)
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        
        Map<String, Object> response = restTemplate.postForObject(url, request, Map.class);
        
        // 解析响应
        List<Map> choices = (List<Map>) ((Map) ((List) response.get("choices")).get(0)).get("message");
        return (String) choices.get("content");
    }
}

本地部署架构示例

┌─────────────┐
│  你的应用    │
│  (Java)     │
└──────┬──────┘
       │ HTTP请求(内网)
       ▼
┌─────────────┐
│  AI模型服务  │
│  (Python)   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  AI模型文件  │
│  (GPU服务器) │
└─────────────┘

本地部署核心步骤(以ChatGLM为例)

  1. 环境准备

    • 安装Python 3.8+、PyTorch 1.12+
    • 安装CUDA(如果使用GPU)
    • 推荐使用conda管理Python环境
  2. 克隆仓库

    git clone https://github.com/THUDM/ChatGLM-6B.git
    cd ChatGLM-6B
    
  3. 安装依赖

    pip install -r requirements.txt
    
  4. 下载模型文件

    • 从Hugging Face下载ChatGLM-6B模型文件
    • 配置模型路径
  5. 启动API服务

    python api.py --port 8000 --model-path /path/to/chatglm-6b
    
  6. 验证服务

    curl http://localhost:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{"model": "chatglm-6b", "messages": [{"role": "user", "content": "你好"}]}'
    

注意事项

  • ⚠️ 硬件要求:ChatGLM-6B至少需要16GB内存,推荐使用GPU加速
  • ⚠️ 模型文件:模型文件较大(约12GB),需要足够的磁盘空间
  • 生产环境:建议使用Docker容器化部署,便于管理和扩展

2.3.4 两种方式对比

维度API调用(公有云)本地化部署(私有模型)
部署成本零成本需要服务器、GPU,成本高
接入速度几分钟几天到几周
数据安全数据出域数据不出域,安全
使用成本按量付费一次性投入,后续成本低
技术要求低(HTTP调用)高(需要部署、运维)
稳定性AI平台保障需要自己保障
适用场景大多数业务场景数据安全要求高、大量使用

2.3.5 选择建议

决策流程

image.png

Java开发者建议

  1. 优先选择API调用:对于大多数业务场景,API调用是最佳选择
  2. 特殊情况选择本地部署:只有在数据安全要求极高、使用量非常大、有专业团队维护的情况下,才考虑本地部署

2.3.6 本节总结

核心要点

  1. 两种调用方式:API调用(公有云)和本地化部署(私有模型)
  2. 选择原则:根据数据安全要求、使用量、成本、技术要求选择
  3. Java开发者建议:优先选择API调用,特殊情况才考虑本地部署

下一步:了解AI模型调用的关键概念,为实际调用做准备。


2.4 关键概念扫盲

2.4.1 为什么需要了解这些概念?

在实际调用AI模型API时,你会遇到很多专业术语。理解这些概念,可以帮助你:

  • 正确配置参数:理解参数含义,才能正确配置
  • 优化调用效果:通过调整参数,优化AI模型的输出效果
  • 控制成本:理解计费方式,控制调用成本
  • 排查问题:遇到问题时,能快速定位原因

2.4.2 API Key(API密钥)

什么是API Key?

通俗理解:就像你的"身份证",用来证明你有权限调用AI平台的API。

作用

  • 身份认证:AI平台通过API Key识别你的身份
  • 权限控制:不同的API Key可能有不同的权限(如免费额度、付费额度)
  • 计费统计:AI平台通过API Key统计你的使用量并计费

使用方式

// 方式1:放在请求头中(推荐)
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(apiKey); // OpenAI使用这种方式

// 方式2:放在URL参数中
String url = "https://api.example.com/v1/chat?api_key=" + apiKey;

// 方式3:放在请求体中
requestBody.put("api_key", apiKey);

安全注意事项

  • ⚠️ 不要提交到代码仓库:API Key是敏感信息,不要提交到Git
  • 使用环境变量或配置文件:将API Key放在环境变量或配置文件中
  • 定期更换:定期更换API Key,提升安全性

Java最佳实践

// 方式1:使用环境变量(推荐,开发环境)
String apiKey = System.getenv("OPENAI_API_KEY");

// 方式2:使用配置文件(application.yml,开发/测试环境)
@Value("${ai.openai.api-key}")
private String apiKey;

// 方式3:使用配置类
@Configuration
public class AIConfig {
    @Value("${ai.openai.api-key}")
    private String apiKey;
    
    public String getApiKey() {
        return apiKey;
    }
}

生产环境API Key安全存储方案

方案1:使用Jasypt加密配置文件(推荐)

  1. 添加依赖(pom.xml):
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>
  1. 配置文件(application.yml):
ai:
  openai:
    api-key: ENC(加密后的字符串)  # 使用Jasypt加密后的API Key
  1. 启动时指定加密密钥
java -jar app.jar --jasypt.encryptor.password=你的加密密钥
  1. 加密API Key的命令
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
  input="sk-your-api-key" \
  password=你的加密密钥 \
  algorithm=PBEWithMD5AndDES

方案2:使用Spring Cloud Config(微服务架构)

将API Key存储在配置中心(如Nacos、Consul),配置中心负责加密存储和安全管理。

方案3:使用密钥管理服务(KMS)

对于大型企业,可以使用云服务商的密钥管理服务(如阿里云KMS、AWS KMS),通过API动态获取API Key。

2.4.3 Token(令牌)

什么是Token?

通俗理解:Token是AI模型处理文本的基本单位,可以理解为"词片段"。

重要概念

  • 输入Token:你发送给AI模型的文本会被切分成Token
  • 输出Token:AI模型生成的文本也会被切分成Token
  • Token数量:通常1个Token ≈ 0.75个英文单词 ≈ 1-2个中文字符

为什么重要?

  • 计费依据:大多数AI平台按Token数量计费
  • 长度限制:每个模型都有最大Token限制(上下文窗口)

Token计算示例

输入文本:"你好,请介绍一下Java"
Token数量:约8-10个Token(中文)

输入文本:"Hello, please introduce Java"
Token数量:约6-8个Token(英文)

Java代码示例

方式1:使用官方Token计算API(推荐,精准)

import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.*;

/**
 * Token计算服务(使用OpenAI官方API)
 */
@Service
public class TokenCountService {
    
    private final RestTemplate restTemplate = new RestTemplate();
    private static final String TOKEN_COUNT_URL = "https://api.openai.com/v1/chat/completions";
    
    /**
     * 使用OpenAI API精准计算Token数量
     * 注意:这需要调用一次API,会产生少量费用
     */
    public int countTokens(String text, String apiKey) {
        // 构建一个最小请求来获取Token数量
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", text)
        ));
        // 设置max_tokens为1,避免实际生成内容
        requestBody.put("max_tokens", 1);
        
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        ResponseEntity<Map> response = restTemplate.postForEntity(TOKEN_COUNT_URL, request, Map.class);
        
        // 从响应中获取Token数量
        Map<String, Object> usage = (Map<String, Object>) response.getBody().get("usage");
        return (Integer) usage.get("prompt_tokens");
    }
}

方式2:使用tiktoken库(Java版本,离线计算)

// 注意:需要添加tiktoken-java依赖
// <dependency>
//     <groupId>com.knuddels</groupId>
//     <artifactId>jtokkit</artifactId>
//     <version>1.0.0</version>
// </dependency>

import com.knuddels.jtokkit.Encodings;
import com.knuddels.jtokkit.api.Encoding;
import com.knuddels.jtokkit.api.EncodingType;

public class TokenCountService {
    
    private static final Encoding encoding = Encodings.newDefaultEncodingRegistry()
        .getEncoding(EncodingType.CL100K_BASE); // GPT-3.5/GPT-4使用的编码
    
    /**
     * 离线计算Token数量(无需调用API,免费)
     */
    public int countTokens(String text) {
        return encoding.countTokens(text);
    }
}

方式3:粗略估算(仅用于快速估算,不精准)

public class TokenExample {
    /**
     * 估算Token数量(简化版,仅用于快速估算)
     */
    public int estimateTokenCount(String text) {
        // 中文:1个字符 ≈ 1-2个Token
        // 英文:1个单词 ≈ 1.3个Token
        // 这里只是粗略估算
        int chineseChars = countChineseChars(text);
        int englishWords = countEnglishWords(text);
        
        return chineseChars * 1.5 + englishWords * 1.3;
    }
    
    private int countChineseChars(String text) {
        // 统计中文字符数量
        return (int) text.chars().filter(c -> c >= 0x4E00 && c <= 0x9FFF).count();
    }
    
    private int countEnglishWords(String text) {
        // 统计英文单词数量
        return text.split("\\s+").length;
    }
}

选择建议

  • 精准计算:使用官方API或tiktoken库(推荐生产环境)
  • 快速估算:使用粗略估算方法(仅用于开发测试)

注意

  • OpenAI提供了Token计算API,但调用会产生少量费用
  • 百度文心一言的Token计算方式与OpenAI类似,可以通过API响应中的usage字段获取实际Token数量
  • 对于Java开发者,推荐使用tiktoken-java库进行离线Token计算,无需调用API

2.4.4 QPS(每秒查询数)

什么是QPS?

通俗理解:QPS(Queries Per Second)表示每秒可以发送多少个请求。

作用

  • 限流控制:AI平台通过QPS限制,防止单个用户占用过多资源
  • 性能指标:QPS越高,说明API性能越好

常见QPS限制

  • 免费额度:通常QPS较低(如5 QPS)
  • 付费额度:QPS较高(如50 QPS、100 QPS)

Java代码示例

import com.google.common.util.concurrent.RateLimiter;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * AI服务(带QPS限流和重试机制)
 */
@Service
public class AIServiceWithRateLimit {
    
    // 使用RateLimiter控制QPS(Google Guava库)
    private final RateLimiter rateLimiter = RateLimiter.create(5.0); // 5 QPS
    private final RestTemplate restTemplate = new RestTemplate();
    private static final int MAX_RETRIES = 3;
    
    /**
     * 调用AI API,带QPS限流和重试机制
     */
    public String callAI(String question) {
        int retryCount = 0;
        
        while (retryCount < MAX_RETRIES) {
            try {
                // 等待获取许可(如果超过QPS限制,会阻塞等待)
                rateLimiter.acquire();
                
                // 调用AI API
                return callAIAPI(question);
                
            } catch (HttpClientErrorException.TooManyRequests e) {
                // 429错误:超过QPS限制
                retryCount++;
                if (retryCount >= MAX_RETRIES) {
                    throw new RuntimeException("超过最大重试次数,QPS限制仍未解除", e);
                }
                
                // 指数退避重试(等待时间递增:1s, 2s, 4s)
                try {
                    long waitTime = 1000L * (1L << retryCount);
                    Thread.sleep(waitTime);
                    System.out.println("QPS限流,等待" + waitTime + "ms后重试,第" + retryCount + "次");
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("重试等待被中断", ie);
                }
                
            } catch (Exception e) {
                // 其他异常直接抛出
                throw new RuntimeException("调用AI API失败", e);
            }
        }
        
        throw new RuntimeException("调用AI API失败,已重试" + MAX_RETRIES + "次");
    }
    
    /**
     * 实际的API调用
     */
    private String callAIAPI(String question) {
        String url = "https://api.openai.com/v1/chat/completions";
        String apiKey = "sk-xxx"; // 从配置读取
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", question)
        ));
        
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        ResponseEntity<Map> response = restTemplate.exchange(
            url, HttpMethod.POST, request, Map.class
        );
        
        // 解析响应...
        return "AI响应";
    }
}

注意事项

  • ⚠️ 不要超过QPS限制:超过限制会导致请求失败(429错误)
  • 合理控制并发:使用线程池、限流器等工具控制并发
  • 处理限流异常:当遇到限流时,应该重试(指数退避)或提示用户
  • 监控QPS使用:记录QPS使用情况,及时调整限流策略

2.4.5 上下文窗口(Context Window)

什么是上下文窗口?

通俗理解:上下文窗口是AI模型能"记住"的最大文本长度,就像人的"短期记忆容量"。

作用

  • 限制输入长度:超过上下文窗口的文本会被截断
  • 影响理解能力:上下文窗口越大,AI模型能理解的上下文越多

常见上下文窗口大小

  • GPT-3.5:4096 Token(约3000个英文单词)
  • GPT-4:8192 Token(约6000个英文单词)
  • 文心一言:约2000-4000 Token(根据模型版本不同)

Java代码示例

@Service
public class AIServiceWithContextLimit {
    
    private static final int MAX_CONTEXT_TOKENS = 4096; // GPT-3.5的上下文窗口
    
    /**
     * 检查并截断文本,确保不超过上下文窗口
     */
    public String truncateText(String text, int maxTokens) {
        // 估算Token数量(简化版)
        int estimatedTokens = estimateTokenCount(text);
        
        if (estimatedTokens <= maxTokens) {
            return text;
        }
        
        // 如果超过限制,截断文本
        // 注意:实际项目中应该使用AI平台的Token计算API
        int maxChars = (int) (maxTokens * 0.75); // 粗略估算
        return text.substring(0, Math.min(maxChars, text.length()));
    }
    
    /**
     * 调用AI API,自动处理上下文窗口限制
     */
    public String callAIWithContext(String question, String context) {
        // 构建完整的提示词
        String fullPrompt = context + "\n\n问题:" + question;
        
        // 检查并截断
        String truncatedPrompt = truncateText(fullPrompt, MAX_CONTEXT_TOKENS);
        
        // 调用AI API
        return callAIAPI(truncatedPrompt);
    }
    
    private int estimateTokenCount(String text) {
        // 简化的Token估算(实际应该调用AI平台的API)
        return (int) (text.length() * 1.5);
    }
    
    private String callAIAPI(String prompt) {
        // 实际的API调用代码
        // ...
        return "AI响应";
    }
}

注意事项

  • ⚠️ 不要超过上下文窗口:超过限制会导致请求失败
  • 合理组织提示词:将重要信息放在前面,避免被截断
  • 分批处理长文本:对于超长文本,可以分批处理

2.4.6 Temperature参数(温度参数)

什么是Temperature?

通俗理解:Temperature控制AI模型生成内容的"随机性"或"创造性"。

参数范围:通常是0.0到2.0之间

参数效果

  • Temperature = 0.0:最保守,生成内容最确定、最一致(适合事实性回答)
  • Temperature = 0.7:平衡,既有创造性又有准确性(大多数场景的默认值)
  • Temperature = 1.0:标准随机性
  • Temperature = 2.0:最随机,生成内容最有创造性(适合创意写作)

实际效果对比

问题:"请介绍Java的特点"

Temperature = 0.0

Java是一种面向对象的编程语言,具有跨平台、安全性高、易于学习等特点。

Temperature = 0.7

Java是一种广泛使用的编程语言,具有以下特点:1. 跨平台性,一次编写到处运行;2. 面向对象,代码结构清晰;3. 丰富的生态系统...

Temperature = 2.0

Java就像一位多才多艺的艺术家,它不仅能编写企业级应用,还能开发移动应用。它的跨平台特性让它成为了程序员的最爱...

Java代码示例

@Service
public class AIServiceWithTemperature {
    
    /**
     * 调用AI API,支持Temperature参数
     */
    public String callAI(String question, double temperature) {
        String url = "https://api.openai.com/v1/chat/completions";
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        requestBody.put("temperature", temperature); // 设置Temperature参数
        requestBody.put("messages", Arrays.asList(
            Map.of("role", "user", "content", question)
        ));
        
        // 发送请求...
        return "AI响应";
    }
    
    /**
     * 不同场景的Temperature推荐值
     */
    public String callAIForScenario(String question, String scenario) {
        double temperature;
        
        switch (scenario) {
            case "factual": // 事实性回答
                temperature = 0.0;
                break;
            case "creative": // 创意写作
                temperature = 1.5;
                break;
            case "balanced": // 平衡场景(默认)
            default:
                temperature = 0.7;
                break;
        }
        
        return callAI(question, temperature);
    }
}

选择建议

  • 事实性回答(如客服问答):Temperature = 0.0 - 0.3
  • 一般对话(如智能助手):Temperature = 0.7 - 1.0
  • 创意写作(如文案生成):Temperature = 1.0 - 1.5

2.4.7 其他重要概念

Max Tokens(最大输出Token数)

作用:限制AI模型生成的最大Token数量。

使用场景

  • 控制生成内容的长度
  • 控制成本(输出Token也会计费)

Java代码示例

requestBody.put("max_tokens", 500); // 最多生成500个Token

Top P(核采样)

作用:控制AI模型从哪些候选词中选择(类似Temperature,但方法不同)。

参数范围:0.0到1.0之间

使用建议

  • 通常与Temperature配合使用
  • 大多数场景使用默认值即可

Stop Sequences(停止序列)

作用:当AI模型生成特定文本时,停止生成。

使用场景

  • 控制生成内容的格式
  • 防止生成不需要的内容

Java代码示例

requestBody.put("stop", Arrays.asList("\n\n", "问题:")); // 遇到这些文本时停止生成

2.4.8 术语对照表

为确保术语一致性,以下是本章核心术语的统一表述:

术语英文说明首次出现位置
API密钥API Key用于身份认证的密钥2.4.2
令牌Token文本处理的基本单位2.4.3
每秒查询数QPS (Queries Per Second)每秒可发送的请求数2.4.4
上下文窗口Context WindowAI模型能处理的最大文本长度2.4.5
温度参数Temperature控制生成内容的随机性2.4.6
最大输出Token数Max Tokens限制AI生成的最大Token数量2.4.7

注意:本章中所有术语均使用上述统一表述,避免混用"上下文长度"、"上下文窗口"等不同说法。

2.4.9 本节总结

核心要点

  1. API Key(API密钥):身份认证和计费依据,需要妥善保管,生产环境使用加密存储
  2. Token(令牌):文本处理的基本单位,是计费依据,可通过官方API或tiktoken库精准计算
  3. QPS(每秒查询数):需要控制并发避免超过限制,遇到限流时应重试(指数退避)
  4. 上下文窗口(Context Window):AI模型能处理的最大文本长度,超过会被截断
  5. Temperature(温度参数):控制生成内容的随机性,根据场景选择合适的值

参数选择速查表

场景TemperatureMax Tokens说明
事实性回答0.0-0.3200-500客服、问答
一般对话0.7-1.0500-1000智能助手
创意写作1.0-1.51000-2000文案生成
代码生成0.0-0.3500-2000代码补全

下一步:通过实战案例,完成第一个AI接口调用。


2.5 小实战:用Postman调用第一个AI接口

2.5.1 实战目标

通过本实战,你将:

  1. 掌握Postman调用AI API的完整流程
  2. 理解AI API的请求和响应格式
  3. 学会用Java代码调用AI API
  4. 具备独立调用AI接口的能力

2.5.2 准备工作

前置条件

  • ✅ Postman已安装
  • ✅ OpenAI API Key已申请(或百度文心一言API Key)
  • ✅ 基本了解HTTP请求和JSON格式

如果还没有API Key

2.5.3 实战案例:调用OpenAI API(文生文)

步骤1:打开Postman,创建新请求

  1. 打开Postman
  2. 点击"New" → "HTTP Request"
  3. 请求方法选择"POST"
  4. URL输入:https://api.openai.com/v1/chat/completions

步骤2:配置请求头(Headers)

在Headers标签页中添加:

KeyValue
Content-Typeapplication/json
AuthorizationBearer sk-your-api-key-here

注意:将sk-your-api-key-here替换为你的实际API Key。

步骤3:配置请求体(Body)

  1. 选择"Body"标签页
  2. 选择"raw"和"JSON"格式
  3. 输入以下JSON内容:
{
  "model": "gpt-3.5-turbo",
  "messages": [
    {
      "role": "user",
      "content": "你好,请用一句话介绍Java编程语言"
    }
  ],
  "temperature": 0.7,
  "max_tokens": 200
}

参数说明

  • model:使用的模型名称(gpt-3.5-turbo是性价比最高的模型)
  • messages:对话消息列表
    • role:角色(user表示用户,assistant表示AI助手)
    • content:消息内容
  • temperature:温度参数(0.7是平衡值)
  • max_tokens:最大输出Token数(200表示最多生成约150个中文字符)

步骤4:发送请求

  1. 点击"Send"按钮
  2. 等待响应(通常几秒钟)

步骤5:查看响应结果

成功响应示例

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "gpt-3.5-turbo-0125",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Java是一种面向对象的编程语言,具有跨平台、安全性高、易于学习等特点,广泛应用于企业级应用开发。"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 35,
    "total_tokens": 55
  }
}

响应字段说明

  • choices[0].message.content:AI生成的回答(这是你需要的内容)
  • usage:Token使用情况
    • prompt_tokens:输入Token数(20个)
    • completion_tokens:输出Token数(35个)
    • total_tokens:总Token数(55个)

步骤6:解析响应结果

核心内容提取

choices[0].message.content = "Java是一种面向对象的编程语言..."

这就是AI生成的回答,你可以在应用中直接使用。

2.5.4 实战案例:调用百度文心一言API(国内开发者推荐)

步骤1:获取Access Token

重要:百度文心一言需要两步认证,先获取Access Token,再调用API。

  1. 打开Postman,创建新请求
  2. 请求方法选择"POST"
  3. URL输入:https://aip.baidubce.com/oauth/2.0/token
  4. 在Params标签页添加参数:
KeyValue
grant_typeclient_credentials
client_id你的API Key
client_secret你的Secret Key
  1. 点击"Send",获取Access Token

响应示例

{
  "access_token": "24.xxx.xxx",
  "expires_in": 2592000
}

注意:Access Token有效期为30天,需要缓存并定期刷新。

步骤2:调用文心一言API

  1. 创建新请求
  2. 请求方法选择"POST"
  3. URL输入:https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=你的Access Token
  4. 在Headers标签页添加:
KeyValue
Content-Typeapplication/json
  1. 在Body标签页(raw + JSON)输入:
{
  "messages": [
    {
      "role": "user",
      "content": "你好,请用一句话介绍Java编程语言"
    }
  ],
  "temperature": 0.7,
  "max_output_tokens": 200
}

参数说明

  • messages:对话消息列表(格式与OpenAI类似)
  • temperature:温度参数(0.7是平衡值)
  • max_output_tokens:最大输出Token数(注意:文心一言使用max_output_tokens而非max_tokens

步骤3:查看响应结果

成功响应示例

{
  "id": "as-xxx",
  "object": "chat.completion",
  "created": 1234567890,
  "result": "Java是一种面向对象的编程语言,具有跨平台、安全性高、易于学习等特点,广泛应用于企业级应用开发。",
  "usage": {
    "prompt_tokens": 20,
    "completion_tokens": 35,
    "total_tokens": 55
  }
}

响应字段说明

  • result:AI生成的回答(注意:文心一言直接返回result字段,而非choices[0].message.content
  • usage:Token使用情况

步骤4:Java代码实现

package com.example.ai.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 百度文心一言API调用服务
 */
@Service
public class WenxinService {
    
    @Value("${ai.wenxin.api-key}")
    private String apiKey;
    
    @Value("${ai.wenxin.secret-key}")
    private String secretKey;
    
    private final RestTemplate restTemplate = new RestTemplate();
    private String cachedAccessToken;
    private long tokenExpireTime;
    
    /**
     * 获取Access Token(带缓存)
     */
    private String getAccessToken() {
        // 如果Token未过期,直接返回缓存的Token
        if (cachedAccessToken != null && System.currentTimeMillis() < tokenExpireTime) {
            return cachedAccessToken;
        }
        
        // 获取新的Access Token
        String url = "https://aip.baidubce.com/oauth/2.0/token";
        String params = String.format(
            "grant_type=client_credentials&client_id=%s&client_secret=%s",
            apiKey, secretKey
        );
        
        ResponseEntity<Map> response = restTemplate.postForEntity(
            url + "?" + params, null, Map.class
        );
        
        Map<String, Object> body = response.getBody();
        cachedAccessToken = (String) body.get("access_token");
        int expiresIn = (Integer) body.get("expires_in");
        
        // 设置过期时间(提前5分钟刷新)
        tokenExpireTime = System.currentTimeMillis() + (expiresIn - 300) * 1000L;
        
        return cachedAccessToken;
    }
    
    /**
     * 调用文心一言API
     */
    public String chat(String question) {
        // 1. 获取Access Token
        String accessToken = getAccessToken();
        
        // 2. 构建请求
        String url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=" + accessToken;
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        Map<String, Object> requestBody = new HashMap<>();
        List<Map<String, String>> messages = new ArrayList<>();
        Map<String, String> userMessage = new HashMap<>();
        userMessage.put("role", "user");
        userMessage.put("content", question);
        messages.add(userMessage);
        
        requestBody.put("messages", messages);
        requestBody.put("temperature", 0.7);
        requestBody.put("max_output_tokens", 200);
        
        // 3. 发送请求
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        
        try {
            ResponseEntity<Map> response = restTemplate.postForEntity(url, request, Map.class);
            
            // 4. 解析响应(注意:文心一言直接返回result字段)
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Object result = response.getBody().get("result");
                if (result != null) {
                    return (String) result;
                }
            }
            throw new RuntimeException("文心一言API响应异常");
            
        } catch (Exception e) {
            throw new RuntimeException("调用文心一言API失败:" + e.getMessage(), e);
        }
    }
}

2.5.5 Java代码调用示例

完整Java代码实现

package com.example.ai.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * OpenAI API调用服务
 */
@Service
public class OpenAIService {
    
    @Value("${ai.openai.api-key}")
    private String apiKey;
    
    private final RestTemplate restTemplate = new RestTemplate();
    
    private static final String API_URL = "https://api.openai.com/v1/chat/completions";
    
    /**
     * 调用OpenAI API,获取AI回答
     * 
     * @param question 用户问题
     * @return AI回答
     */
    public String chat(String question) {
        // 1. 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey); // 设置Bearer Token认证
        
        // 2. 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        
        // 构建消息列表
        List<Map<String, String>> messages = new ArrayList<>();
        Map<String, String> userMessage = new HashMap<>();
        userMessage.put("role", "user");
        userMessage.put("content", question);
        messages.add(userMessage);
        
        requestBody.put("messages", messages);
        requestBody.put("temperature", 0.7);
        requestBody.put("max_tokens", 200);
        
        // 3. 发送HTTP请求
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        
        try {
            ResponseEntity<Map> response = restTemplate.exchange(
                API_URL,
                HttpMethod.POST,
                request,
                Map.class
            );
            
            // 4. 解析响应
            return parseResponse(response.getBody());
            
        } catch (Exception e) {
            throw new RuntimeException("调用OpenAI API失败", e);
        }
    }
    
    /**
     * 解析API响应,提取AI回答
     */
    private String parseResponse(Map<String, Object> response) {
        // 获取choices数组
        List<Map<String, Object>> choices = (List<Map<String, Object>>) response.get("choices");
        
        if (choices == null || choices.isEmpty()) {
            throw new RuntimeException("API响应中没有choices字段");
        }
        
        // 获取第一个choice
        Map<String, Object> firstChoice = choices.get(0);
        
        // 获取message对象
        Map<String, Object> message = (Map<String, Object>) firstChoice.get("message");
        
        // 获取content字段(AI的回答)
        String content = (String) message.get("content");
        
        return content;
    }
    
    /**
     * 获取Token使用情况(用于成本统计)
     */
    public Map<String, Integer> getTokenUsage(String question) {
        // 调用API(同上)
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "gpt-3.5-turbo");
        
        List<Map<String, String>> messages = new ArrayList<>();
        Map<String, String> userMessage = new HashMap<>();
        userMessage.put("role", "user");
        userMessage.put("content", question);
        messages.add(userMessage);
        
        requestBody.put("messages", messages);
        
        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
        ResponseEntity<Map> response = restTemplate.exchange(
            API_URL,
            HttpMethod.POST,
            request,
            Map.class
        );
        
        // 解析usage字段
        Map<String, Object> usage = (Map<String, Object>) response.getBody().get("usage");
        
        Map<String, Integer> tokenUsage = new HashMap<>();
        tokenUsage.put("prompt_tokens", (Integer) usage.get("prompt_tokens"));
        tokenUsage.put("completion_tokens", (Integer) usage.get("completion_tokens"));
        tokenUsage.put("total_tokens", (Integer) usage.get("total_tokens"));
        
        return tokenUsage;
    }
}

配置文件(application.yml)

ai:
  openai:
    api-key: sk-your-api-key-here  # 替换为你的实际API Key

使用示例

@RestController
@RequestMapping("/api/ai")
public class AIController {
    
    @Autowired
    private OpenAIService openAIService;
    
    /**
     * 聊天接口
     */
    @PostMapping("/chat")
    public ResponseEntity<Map<String, String>> chat(@RequestBody Map<String, String> request) {
        String question = request.get("question");
        String answer = openAIService.chat(question);
        
        Map<String, String> response = new HashMap<>();
        response.put("answer", answer);
        
        return ResponseEntity.ok(response);
    }
}

测试请求

curl -X POST http://localhost:8080/api/ai/chat \
  -H "Content-Type: application/json" \
  -d '{"question": "你好,请用一句话介绍Java编程语言"}'

响应示例

{
  "answer": "Java是一种面向对象的编程语言,具有跨平台、安全性高、易于学习等特点,广泛应用于企业级应用开发。"
}

2.5.6 实战常见问题排查指南

问题排查速查表

错误现象HTTP状态码排查方向解决方案
API Key无效401API Key错误/过期核对API Key,重新生成
超过QPS限制429超过QPS/Token限额增加限流控制、升级付费套餐
请求参数错误400参数格式/值错误检查JSON格式、参数范围
响应内容截断200超过max_tokens限制调大max_tokens,或分批处理文本
网络连接超时-网络问题/服务不可用检查网络、使用代理、添加重试
Token超限429超过上下文窗口减少输入文本长度,分批处理

2.5.7 常见问题排查

问题1:401 Unauthorized错误

错误信息

{
  "error": {
    "message": "Incorrect API key provided",
    "type": "invalid_request_error",
    "code": "invalid_api_key"
  }
}

原因:API Key错误或未设置

解决方法

  1. 检查API Key是否正确
  2. 检查请求头中的Authorization格式:Bearer sk-xxx
  3. 确认API Key是否有权限

问题2:429 Too Many Requests错误

错误信息

{
  "error": {
    "message": "Rate limit exceeded",
    "type": "rate_limit_error"
  }
}

原因:超过QPS限制

解决方法

  1. 降低请求频率
  2. 使用限流器控制并发
  3. 升级API套餐(提高QPS限制)

问题3:400 Bad Request错误

错误信息

{
  "error": {
    "message": "Invalid parameter",
    "type": "invalid_request_error"
  }
}

原因:请求参数错误

解决方法

  1. 检查请求体JSON格式是否正确
  2. 检查参数值是否合法(如temperature范围0-2)
  3. 参考API文档确认参数格式

问题4:网络连接超时

原因:网络问题或API服务不可用

解决方法

  1. 检查网络连接
  2. 使用代理(如在国内访问OpenAI)
  3. 添加重试机制

Java重试示例

@Service
public class OpenAIServiceWithRetry {
    
    private static final int MAX_RETRIES = 3;
    
    public String chat(String question) {
        int retries = 0;
        while (retries < MAX_RETRIES) {
            try {
                return callAPI(question);
            } catch (Exception e) {
                retries++;
                if (retries >= MAX_RETRIES) {
                    throw new RuntimeException("调用API失败,已重试" + MAX_RETRIES + "次", e);
                }
                // 等待后重试
                try {
                    Thread.sleep(1000 * retries); // 递增等待时间
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        return null;
    }
    
    private String callAPI(String question) {
        // 实际的API调用代码
        // ...
        return "AI响应";
    }
}

2.5.8 AI调用成本优化技巧

优化策略

1. 精简提示词

  • 原则:去除冗余内容,仅保留核心需求
  • 示例
    // ❌ 不好的提示词(冗余)
    String prompt = "请帮我写一段关于Java编程语言的介绍,要求详细、全面、专业,字数不少于200字...";
    
    // ✅ 好的提示词(精简)
    String prompt = "用一句话介绍Java编程语言";
    

2. 缓存重复请求

  • 原理:对相同问题的AI响应进行缓存,避免重复调用
  • 实现:使用Redis缓存,Key为问题内容的MD5,Value为AI回答
  • Java示例
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    import org.apache.commons.codec.digest.DigestUtils;
    import java.util.concurrent.TimeUnit;
    
    /**
     * AI服务(带缓存优化)
     */
    @Service
    public class AIServiceWithCache {
        
        @Autowired
        private RedisTemplate<String, String> redisTemplate;
        
        private static final String CACHE_PREFIX = "ai:answer:";
        private static final int CACHE_EXPIRE_HOURS = 24;
        
        public String chat(String question) {
            // 生成缓存Key
            String cacheKey = CACHE_PREFIX + DigestUtils.md5Hex(question);
            
            // 先查缓存
            String cachedAnswer = redisTemplate.opsForValue().get(cacheKey);
            if (cachedAnswer != null) {
                return cachedAnswer;
            }
            
            // 缓存未命中,调用AI API
            String answer = callAIAPI(question);
            
            // 写入缓存
            redisTemplate.opsForValue().set(
                cacheKey, 
                answer, 
                CACHE_EXPIRE_HOURS, 
                TimeUnit.HOURS
            );
            
            return answer;
        }
    }
    

3. 选择合适模型

  • 原则:非核心场景使用轻量模型,核心场景使用高级模型
  • 示例
    • 简单问答:使用gpt-3.5-turbo(成本低)
    • 复杂推理:使用gpt-4(能力强但成本高)

4. 控制输出长度

  • 原则:合理设置max_tokens,避免生成过长内容
  • 建议
    • 简单回答:max_tokens = 200-500
    • 详细回答:max_tokens = 500-1000
    • 长文本生成:max_tokens = 1000-2000

5. 批量处理

  • 原理:将多个问题合并为一个请求,减少API调用次数
  • 注意:需要确保总Token数不超过上下文窗口

成本优化效果对比

优化策略成本降低适用场景
精简提示词10-30%所有场景
缓存重复请求50-80%常见问题场景
选择合适模型30-70%非核心场景
控制输出长度20-40%所有场景
批量处理20-50%批量处理场景

2.5.9 实战总结

核心流程回顾

  1. 准备API Key:申请并配置API Key
  2. 构建请求:设置请求方法、URL、请求头、请求体
  3. 发送请求:使用Postman或Java代码发送HTTP请求
  4. 解析响应:从JSON响应中提取AI回答
  5. 错误处理:处理常见的错误情况

关键技能

  • ✅ HTTP请求的构建和发送
  • ✅ JSON数据的解析
  • ✅ API认证(Bearer Token)
  • ✅ 错误处理和重试机制

下一步

  • 尝试调用其他AI模型(如百度文心一言)
  • 实现更复杂的功能(如多轮对话、流式响应)
  • 优化代码结构,提升可维护性

2.6 本章总结

2.6.1 核心要点回顾

通过本章的学习,你应该已经掌握了以下核心内容:

  1. AI模型分类与应用场景

    • 四大主流模型类型:大语言模型(LLM)、图像识别、语音处理、语义理解
    • 不同模型适用于不同业务场景,选对模型才能发挥最大价值
  2. 主流模型介绍

    • GPT系列:国际化应用、代码生成
    • 文心一言:国内应用、中文场景(Java开发者优先推荐)
    • 讯飞星火:语音交互场景
    • ChatGLM:本地部署场景
  3. 模型调用方式

    • API调用(公有云):零部署成本,快速接入,适合大多数场景
    • 本地化部署(私有模型):数据安全,适合敏感数据场景
  4. 关键概念

    • API Key:身份认证和计费依据
    • Token:文本处理的基本单位,计费依据
    • QPS:每秒查询数,需要控制并发
    • 上下文窗口:AI模型能处理的最大文本长度
    • Temperature:控制生成内容的随机性
  5. 实战能力

    • 使用Postman调用AI API
    • 用Java代码调用AI API
    • 解析API响应,提取AI回答
    • 处理常见错误情况

2.6.2 知识框架梳理

image.png

2.6.3 下一步学习方向

完成本章学习后,建议你:

  1. 巩固基础

    • 多练习调用不同AI模型的API
    • 熟悉不同参数的配置和效果
    • 掌握错误处理和重试机制
  2. 准备下一章

    • 第3章将深入学习AI应用开发的核心技能
    • 你将学习如何封装AI能力,开发业务接口
    • 你将学习如何处理实际业务场景中的各种问题
  3. 持续实践

    • 尝试在实际项目中应用AI能力
    • 关注AI平台的最新动态和API更新
    • 通过实际项目积累经验

2.6.4 学习建议

  • 理论结合实践:每学习一个概念,立即通过代码实践
  • 多尝试不同模型:了解不同模型的特点和适用场景
  • 关注成本控制:理解Token计费,合理控制调用成本
  • 持续优化:通过实际项目,不断优化代码和调用方式

恭喜你完成第2章的学习! 现在你已经掌握了AI模型的基础认知,了解了主流模型的特点,掌握了模型调用的核心方式,理解了关键概念,并完成了第一个AI接口调用。接下来,让我们进入第3章,深入学习AI应用开发的核心技能。