2025-02-12
深度学习
00

目录

API调用
OpenWebUI使用
使用

API调用

登录这里: https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint?config=%7B%7D

注册后,创建DeepSeek R1 API接入点:

image.png

接着Python就可以直接调用了:

python
import os from openai import OpenAI client = OpenAI( api_key = "填写自己的key", base_url = "https://ark.cn-beijing.volces.com/api/v3", ) # Non-streaming: print("----- standard request -----") completion = client.chat.completions.create( model = "ep-20250211175825-填写自己的模型名字", # your model endpoint ID messages = [ {"role": "system", "content": "你是豆包,是由字节跳动开发的 AI 人工智能助手"}, {"role": "user", "content": "常见的十字花科植物有哪些?"}, ], ) print(completion.choices[0].message.content)

OpenWebUI使用

安装:

docker run -d -p 8888:8080 \ -v /root/ollama:/root/.ollama \ -v /root/openwebui-test:/app/backend/data \ --restart always -e HF_HUB_OFFLINE=1 \ ghcr.io/open-webui/open-webui:ollama

增加这个函数到OpenWebUI:

bash
""" title: DeepSeek R1 author: zgccrui description: 在OpwenWebUI中显示DeepSeek R1模型的思维链 - 仅支持0.5.6及以上版本 version: 1.2.6 licence: MIT """ import json import httpx import re from typing import AsyncGenerator, Callable, Awaitable from pydantic import BaseModel, Field import asyncio class Pipe: class Valves(BaseModel): DEEPSEEK_API_BASE_URL: str = Field( default="自己的baseurl", description="Base Url", ) DEEPSEEK_API_KEY: str = Field( default="", description="用于身份验证的DeepSeek API密钥,可从控制台获取" ) DEEPSEEK_API_MODEL: str = Field( default="deepseek-reasoner", description="API请求的模型名称,默认为 deepseek-reasoner ", ) def __init__(self): self.valves = self.Valves() self.data_prefix = "data: " self.thinking = -1 # -1:未开始 0:思考中 1:已回答 self.emitter = None def pipes(self): return [ { "id": self.valves.DEEPSEEK_API_MODEL, "name": self.valves.DEEPSEEK_API_MODEL, } ] async def pipe( self, body: dict, __event_emitter__: Callable[[dict], Awaitable[None]] = None ) -> AsyncGenerator[str, None]: """主处理管道(已移除缓冲)""" self.thinking = -1 self.emitter = __event_emitter__ # 验证配置 if not self.valves.DEEPSEEK_API_KEY: yield json.dumps({"error": "未配置API密钥"}, ensure_ascii=False) return # 准备请求参数 headers = { "Authorization": f"Bearer {self.valves.DEEPSEEK_API_KEY}", "Content-Type": "application/json", } try: # 模型ID提取 model_id = body["model"].split(".", 1)[-1] payload = {**body, "model": model_id} # 处理消息以防止连续的相同角色 messages = payload["messages"] i = 0 while i < len(messages) - 1: if messages[i]["role"] == messages[i + 1]["role"]: # 插入具有替代角色的占位符消息 alternate_role = ( "assistant" if messages[i]["role"] == "user" else "user" ) messages.insert( i + 1, {"role": alternate_role, "content": "[Unfinished thinking]"}, ) i += 1 # yield json.dumps(payload, ensure_ascii=False) # 发起API请求 async with httpx.AsyncClient(http2=True) as client: async with client.stream( "POST", f"{self.valves.DEEPSEEK_API_BASE_URL}/chat/completions", json=payload, headers=headers, timeout=300, ) as response: # 错误处理 if response.status_code != 200: error = await response.aread() yield self._format_error(response.status_code, error) return # 流式处理响应 async for line in response.aiter_lines(): if not line.startswith(self.data_prefix): continue # 截取 JSON 字符串 json_str = line[len(self.data_prefix) :] try: data = json.loads(json_str) except json.JSONDecodeError as e: # 格式化错误信息,这里传入错误类型和详细原因(包括出错内容和异常信息) error_detail = f"解析失败 - 内容:{json_str},原因:{e}" yield self._format_error("JSONDecodeError", error_detail) return choice = data.get("choices", [{}])[0] # 结束条件判断 if choice.get("finish_reason"): return # 状态机处理 state_output = await self._update_thinking_state( choice.get("delta", {}) ) if state_output: yield state_output # 直接发送状态标记 if state_output == "<think>": yield "\n" # 内容处理并立即发送 content = self._process_content(choice["delta"]) if content: if content.startswith("<think>"): match = re.match(r"^<think>", content) if match: content = re.sub(r"^<think>", "", content) yield "<think>" await asyncio.sleep(0.1) yield "\n" elif content.startswith("</think>"): match = re.match(r"^</think>", content) if match: content = re.sub(r"^</think>", "", content) yield "</think>" await asyncio.sleep(0.1) yield "\n" yield content except Exception as e: yield self._format_exception(e) async def _update_thinking_state(self, delta: dict) -> str: """更新思考状态机(简化版)""" state_output = "" # 状态转换:未开始 -> 思考中 if self.thinking == -1 and delta.get("reasoning_content"): self.thinking = 0 state_output = "<think>" # 状态转换:思考中 -> 已回答 elif ( self.thinking == 0 and not delta.get("reasoning_content") and delta.get("content") ): self.thinking = 1 state_output = "\n</think>\n\n" return state_output def _process_content(self, delta: dict) -> str: """直接返回处理后的内容""" return delta.get("reasoning_content", "") or delta.get("content", "") def _format_error(self, status_code: int, error: bytes) -> str: """错误格式化保持不变""" try: err_msg = json.loads(error).get("message", error.decode(errors="ignore"))[ :200 ] except: err_msg = error.decode(errors="ignore")[:200] return json.dumps( {"error": f"HTTP {status_code}: {err_msg}"}, ensure_ascii=False ) def _format_exception(self, e: Exception) -> str: """异常格式化保持不变""" err_type = type(e).__name__ return json.dumps({"error": f"{err_type}: {str(e)}"}, ensure_ascii=False)

保存函数,配置函数参数:

image.png

使用

可以自己修改一个模型名称便于认识,然后这个函数就可以显示出思考过程了。

image.png

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!