PHP如何调用OpenAI接口实现AI自动生成文章与摘要功能

各位亲爱的码农朋友们,大家好!

欢迎来到今天的“PHP与AI联姻”特别讲座。我是你们的老朋友,一个每天都在和代码死磕,同时又在思考怎么用代码征服世界的资深编程专家。

今天我们要聊的,是一个非常性感的话题:如何让PHP——这门被称为“世界上最流行(也最让人头疼)的服务端语言”,去调用OpenAI的API,实现AI自动生成文章和摘要。

你可能会问:“老专家,PHP不是那种老掉牙的语言吗?现在不是流行Go、Python、Rust吗?”
哎,各位,肤浅!PHP的魅力就在于它的“粘性”。只要有人类写网站的地方,就有PHP的身影。而现在,AI是未来的王,把PHP和AI结合,那就是“王炸”啊!这就像给哆啦A梦装上了任意门,你想要什么,他就给你变什么。

别废话了,直接上干货。今天咱们不讲虚的,只讲怎么把OpenAI的嘴撬开,让它乖乖为你写文章、做摘要。


第一章:准备工作,别还没开始就“裸奔”

在开始写代码之前,咱们得先有个“通行证”。OpenAI的API不是在大街上发传单的,你得去OpenAI官网申请一个API Key。这玩意儿就像是你家门钥匙,别告诉任何人,更别把钥匙贴在衬衫的背面。

注意: 不同的模型(比如GPT-3.5和GPT-4)价格不一样,GPT-4那家伙比较费钱,你每敲一下键盘,它的Token计数器都在滴答作响,就像你信用卡在滴答。咱们今天的实战,主要用GPT-3.5-turbo,性价比高,适合咱们这种“穷但有追求”的开发者。

另外,PHP版本嘛,咱们得讲究点。建议PHP 7.4或者8.0以上。如果你还在用PHP 5.6,那咱们就得先聊聊“回忆杀”了,或者,直接升级吧,别让旧代码拖累你的AI梦想。


第二章:PHP与HTTP的“亲密接触”——CURL是主角

PHP要调用OpenAI接口,本质上就是发一个HTTP POST请求。在这个领域,没有比 curl 函数族更忠诚的伙伴了。虽然有些人讨厌它,觉得它太复杂,参数太多像天书,但我告诉你,它是PHP的灵魂。如果你不会用CURL,你就不是个正宗的PHP程序员。

咱们先看个最基础的例子,就像打个招呼:“嘿,OpenAI,在吗?”

<?php

// 1. 初始化,就像你拨通电话
$ch = curl_init();

// 2. 设置目标URL,OpenAI的聊天接口地址
$url = 'https://api.openai.com/v1/chat/completions';

// 3. 构造请求头,告诉人家你是谁,你想干嘛
$headers = [
    'Content-Type: application/json',
    'Authorization: Bearer YOUR_OPENAI_API_KEY_HERE', // 这里记得替换成你自己的Key
];

// 4. 准备要发送的数据,这就是你要喂给AI的“饲料”
$data = [
    'model' => 'gpt-3.5-turbo', // 咱们用便宜的3.5
    'messages' => [
        ['role' => 'user', 'content' => '你好,请用一句话介绍PHP语言。']
    ]
];

// 5. 把数据转成JSON格式,这是HTTP协议最喜欢的语言(虽然HTTP自己不懂)
$payload = json_encode($data);

// 6. 设置CURL选项
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true, // true表示把返回结果存到变量里,而不是直接打印出来
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_TIMEOUT => 30, // 别让请求挂太久,超过30秒你就得喝西北风了
]);

// 7. 执行请求,就像按下拨号键
$response = curl_exec($ch);

// 8. 检查有没有错误,别光顾着笑,还得检查有没有翻车
if (curl_errno($ch)) {
    echo '请求出错: ' . curl_error($ch);
} else {
    // 9. 打印结果,看看AI说了啥
    echo $response;
}

// 10. 关闭连接,挂断电话
curl_close($ch);

?>

这段代码虽然短,但它干了一件大事:它成功地把请求发给了OpenAI。如果你运行这段代码,你会发现返回的 $response 是一大坨JSON字符串。别慌,那是AI的思考过程,里面包含了AI说的话。咱们下一章,就要教你怎么从这坨乱七八糟的字符串里,把有用的信息“抠”出来。


