react 接入Deepseek

核心

URL

POST https://api.nowjava.cn/v1/chat/completions

headers :

{
  'Authorization': 'Bearer XXX',
  'Content-Type': 'application/json'
}

请求参数:

{
      "model": "你的模型",
      "messages": [
        { "role": "user", "content": prompt }
      ],
      "stream": true,
      // "max_tokens": 512,
      // "stop": ["null"],
      // "temperature": 0.7, "top_p": 0.7,
      // "top_k": 50, "frequency_penalty": 0.5, "n": 1,
      // "response_format": { "type": "text" },
      // "tools": [{ "type": "function", "function": { "description": "<string>", "name": "<string>", "parameters": {}, "strict": false } }]
}

使用示例(代码)

这里用react的代码做了个简单的示例

AIApi.jsx:

import { useEffect, useState, useRef } from 'react';
import './AIApi.scss';

export default function AIApi() {
  const [dialogRecords, setDialogRecords] = useState([]);

  // ref 存储textarea 内容
  const inputRef = useRef(null);

  // 实例创建时发送 axios
  useEffect(() => {
    // handleSubmit();
  }, []);

  let handleSubmit = async (event) => {
    event.preventDefault();
    streamOllamaResponse(inputRef.current.value);
  }

  async function streamOllamaResponse(prompt) {
    setDialogRecords((dialogRecords) => [...dialogRecords, {
      id: new Date().getTime(),
      content: prompt,
      reasoning_content: '',
      type: 'user'
    }]);

    const data = {
      "model": "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B",
      "messages": [
        { "role": "user", "content": prompt }
      ],
      "stream": true,
      // "max_tokens": 512,
      // "stop": ["null"],
      // "temperature": 0.7, "top_p": 0.7,
      // "top_k": 50, "frequency_penalty": 0.5, "n": 1,
      // "response_format": { "type": "text" },
      // "tools": [{ "type": "function", "function": { "description": "<string>", "name": "<string>", "parameters": {}, "strict": false } }]
    }
    const url = 'https://api.siliconflow.cn/v1/chat/completions';
    const headers = {
      'Authorization': 'Bearer apikey。。。',
      'Content-Type': 'application/json'
    }
    const response = await fetch(url, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(data)
    });
    if (!response.ok) {
      console.error(`请求失败,状态码: ${response.status}`);
      return;
    }
    const reader = response.body.getReader();
    const decoder = new TextDecoder('utf-8');
    let buffer = '';
    const processText = ({ done, value }) => {
      if (done) {
        // 处理最后可能剩余的数据
        processDataChunk(buffer, '');
        // Stream complete
        return;
      }
      let chunk = decoder.decode(value, { stream: true });
      buffer += chunk;
      let eventEndIndex = buffer.indexOf('\n\n');
      // console.log("chunk", chunk);
      while (eventEndIndex !== -1) {
        const eventData = buffer.slice(0, eventEndIndex);
        processDataChunk(eventData, '');
        buffer = buffer.slice(eventEndIndex + 2);
        eventEndIndex = buffer.indexOf('\n\n');
      }
      // next chunk
      return reader.read().then(processText);
    };

    // 开始读取第一个数据块
    return reader.read().then(processText);
  }
  function processDataChunk(eventData, outputDiv) {
    // 检查是否以 "data:" 开头
    if (eventData.startsWith('data:')) {
      // 提取数据部分
      const data = eventData.slice(5).trim();
      try {
        // 尝试解析为 JSON(如果数据是 JSON 格式)
        const parsedData = JSON.parse(data);
        // console.log(parsedData);
        let id = parsedData.id;
        let content = parsedData.choices[0].delta.content || '';
        let reasoning_content = parsedData.choices[0].delta.reasoning_content || '';

        setDialogRecords((dialogRecords) =>{
          let recordIndex = dialogRecords.findIndex(item => item.id == id);
          console.log(id, content, recordIndex);
          if (recordIndex === -1) {
            return [...dialogRecords, {
              id,
              content,
              reasoning_content,
              type: 'assistant'
            }];
          } else {
              let newRecords = [...dialogRecords];
              newRecords[recordIndex].content += content;
              newRecords[recordIndex].reasoning_content += reasoning_content;
              console.log(newRecords);
              return newRecords;
          }
        })
      }
      catch (parseError) {
        console.error(data);
      }
    }
  }

  return (
    <div className='ai-container'>
      <h2>AI api Page</h2>
      <div className='ai-content'>
        <div className='output-container'>
          {dialogRecords.map((item, index) => {
            return (
              <div key={index} className={`output-item ${item.type}`}>
                <div className='reasoning-content'>{item.reasoning_content}</div>
                <div className='content'>{item.content}</div>
              </div>
            )
          })}
        </div>
        <div className='input-container'>
          <textarea ref={inputRef} name="" id="" placeholder='请输入您的问题'></textarea>
          <button onClick={handleSubmit}>提交</button>
        </div>
      </div>
    </div>
  )
}

AIApi.scss:

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java