import shutil # 导入shutil模块,用于查找系统中的可执行文件
import asyncio # 导入asyncio模块,用于编写异步代码
import argparse # 导入argparse模块,用于解析命令行参数
import ollama # 导入ollama模块,用于与Ollama服务器交互
# 定义一个异步函数speak,用于执行语音合成
async def speak(speaker, content):
if speaker:
# 使用asyncio创建一个子进程,执行speaker命令并传入content
p = await asyncio.create_subprocess_exec(speaker, content)
await p.communicate()
# 定义一个异步函数main,作为程序的入口点
async def main():
parser = argparse.ArgumentParser() # 创建一个argparse解析器
parser.add_argument('--speak', default=False, action='store_true') # 添加一个命令行参数,用于控制是否需要语音合成
args = parser.parse_args() # 解析命令行参数
speaker = None # 初始化speaker变量为None
if not args.speak: # 如果不需要语音合成
... # 执行某些操作(代码省略)
elif say := shutil.which('say'): # 查找系统中是否存在'say'命令
speaker = say # 如果找到,设置speaker变量为'say'命令的路径
elif (espeak := shutil.which('espeak')) or (espeak := shutil.which('espeak-ng')): # 查找系统中是否存在'espeak'或'espeak-ng'命令
speaker = espeak # 如果找到,设置speaker变量为'espeak'或'espeak-ng'命令的路径
client = ollama.AsyncClient() # 创建一个异步Ollama客户端实例
messages = [] # 初始化一个消息列表
while True: # 无限循环
if content_in := input('>>> '): # 从用户输入获取消息
messages.append({'role': 'user', 'content': content_in}) # 将消息添加到消息列表
content_out = '' # 初始化内容输出变量
message = {'role': 'assistant', 'content': ''} # 初始化消息变量
async for response in await client.chat(model='qwen:14b', messages=messages, stream=True): # 异步发送聊天请求
if response['done']: # 如果响应表示聊天结束
messages.append(message) # 将消息添加到消息列表
content = response['message']['content'] # 获取聊天内容
print(content, end='', flush=True) # 打印聊天内容
content_out += content # 更新内容输出变量
if content in ['.', '!', '?', '\n']: # 如果聊天内容是句点、感叹号、问号或换行符
await speak(speaker, content_out) # 异步执行语音合成
content_out = '' # 清空内容输出变量
message['content'] += content # 更新消息变量
if content_out: # 如果内容输出变量不为空
await speak(speaker, content_out) # 异步执行语音合成
content_out = '' # 清空内容输出变量
print() # 打印换行符
try:
asyncio.run(main()) # 使用asyncio运行main函数
except (KeyboardInterrupt, EOFError): # 捕获键盘中断或文件结束错误
... # 执行某些操作(代码省略)
这段Python代码是一个简单的异步聊天程序,它使用ollama
库与Ollama服务器进行交互