第三章:解析JSON与提示词工程——给AI“穿”上西装

得到JSON响应后,我们得用 json_decode 把它变成PHP能读懂的数组。然后,你会发现返回的结构里有一个 choices[0][message][content] 字段,那就是AI的回答。

但是,光会调用还不够。你想让AI写文章?那得靠提示词

提示词(Prompt)是灵魂。就像你让厨师做菜,你说“给我做个饭”,厨师可能给你端来一盘空气;但你说“给我做个麻婆豆腐,要微辣,不要太麻,配米饭”,那出来的就是完美的菜肴。

在PHP里,我们可以把提示词放在一个变量里,甚至可以做成一个模板。

<?php

function generateSummary($text) {
    $apiKey = 'YOUR_API_KEY';
    $url = 'https://api.openai.com/v1/chat/completions';

    // 这是提示词工程的艺术
    // system角色:设定AI的人设,让它像个严肃的编辑
    // user角色:具体的任务
    $messages = [
        ['role' => 'system', 'content' => '你是一个资深的编辑,擅长撰写文章摘要。你的输出必须简洁、准确,且只包含摘要,不要有废话。'],
        ['role' => 'user', 'content' => "请为以下这段文字生成一个摘要:nn{$text}"]
    ];

    $payload = json_encode([
        'model' => 'gpt-3.5-turbo',
        'messages' => $messages,
        'temperature' => 0.7 // 这里的temperature决定了AI的“发挥空间”,0.7比较稳妥
    ]);

    // 发送请求...(省略了重复的curl_init等代码,实际开发要封装成一个函数)

    // 假设 $response 是刚才返回的JSON字符串
    $decoded = json_decode($response, true);

    if (isset($decoded['choices'][0]['message']['content'])) {
        return $decoded['choices'][0]['message']['content'];
    }

    return "AI罢工了,没吐出东西。";
}

// 测试一下
$longText = "PHP(PHP: Hypertext Preprocessor)是一种通用开源脚本语言。脚本语言主要运行在服务器端,PHP代码会被处理为生成HTML等网页文档。尽管PHP最初是个人主页工具,但如今它已被广泛使用,用来开发Web应用,从简单的命令行脚本到复杂的社交网络应用。PHP语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。";
echo generateSummary($longText);
?>

看,这就是PHP调用AI的核心逻辑。你把 $longText 传进去,告诉AI“这玩意儿太长了,给我总结一下”,AI就会乖乖吐出一个简洁的摘要。


第四章:实战演练——自动生成文章

现在咱们来点更刺激的。如果只做摘要,那AI顶多是个小学生。我们要让它写文章。

写文章有个难点:上下文长度。GPT-3.5或者GPT-4都有个脾气,它一次最多只能处理一定的字数(比如4096个Token)。如果你的文章太长,直接塞给它,它会说“哎呀,我内存不够了,记不住了”。这就好比你让一个人背整本字典,他背到一半肯定会忘开头。

所以,对于长篇文章的生成,咱们得用分段处理的策略。把文章切成一段一段,让AI一段一段地写,最后再把它拼起来。

下面是一个完整的生成长文类的代码示例。为了演示效果,我封装了一个 OpenAIChat 类。

<?php

class OpenAIChat {
    private $apiKey;
    private $model;
    private $ch; // CURL句柄,复用能提升性能

    public function __construct($apiKey, $model = 'gpt-3.5-turbo') {
        $this->apiKey = $apiKey;
        $this->model = $model;
        $this->ch = curl_init();
    }

    public function complete($messages, $stream = false) {
        $url = 'https://api.openai.com/v1/chat/completions';
        $payload = json_encode([
            'model' => $this->model,
            'messages' => $messages,
            'stream' => $stream
        ]);

        curl_setopt_array($this->ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $payload,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $this->apiKey
            ],
            CURLOPT_TIMEOUT => 60
        ]);

        $response = curl_exec($this->ch);

        if (curl_errno($this->ch)) {
            throw new Exception('CURL Error: ' . curl_error($this->ch));
        }

        return json_decode($response, true);
    }

    public function close() {
        curl_close($this->ch);
    }
}

// ==========================================
// 主程序:生成一篇关于“PHP未来”的文章
// ==========================================

$apiKey = 'YOUR_KEY';
$ai = new OpenAIChat($apiKey);

