简介

本文将介绍如何使用 PHP 调用 DeepSeek API,实现流式对话并保存对话记录。PHP 版本使用面向对象的方式实现,代码结构清晰,易于维护。

1. 环境准备

1.1 系统要求

  • PHP 7.0 或更高版本
  • PHP cURL 扩展
  • 文件写入权限

1.2 项目结构

1

2

3

deepseek-project/

├── main.php          # 主程序

└── conversation.txt  # 对话记录文件

2. 完整代码实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

<?php

class DeepSeekChat {

    private $url = 'https://api.siliconflow.cn/v1/chat/completions';

    private $apiKey = 'YOUR_API_KEY'// 替换为你的 API Key

    private $logFile = 'conversation.txt';

    public function __construct() {

        // 确保日志文件存在且可写

        if (!file_exists($this->logFile)) {

            touch($this->logFile);

        }

    }

    private function saveToFile($content, $isQuestion = false) {

        $timestamp = date('Y-m-d H:i:s');

        $text = $isQuestion

            ? "\n[$timestamp] Question:\n$content\n\n[$timestamp] Answer:\n"

            : $content;

         

        file_put_contents($this->logFile, $text, FILE_APPEND);

    }

    private function processStreamingResponse($handle) {

        $buffer = '';

        while (!feof($handle)) {

            $chunk = fread($handle, 1024);

            $buffer .= $chunk;

            // 处理缓冲区中的每一行

            while (($pos = strpos($buffer, "\n")) !== false) {

                $line = substr($buffer, 0, $pos);

                $buffer = substr($buffer, $pos + 1);

                if (strlen(trim($line)) > 0) {

                    if (strpos($line, 'data: ') === 0) {

                        $data = substr($line, 6); // 移除 "data: " 前缀

                        if ($data === '[DONE]') {

                            continue;

                        }

                        $json = json_decode($data, true);

                        if ($json && isset($json['choices'][0]['delta']['content'])) {

                            $content = $json['choices'][0]['delta']['content'];

                            echo $content;

                            flush();

                            $this->saveToFile($content);

                        }

                    }

                }

            }

        }

    }

    public function chat() {

        while (true) {

            echo "\n请输入您的问题 (输入 q 退出): ";

            $question = trim(fgets(STDIN));

            if ($question === 'q') {

                echo "程序已退出\n";

                break;

            }

            // 保存问题

            $this->saveToFile($question, true);

            // 准备请求数据

            $data = [

                'model' => 'deepseek-ai/DeepSeek-V3',

                'messages' => [

                    [

                        'role' => 'user',

                        'content' => $question

                    ]

                ],

                'stream' => true,

                'max_tokens' => 2048,

                'temperature' => 0.7,

                'top_p' => 0.7,

                'top_k' => 50,

                'frequency_penalty' => 0.5,

                'n' => 1,

                'response_format' => [

                    'type' => 'text'

                ]

            ];

            // 准备 cURL 请求

            $ch = curl_init($this->url);

            curl_setopt_array($ch, [

                CURLOPT_POST => true,

                CURLOPT_POSTFIELDS => json_encode($data),

                CURLOPT_RETURNTRANSFER => true,

                CURLOPT_HTTPHEADER => [

                    'Content-Type: application/json',

                    'Authorization: Bearer ' . $this->apiKey

                ],

                CURLOPT_WRITEFUNCTION => function($ch, $data) {

                    echo $data;

                    return strlen($data);

                }

            ]);

            try {

                // 发送请求并处理响应

                $handle = curl_exec($ch);

                 

                if (curl_errno($ch)) {

                    throw new Exception(curl_error($ch));

                }

                // 添加分隔符

                echo "\n----------------------------------------\n";

                $this->saveToFile("\n----------------------------------------\n");

            } catch (Exception $e) {

                $error_msg = "请求错误: " . $e->getMessage() . "\n";

                echo $error_msg;

                $this->saveToFile($error_msg);

            } finally {

                curl_close($ch);

            }

        }

    }

}

// 运行程序

$chatbot = new DeepSeekChat();

$chatbot->chat();

3. 代码详解

3.1 类结构

  • DeepSeekChat: 主类,封装所有功能
  • __construct: 构造函数,初始化日志文件
  • saveToFile: 保存对话记录
  • processStreamingResponse: 处理流式响应
  • chat: 主对话循环

3.2 关键功能

文件操作

1

2

3

4

5

6

7

8

private function saveToFile($content, $isQuestion = false) {

    $timestamp = date('Y-m-d H:i:s');

    $text = $isQuestion

        ? "\n[$timestamp] Question:\n$content\n\n[$timestamp] Answer:\n"

        : $content;

     

    file_put_contents($this->logFile, $text, FILE_APPEND);

}

cURL 配置

1

2

3

4

5

6

7

8

9

curl_setopt_array($ch, [

    CURLOPT_POST => true,

    CURLOPT_POSTFIELDS => json_encode($data),

    CURLOPT_RETURNTRANSFER => true,

    CURLOPT_HTTPHEADER => [

        'Content-Type: application/json',

        'Authorization: Bearer ' . $this->apiKey

    ]

]);

3.3 参数说明

  • model: 使用的模型名称
  • stream: 启用流式输出
  • max_tokens: 最大输出长度 (2048)
  • temperature: 控制随机性 (0.7)
  • top_ptop_k: 采样参数
  • frequency_penalty: 重复惩罚系数

4. 错误处理

代码包含完整的错误处理机制:

  • cURL 错误检查
  • JSON 解析错误处理
  • 文件操作错误处理
  • 异常捕获和日志记录

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