当前位置: 首页 > news >正文

WEB项目接入Deepseek(硅基流动)

在这里插入图片描述

文末有彩蛋哦!!!

这里调用的api为硅基流动的,如用的是其他平台的请自行改url

核心

URL

POST https://api.siliconflow.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:

.ai-container{
  padding: 20px;
  padding-bottom: 140px;

  
  .output-item{
    padding: 20px 0;
    max-width: 80%;
    .reasoning-content{
      color: #8b8b8b;
      white-space: pre-wrap;
      margin: 0;
      padding: 0 0 0 13px;
      line-height: 26px;
      position: relative;
      border-left: 1px solid #e0e0e0;
    }
    &.user{
      text-align: right;
      margin-left: auto;
    }
    &.assistant{
      text-align: left;
      margin-right: auto;
    }
  }


  .input-container{
    background-color: #fff;
    padding: 0px 40px;
    width: 100%;
    height: 140px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    bottom: 0;
    left: 0;
    border-top: 1px solid #e0e0e0;
    textarea{
      flex: 1;
      padding: 20px;
      // width: 100%;
      background-color: #f0f0f0;
      border-radius: 8px;
      border-color: #e0e0e0;
      outline: none;
      height: 3em;
    }
    button{
      flex-shrink: 0;
      margin-left: 10px;
    }
  }
}

效果

在这里插入图片描述


文末彩蛋!!(粉丝福利)

DeepSeek使用技巧大全.rar:https://pan.quark.cn/s/6e769f336d4b

http://www.dtcms.com/a/26688.html

相关文章:

  • Shapr3D在ipad上无法识别鼠标点击问题
  • NPB安装使用教程
  • 基于iptables的Docker端口白名单控制
  • C++ 程序 return value 1 是什么原因
  • 寒假阶段学习总结
  • C++:pthread的使用
  • SpringSecurity基于配置方法控制访问权限:MVC匹配器、Ant匹配器
  • hive 编译慢问题处理
  • FontConfig封装分享
  • Token Embedding(词嵌入)和Positional Encoding(位置编码)的矩阵形状关系及转换过程
  • [grub]修改启动项选项来区分不同系统
  • fastapi sqlalchemy 日志 logging 写入异常 多进程文件写入异常
  • python-leetcode 37.翻转二叉树
  • Javascript网页设计实例:通过JS实现上传Markdown转化为脑图并下载脑图
  • 火语言RPA--Excel关闭保存文档
  • 【HarmonyOS Next】鸿蒙监听手机按键
  • 汇能感知的光谱相机/模块产品有哪些?
  • 【python】tkinter简要教程
  • oppo,汤臣倍健,康冠科技,高途教育25届春招内推
  • 记录一下windows11编译Openpose的过程
  • 使用VSCODE开发C语言程序
  • 【PLL】应用:时钟生成
  • 【项目日记】仿RabbitMQ实现消息队列 --- 模块设计
  • 【云安全】云原生-Docker(六)Docker API 未授权访问
  • unity学习49:寻路网格链接 offMeshLinks, 以及传送门效果
  • 使用FFmpeg将PCMA格式的WAV文件转换为16K采样率的PCM WAV文件
  • 基于SpringBoot实现的宠物领养系统平台功能一
  • JUC并发编程——Java线程(一)
  • 从线程池到负载均衡:高并发场景下的系统优化实战
  • 本地部署Anything LLM+Ollama+DeepSeek R1打造AI智能知识库教程