// 1. 构建任务
$task = "请写一篇关于《PHP在2024年的未来展望》的文章,字数要求800字。要求文章结构完整,包含引言、正文和结论。";

// 2. 发起请求
try {
    $result = $ai->complete([
        ['role' => 'system', 'content' => '你是一位知名的科技博主,擅长撰写深度技术文章。'],
        ['role' => 'user', 'content' => $task]
    ]);

    $content = $result['choices'][0]['message']['content'];

    echo "<h1>AI生成的文章如下:</h1>";
    echo "<p>" . nl2br($content) . "</p>";

} catch (Exception $e) {
    echo "哎呀,出错了: " . $e->getMessage();
}

$ai->close();

?>

这段代码展示了如何发送系统提示词(System Prompt)来设定AI的人设。告诉它“你是科技博主”,它写出来的东西就会比你那个只会喊“Hello World”的初级开发者要专业得多。


第五章:流式响应——像看视频一样看AI写作

你肯定见过那种,文字一个个蹦出来的效果,像打字机一样。这就是流式响应

在PHP里实现流式响应,稍微有点技术含量。因为它不是一次性把结果发回来,而是数据一点点发回来。我们需要使用 CURLOPT_WRITEFUNCTION 回调函数,实时捕获数据并打印。

这对用户体验来说是革命性的。当你在写一个博客生成器时,用户不用干坐着等3秒钟,而是看着字一个一个冒出来,心里会觉得“哇,好快!好智能!”

<?php

function streamChat($apiKey, $prompt) {
    $ch = curl_init('https://api.openai.com/v1/chat/completions');

    $headers = [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $apiKey
    ];

    $data = [
        'model' => 'gpt-3.5-turbo',
        'messages' => [
            ['role' => 'user', 'content' => $prompt]
        ],
        'stream' => true // 关键!开启流式传输
    ];

    // 定义回调函数,每次收到数据就调用
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $chunk) {
        // OpenAI的流式数据是以 "data: " 开头的JSON片段
        if (strpos($chunk, 'data: ') === 0) {
            $jsonStr = substr($chunk, 6); // 去掉 "data: "

            if ($jsonStr === '[DONE]') {
                return strlen($chunk); // 结束了
            }

            $json = json_decode($jsonStr, true);
            if (isset($json['choices'][0]['delta']['content'])) {
                $content = $json['choices'][0]['delta']['content'];
                echo $content; // 实时输出
                flush(); // 强制刷新缓冲区,让浏览器立马显示出来
            }
        }
        return strlen($chunk);
    });

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    curl_exec($ch);
    curl_close($ch);
}

// 使用示例
streamChat('YOUR_KEY', '请流式地给我讲个笑话,讲完为止。');

?>

这段代码展示了 flush() 函数的重要性。PHP默认会把输出缓冲,导致你可能要等一大堆数据攒够了才显示出来。用了这个函数,用户就能感受到AI“正在思考”的过程。


第六章:架构之美——封装与服务层

老专家我要敲黑板了!上面的代码虽然能跑,但在生产环境中就是“地雷”。

  1. 安全性: API Key不能写在代码里,应该放在环境变量里。
  2. 重试机制: 网络是不稳定的,有时候AI服务器会抽风,你得写个 try-catch 循环,失败了重试3次。
  3. 缓存: 别每次都问AI。如果用户看了同一篇文章两次,别再浪费钱去调用API了,直接读缓存。
  4. Token统计: 记得记录用了多少Token,方便算账。

咱们来构建一个稍微高级一点的 OpenAIService 类。

<?php

class OpenAIService {
    private $apiKey;
    private $model;
    private $retryCount = 3; // 失败重试3次

    public function __construct($apiKey, $model = 'gpt-3.5-turbo') {
        $this->apiKey = $apiKey;
        $this->model = $model;
    }

    /**
     * 发送请求,包含重试逻辑
     */
    public function sendMessage($prompt, $systemRole = 'You are a helpful assistant.') {
        $messages = [
            ['role' => 'system', 'content' => $systemRole],
            ['role' => 'user', 'content' => $prompt]
        ];

        for ($attempt = 1; $attempt <= $this->retryCount; $attempt++) {
            try {
                $result = $this->doRequest($messages);
                return $result['content'];
            } catch (Exception $e) {
                echo "第 {$attempt} 次尝试失败: " . $e->getMessage() . "n";
                if ($attempt < $this->retryCount) {
                    sleep(1 * $attempt); // 指数退避,别立刻重试,给服务器喘口气
                } else {
                    throw new Exception("重试3次后依然失败,放弃治疗。");
                }
            }
        }
    }

