Compare commits

..
2 Commits
Author SHA1 Message Date
8376b6f0f2 更新GPT_SOVITS_V3接口 (#375)
* ollama去除回复中的think字段 (#373)

* ollama调用修复,并且去除回复中的think字段(deepseek)

* ollama调用修复,并且去除回复中的think字段(deepseek)

* ollama去除回复中的think字段(deepseek)
deepseek 14b,qwen2.5测试通过

* ollama去除回复中的think字段(deepseek)
deepseek 14b,qwen2.5测试通过

* Update ollama.py

---------

Co-authored-by: aileenfun <105077614@qq.com>
Co-authored-by: 欣南科技 <huangrongzhuang@xin-nan.com>

* fix:GPT_SOVITS_V3-20250228 API (#312)

---------

Co-authored-by: aileenfun <alanliu0618@gmail.com>
Co-authored-by: aileenfun <105077614@qq.com>
Co-authored-by: Miyo <101488652+Miyokiss@users.noreply.github.com>
2025-03-16 16:04:27 +08:00
490a66d3fe Add deploy pic (#354)
* update:添加部署方案图

* update:部署参考图

---------

Co-authored-by: hrz <1710360675@qq.com>
2025-03-15 16:17:25 +08:00
6 changed files with 56 additions and 39 deletions
+7 -5
View File
@@ -92,9 +92,11 @@
- **硬件**:一套兼容 `xiaozhi-esp32`
的硬件设备(具体型号请参考 [此处](https://rcnv1t9vps13.feishu.cn/wiki/DdgIw4BUgivWDPkhMj1cGIYCnRf))。
- **电脑或服务器**至少 4 核 CPU、8G 内存的电脑。
- **电脑或服务器**建议 4 核 CPU、8G 内存的电脑。如果开启ASR也使用API,可运行在2核CPU、2G内存的服务器中。
- **固件编译**:请将本后端服务的接口地址更新至 `xiaozhi-esp32` 项目中,再重新编译`xiaozhi-esp32`固件并烧录到设备上。
![图片](docs/images/deploy.png)
如果你没有esp32相关的硬件设备,但是非常想体验该项目,可以使用以下的项目让你的电脑、手机模拟成esp32设备。
- [小智安卓端](https://github.com/TOM88812/xiaozhi-android-client)
@@ -212,10 +214,10 @@ server:
### Memory 记忆存储
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|:------:|:---------------:|:----:|:--------:|:--:|
| Memory | mem0ai | 接口调用 | 100次/月额度 | |
| Memory | mem_local_short | 本地总结 | 免费 | |
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|:------:|:---------------:|:----:|:---------:|:--:|
| Memory | mem0ai | 接口调用 | 1000次/月额度 | |
| Memory | mem_local_short | 本地总结 | 免费 | |
---
+2
View File
@@ -1,3 +1,5 @@
# 部署方案参考
![图片](images/deploy.png)
# 方式一:docker快速部署
docker镜像已支持x86架构、arm64架构的CPU,支持在国产操作系统上运行。
Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

+15 -11
View File
@@ -306,20 +306,24 @@ TTS:
repetition_penalty: 1.35
aux_ref_audio_paths: []
GPT_SOVITS_V3:
# 定义TTS API类型 GPT-SoVITS-v3lora-20250228
#启动tts方法:
#python api.py
type: gpt_sovits_v3
url: "http://127.0.0.1:9880/tts"
url: "http://127.0.0.1:9880"
output_file: tmp/
text_lang: "auto"
ref_audio_path: "caixukun.wav"
prompt_lang: "zh"
text_language: "auto"
refer_wav_path: "caixukun.wav"
prompt_language: "zh"
prompt_text: ""
top_k: 5
top_p: 1
temperature: 1
sample_steps: 16
media_type: "wav"
streaming_mode: false
threshold: 30
top_k: 15
top_p: 1.0
temperature: 1.0
cut_punc: ""
speed: 1.0
inp_refs: []
sample_steps: 32
if_sr: false
MinimaxTTS:
# Minimax语音合成服务,需要先在minimax平台创建账户充值,并获取登录信息
# 平台地址:https://platform.minimaxi.com/
@@ -12,10 +12,10 @@ class LLMProvider(LLMProviderBase):
self.model_name = config.get("model_name")
self.base_url = config.get("base_url", "http://localhost:11434")
# Initialize OpenAI client with Ollama base URL
#如果没有v1,增加v1
# 如果没有v1,增加v1
if not self.base_url.endswith("/v1"):
self.base_url = f"{self.base_url}/v1"
self.client = OpenAI(
base_url=self.base_url,
api_key="ollama" # Ollama doesn't need an API key but OpenAI client requires one
@@ -28,13 +28,20 @@ class LLMProvider(LLMProviderBase):
messages=dialogue,
stream=True
)
is_active=True
for chunk in responses:
try:
delta = chunk.choices[0].delta if getattr(chunk, 'choices', None) else None
content = delta.content if hasattr(delta, 'content') else ''
if content:
yield content
if '<think>' in content:
is_active = False
content = content.split('<think>')[0]
if '</think>' in content:
is_active = True
content = content.split('</think>')[-1]
if is_active:
yield content
except Exception as e:
logger.bind(tag=TAG).error(f"Error processing chunk: {e}")
@@ -50,10 +57,10 @@ class LLMProvider(LLMProviderBase):
stream=True,
tools=functions,
)
for chunk in stream:
yield chunk.choices[0].delta.content, chunk.choices[0].delta.tool_calls
except Exception as e:
logger.bind(tag=TAG).error(f"Error in Ollama function call: {e}")
yield {"type": "content", "content": f"【Ollama服务响应异常: {str(e)}"}
yield {"type": "content", "content": f"【Ollama服务响应异常: {str(e)}"}
@@ -12,17 +12,18 @@ class TTSProvider(TTSProviderBase):
def __init__(self, config, delete_audio_file):
super().__init__(config, delete_audio_file)
self.url = config.get("url")
self.text_lang = config.get("text_lang", "audo")
self.ref_audio_path = config.get("ref_audio_path")
self.prompt_lang = config.get("prompt_lang")
self.refer_wav_path = config.get("refer_wav_path")
self.prompt_text = config.get("prompt_text")
self.top_k = config.get("top_k", 5)
self.top_p = config.get("top_p", 1)
self.temperature = config.get("temperature", 1)
self.sample_steps = config.get("sample_steps", 16)
self.media_type = config.get("media_type", "wav")
self.streaming_mode = config.get("streaming_mode", False)
self.threshold = config.get("threshold", 30)
self.prompt_language = config.get("prompt_language")
self.text_language = config.get("text_language", "audo")
self.top_k = config.get("top_k", 15)
self.top_p = config.get("top_p", 1.0)
self.temperature = config.get("temperature", 1.0)
self.cut_punc = config.get("cut_punc","")
self.speed = config.get("speed", 1.0)
self.inp_refs = config.get("inp_refs",[])
self.sample_steps = config.get("inp_refs",32)
self.if_sr = config.get("if_sr",False)
def generate_filename(self, extension=".wav"):
@@ -30,18 +31,19 @@ class TTSProvider(TTSProviderBase):
async def text_to_speak(self, text, output_file):
request_params = {
"text": text,
"text_lang": self.text_lang,
"ref_audio_path": self.ref_audio_path,
"prompt_lang": self.prompt_lang,
"refer_wav_path": self.refer_wav_path,
"prompt_text": self.prompt_text,
"prompt_language": self.prompt_language,
"text": text,
"text_language": self.text_language,
"top_k": self.top_k,
"top_p": self.top_p,
"temperature": self.temperature,
"cut_punc": self.cut_punc,
"speed": self.speed,
"inp_refs": self.inp_refs,
"sample_steps": self.sample_steps,
"media_type": self.media_type,
"streaming_mode": self.streaming_mode,
"threshold": self.threshold,
"if_sr": self.if_sr,
}
resp = requests.get(self.url, params=request_params)