php调用deepseek接口api并流式输出

 1.注册deepseek并新建密钥

2 php服务端代码

$json = file_get_contents('php://input');
$jsonData = json_decode($json, true);
$datas=  ['model'=>'deepseek-chat',
		  'messages'=>[
			['role'=>'user','content'=>$jsonData['content']]
		  ],
		  'stream'=>true
		 ];
send('https://api.deepseek.com/chat/completions',$datas,'handleResponseData');
function send(string $url,$postdata,callable $callback){
	$curl = curl_init();
 
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
	 
	$headers = [
		"Content-Type: application/json", // 设置内容类型为JSON
		"Authorization: Bearer sk-69**************9d" // 设置认证头信息,例如Bearer Token
	];
	curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); // 设置头信息
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
	curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postdata));
	curl_setopt($curl, CURLOPT_WRITEFUNCTION, function ($curl, $data) use ($callback) {
        // 调用回调函数处理数据
        $callback($data);
        return strlen($data); // 返回接收到的数据长度
    });
	 
	$response = curl_exec($curl); // 执行请求并获取响应
	if ($response === false) {
		echo 'Curl error: ' . curl_error($curl); // 检查是否有错误发生
	}
	 
	curl_close($curl); // 关闭cURL会话
	//echo "123";
}


function handleResponseData($data) {
	echo $data;
    flush(); // 刷新输出缓冲区
}

流式输出有几个关键点

1.报文stream为true

2.curl 开启  CURLOPT_RETURNTRANSFER,使用CURLOPT_WRITEFUNCTION处理返回数据

3前端代码

<body>
<div id="app">
	
  
</div>
</body>
<script>
reading();
async function reading(){
	const resp =await fetch('http://localhost/test.php',{
		method:'POST',
		headers:{
			'Content-Type':'application/json'
		},
		body:JSON.stringify({content:'如何评价自由高达的机设'}),
		dataType:"text/event-stream"
	})
	const reader=resp.body.getReader()
	const decoder=new TextDecoder()
	let container = document.getElementById('app');
	while(1){
		const {done,value}=await reader.read()
		if(done){
		  break;
		}
		let txt=decoder.decode(value)
		let output = handleData(txt);
		container.innerHTML+=output;
	}
}

function handleData(dataString){
	const regex = /"content":"([^"]*)"/g;
	let matches;
	let finalStr='';
	while ((matches = regex.exec(dataString)) !== null) {
	  finalStr+=matches[1];
	}
	//转换行
	let s = finalStr.replace(/\\n/g, '<br>');
	return  s;

}

</script>

前端难点是处理报文,因为deepseek返回的块状数据是这样,我不知道这种具体是什么格式,所以只能用正则把它取下来

data: {"id":"bbadf0e5-3ed5-417a-89f7-146a4869c15d","object":"chat.completion.chunk","created":1743091685,"model":"deepseek-chat","system_fingerprint":"fp_3d5141a69a_prod0225","choices":[{"index":0,"delta":{"content":"am"},"logprobs":null,"finish_reason":null}]}

### Java 调用 DeepSeek 接口实现流式输出 要通过 Java 实现对 DeepSeek API调用来完成流式输出功能,可以基于 Reactor 库中的 `Flux` 来处理异步数据流。以下是具体实现方: #### 配置文件设置 在项目的配置文件 `application.yml` 中定义必要的参数以连接到 DeepSeek API[^1]。 ```yaml ai: deepseek: api-key: ${DEEPSEEK_API_KEY} # 从环境变量读取 base-url: https://api.deepseek.com/v1 ``` 上述配置用于存储 API 密钥以及基础 URL 地址。 --- #### 定义服务接口 创建一个名为 `DeepSeekService` 的接口,其中包含两个方法:一个是返回单次响应的方法;另一个是支持流式输出的方法[^2]。 ```java import reactor.core.publisher.Flux; public interface DeepSeekService { /** * 流式输出 * * @param userId 用户唯一标识符 * @param userMessage 用户输入的消息 * @return 返回 Flux<String> 数据流对象 */ Flux<String> callDeepSeekStream(Long userId, String userMessage); /** * 单次请求并获取完整响应 * * @param userId 用户唯一标识符 * @param userMessage 用户输入的消息 * @return 返回完整的字符串形的响应 */ String callDeepSeek(Long userId, String userMessage); } ``` 此部分定义了两种交互模:一种是非流式的标准 HTTP 请求/响应模型,另一种则是利用 Webflux 提供的支持流式传输的能力。 --- #### 实现服务类逻辑 下面是一个可能的服务实现示例,展示如何构建 RESTful 请求并与 DeepSeek API 进行通信。 ```java import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; public class DeepSeekServiceImpl implements DeepSeekService { private final WebClient webClient; public DeepSeekServiceImpl(String baseUrl, String apiKey) { this.webClient = WebClient.builder() .baseUrl(baseUrl) .defaultHeader("Authorization", "Bearer " + apiKey) .build(); } @Override public Flux<String> callDeepSeekStream(Long userId, String userMessage) { return webClient.post() .uri("/chat/stream") // 假设这是流式接口路径 .bodyValue(Map.of( "userId", userId, "message", userMessage)) .retrieve() .bodyToFlux(String.class); // 将响应转换为 Flux<String> } @Override public String callDeepSeek(Long userId, String userMessage) { return webClient.post() .uri("/chat") // 假设这是非流式接口路径 .bodyValue(Map.of( "userId", userId, "message", userMessage)) .retrieve() .bodyToMono(String.class) // 获取单一响应体作为 Mono<String> .block(); // 同步阻塞等待结果 } } ``` 在此代码片段中: - 使用 Spring 的 `WebClient` 构建了一个可重用的客户端实例。 - 对于流式输出场景,采用 `.bodyToFlux()` 方法将服务器端的数据逐步推送至客户端。 - 非流式情况下,则直接使用 `.bodyToMono().block()` 方便地提取最终的结果。 --- #### 注意事项 为了确保程序能够正常运行,请确认以下几点: 1. **API Key 设置**:确保存储在环境变量中的 `DEEPSEEK_API_KEY` 已正确定义。 2. **依赖引入**:项目需引入 Spring Webflux 和其他必要库。 3. **异常处理**:实际开发过程中应加入更完善的错误捕获机制以便更好地应对网络中断等问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿John

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值