    private function doRequest($messages) {
        // ... 这里复用之前的 curl 代码 ...
        // 为了代码简洁,这里省略具体curl实现,假设调用成功返回数组 ['content' => '...']
        return ['content' => "模拟AI返回的内容"];
    }
}

// 使用
$service = new OpenAIService(getenv('OPENAI_API_KEY'));
$summary = $service->sendMessage("请帮我总结这段代码...");
echo $summary;

?>

这个类封装了 try-catchsleep,这就是“资深”和“菜鸟”的区别。菜鸟写代码是“能跑就行”,老手写代码是“能跑、稳定、安全、可维护”。


第七章:高级玩法——结构化输出与JSON Mode

如果你想让PHP处理AI生成的内容,最头疼的是什么?是解析AI吐出来的乱七八糟的文本。AI有时候很自信,有时候会胡说八道,有时候格式还跑偏了。

现在OpenAI支持一种高级模式叫 JSON Mode。你可以告诉AI:“我只接受JSON格式,而且必须包含这些字段:title, content, tags。” 如果AI不按格式来,它就会被拒绝。

这对PHP开发者来说简直是福音!因为PHP里处理JSON比处理HTML要容易得多。

<?php

function generateStructuredContent($topic) {
    $apiKey = 'YOUR_KEY';

    $payload = json_encode([
        'model' => 'gpt-3.5-turbo',
        'response_format' => ['type' => 'json_object'], // 强制返回JSON
        'messages' => [
            [
                'role' => 'system', 
                'content' => '你是一个内容生成器。你必须以JSON格式输出。JSON结构必须包含 title, description, and tags 数组。'
            ],
            [
                'role' => 'user', 
                'content' => "请生成一个关于 {$topic} 的博客文章元数据。"
            ]
        ]
    ]);

    // 发送请求...
    // $response = curl_exec(...);

    // 解析JSON
    $data = json_decode($response, true);

    return $data; // 直接就是数组了,直接 foreach 就行
}

// 使用
$result = generateStructuredContent("PHP的未来");
echo "标题: " . $result['title'] . "n";
echo "标签: " . implode(', ', $result['tags']);
?>

记得,在 response_format 里指定 json_object,然后配合精心设计的System Prompt,AI会变得非常有纪律性。


第八章:常见坑与最佳实践

好了,到了咱们“扫雷”的时间。在实战中,大家经常会遇到这些问题,老专家我替你们踩过坑了:

  1. Token计数错误:
    PHP的 strlen 是算字节数的,不是算Token的。有些中文字符占3个字节,有的占1个字节。发送给OpenAI的时候,它按Token算钱,你按字节算成本,很容易超支。建议使用库如 token-count 或者直接在本地估算。

  2. Rate Limit(速率限制):
    OpenAI对免费账户有限制。如果你在一个循环里,一瞬间发了100个请求,你的IP会被封禁。一定要设置请求间隔,比如每秒最多1-2个请求。

  3. 提示词越界:
    你问了一个超级复杂的问题,结果GPT只回复了“我无法回答”。这是因为超出了上下文窗口。这时候你要学会把大问题拆成小问题,分步回答。

  4. API Key 泄露:
    千万别把Key写在前端(HTML/JS)里!前端代码是给所有人看的。Key必须放在后端。


总结:PHP,永不放弃的战士

说了这么多,其实PHP调用OpenAI接口的核心原理就三步:

  1. 组装JSON: 把你的问题变成API能懂的语言。
  2. 发HTTP请求: 用CURL把它扔出去。
  3. 解析结果:json_decode 把AI的脑子拿出来。

别再说PHP老了。当Python还在忙着把AI库封装得花花绿绿时,PHP凭借其强大的Web生态,正以极简的方式深入到每一个服务器端。把AI能力塞进你的CMS里,塞进你的电商后台里,塞进你的管理系统中,这才是编程的最高境界——赋能

今天的讲座就到这里。希望你们回去后,能写出那个让全公司都震惊的“AI文章自动生成器”。

别忘了,写代码的时候,喝口水,少点两根烟。AI是智慧,身体是本钱。咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注