2022-12-18 14:03:34 +08:00
# encoding:utf-8
2026-01-30 09:53:46 +08:00
import copy
2022-12-13 01:50:43 +08:00
import json
2023-04-04 14:02:14 +08:00
import logging
2022-12-13 01:50:43 +08:00
import os
2023-04-04 00:59:21 +08:00
import pickle
2022-12-13 01:50:43 +08:00
2023-04-17 01:00:08 +08:00
from common . log import logger
2023-03-26 03:31:29 +08:00
# 将所有可用的配置项写在字典里, 请使用小写字母
2023-04-25 23:58:46 +08:00
# 此处的配置值无实际意义, 程序不会读取此处的配置, 仅用于提示格式, 请将配置加入到config.json中
2023-03-27 14:40:19 +08:00
available_setting = {
# openai api配置
" open_ai_api_key " : " " , # openai api key
# openai apibase, 当use_azure_chatgpt为true时, 需要设置对应的api base
" open_ai_api_base " : " https://api.openai.com/v1 " ,
2026-02-02 11:48:53 +08:00
" claude_api_base " : " https://api.anthropic.com/v1 " , # claude api base
" gemini_api_base " : " https://generativelanguage.googleapis.com " , # gemini api base
2023-03-27 14:40:19 +08:00
" proxy " : " " , # openai使用的代理
# chatgpt模型, 当use_azure_chatgpt为true时, 其名称为Azure上model deployment名称
2024-07-19 11:04:45 +08:00
" model " : " gpt-3.5-turbo " , # 可选择: gpt-4o, pt-4o-mini, gpt-4-turbo, claude-3-sonnet, wenxin, moonshot, qwen-turbo, xunfei, glm-4, minimax, gemini等模型, 全部可选模型详见common/const.py文件
2024-06-13 16:43:03 +08:00
" bot_type " : " " , # 可选配置, 使用兼容openai格式的三方服务时候, 需填"chatGPT"。bot具体名称详见common/const.py文件列出的bot_type, 如不填根据model名称判断,
2023-03-27 14:40:19 +08:00
" use_azure_chatgpt " : False , # 是否使用azure的chatgpt
2023-04-17 01:00:08 +08:00
" azure_deployment_id " : " " , # azure 模型部署名称
2023-07-24 15:44:03 +08:00
" azure_api_version " : " " , # azure api版本
2023-03-27 14:40:19 +08:00
# Bot触发配置
" single_chat_prefix " : [ " bot " , " @bot " ] , # 私聊时文本需要包含该前缀才能触发机器人回复
" single_chat_reply_prefix " : " [bot] " , # 私聊时自动回复的前缀,用于区分真人
2023-08-30 20:49:00 +08:00
" single_chat_reply_suffix " : " " , # 私聊时自动回复的后缀,\n 可以换行
" group_chat_prefix " : [ " @bot " ] , # 群聊时包含该前缀则会触发机器人回复
2024-08-25 15:13:25 +08:00
" no_need_at " : False , # 群聊回复时是否不需要艾特
2023-03-27 14:40:19 +08:00
" group_chat_reply_prefix " : " " , # 群聊时自动回复的前缀
2023-07-20 11:36:02 +08:00
" group_chat_reply_suffix " : " " , # 群聊时自动回复的后缀,\n 可以换行
2023-03-27 14:40:19 +08:00
" group_chat_keyword " : [ ] , # 群聊时包含该关键词则会触发机器人回复
" group_at_off " : False , # 是否关闭群聊时@bot的触发
" group_name_white_list " : [ " ChatGPT测试群 " , " ChatGPT测试群2 " ] , # 开启自动回复的群名称列表
" group_name_keyword_white_list " : [ ] , # 开启自动回复的群名称关键词列表
" group_chat_in_one_session " : [ " ChatGPT测试群 " ] , # 支持会话上下文共享的群名称
2026-03-12 17:08:09 +08:00
" group_shared_session " : False , # 群聊是否共享会话上下文( 所有成员共享) 。False时每个用户在群内有独立会话
2023-11-27 14:38:45 +08:00
" nick_name_black_list " : [ ] , # 用户昵称黑名单
2024-06-12 19:14:09 +08:00
" group_welcome_msg " : " " , # 配置新人进群固定欢迎语,不配置则使用随机风格欢迎
2023-04-03 23:58:19 +08:00
" trigger_by_self " : False , # 是否允许机器人触发
2023-11-10 10:11:02 +08:00
" text_to_image " : " dall-e-2 " , # 图片生成模型,可选 dall-e-2, dall-e-3
2024-03-12 08:32:24 +08:00
# Azure OpenAI dall-e-3 配置
" dalle3_image_style " : " vivid " , # 图片生成dalle3的风格, 可选有 vivid, natural
" dalle3_image_quality " : " hd " , # 图片生成dalle3的质量, 可选有 standard, hd
# Azure OpenAI DALL-E API 配置, 当use_azure_chatgpt为true时,用于将文字回复的资源和Dall-E的资源分开.
" azure_openai_dalle_api_base " : " " , # [可选] azure openai 用于回复图片的资源 endpoint, 默认使用 open_ai_api_base
" azure_openai_dalle_api_key " : " " , # [可选] azure openai 用于回复图片的资源 key, 默认使用 open_ai_api_key
" azure_openai_dalle_deployment_id " : " " , # [可选] azure openai 用于回复图片的资源 deployment id, 默认使用 text_to_image
2023-11-10 10:11:02 +08:00
" image_proxy " : True , # 是否需要图片代理, 国内访问LinkAI时需要
2023-03-27 14:40:19 +08:00
" image_create_prefix " : [ " 画 " , " 看 " , " 找 " ] , # 开启图片回复的前缀
2023-04-17 01:00:08 +08:00
" concurrency_in_session " : 1 , # 同一会话最多有多少条消息在处理中, 大于1可能乱序
2023-11-10 10:11:02 +08:00
" image_create_size " : " 256x256 " , # 图片大小,可选有 256x256, 512x512, 1024x1024 (dall-e-3默认为1024x1024)
2024-06-12 19:14:09 +08:00
" group_chat_exit_group " : False ,
2023-03-27 14:40:19 +08:00
# chatgpt会话参数
" expires_in_seconds " : 3600 , # 无操作会话的过期时间
2023-07-20 11:36:02 +08:00
# 人格描述
" character_desc " : " 你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。 " ,
2023-03-27 14:40:19 +08:00
" conversation_max_tokens " : 1000 , # 支持上下文记忆的最多字符数
# chatgpt限流配置
" rate_limit_chatgpt " : 20 , # chatgpt的调用频率限制
" rate_limit_dalle " : 50 , # openai dalle的调用频率限制
# chatgpt api参数 参考https://platform.openai.com/docs/api-reference/chat/create
2023-03-25 18:08:37 +08:00
" temperature " : 0.9 ,
" top_p " : 1 ,
" frequency_penalty " : 0 ,
" presence_penalty " : 0 ,
2023-11-17 16:27:44 +08:00
" request_timeout " : 180 , # chatgpt请求超时时间, openai接口默认设置为600, 对于难问题一般需要较长时间
2023-04-17 01:00:08 +08:00
" timeout " : 120 , # chatgpt重试超时时间, 在这个时间内, 将会自动重试
2023-07-25 09:52:47 +08:00
# Baidu 文心一言参数
2023-08-25 16:06:55 +08:00
" baidu_wenxin_model " : " eb-instant " , # 默认使用ERNIE-Bot-turbo模型
" baidu_wenxin_api_key " : " " , # Baidu api key
" baidu_wenxin_secret_key " : " " , # Baidu secret key
2024-08-16 14:58:17 +08:00
" baidu_wenxin_prompt_enabled " : False , # Enable prompt if you are using ernie character model
2023-08-25 16:06:55 +08:00
# 讯飞星火API
" xunfei_app_id " : " " , # 讯飞应用ID
" xunfei_api_key " : " " , # 讯飞 API key
" xunfei_api_secret " : " " , # 讯飞 API secret
2024-08-01 17:57:48 +08:00
" xunfei_domain " : " " , # 讯飞模型对应的domain参数, Spark4.0 Ultra为 4.0Ultra,其他模型详见: https://www.xfyun.cn/doc/spark/Web.html
" xunfei_spark_url " : " " , # 讯飞模型对应的请求地址, Spark4.0 Ultra为 wss://spark-api.xf-yun.com/v4.0/chat, 其他模型参考详见: https://www.xfyun.cn/doc/spark/Web.html
2023-09-01 11:32:58 +08:00
# claude 配置
" claude_api_cookie " : " " ,
" claude_uuid " : " " ,
2024-03-12 10:39:51 +08:00
# claude api key
2024-06-12 19:14:09 +08:00
" claude_api_key " : " " ,
2023-11-19 22:42:44 +08:00
# 通义千问API, 获取方式查看文档 https://help.aliyun.com/document_detail/2587494.html
2023-12-08 14:12:21 +08:00
" qwen_access_key_id " : " " ,
" qwen_access_key_secret " : " " ,
" qwen_agent_key " : " " ,
" qwen_app_id " : " " ,
" qwen_node_id " : " " , # 流程编排模型用到的id, 如果没有用到qwen_node_id, 请务必保持为空字符串
2024-06-05 00:44:08 +08:00
# 阿里灵积(通义新版sdk)模型api key
2024-03-27 18:56:08 +08:00
" dashscope_api_key " : " " ,
2023-12-15 10:19:48 +08:00
# Google Gemini Api Key
" gemini_api_key " : " " ,
2023-09-01 11:32:58 +08:00
# wework的通用配置
" wework_smart " : True , # 配置wework是否使用已登录的企业微信, False为多开
2023-03-27 14:40:19 +08:00
# 语音设置
2023-11-10 10:11:02 +08:00
" speech_recognition " : True , # 是否开启语音识别
2023-03-27 14:40:19 +08:00
" group_speech_recognition " : False , # 是否开启群组语音识别
" voice_reply_voice " : False , # 是否使用语音回复语音, 需要设置对应语音合成引擎的api key
2023-04-01 22:27:11 +08:00
" always_reply_voice " : False , # 是否一直使用语音回复
2024-07-19 15:46:19 +08:00
" voice_to_text " : " openai " , # 语音识别引擎, 支持openai,baidu,google,azure,xunfei,ali
" text_to_voice " : " openai " , # 语音合成引擎, 支持openai,baidu,google,azure,xunfei,ali,pytts(offline),elevenlabs,edge(online)
2023-11-10 10:48:52 +08:00
" text_to_voice_model " : " tts-1 " ,
2023-11-10 10:11:02 +08:00
" tts_voice_id " : " alloy " ,
2023-04-01 16:36:27 +08:00
# baidu 语音api配置, 使用百度语音识别和语音合成时需要
2023-03-27 14:40:19 +08:00
" baidu_app_id " : " " ,
" baidu_api_key " : " " ,
" baidu_secret_key " : " " ,
# 1536普通话(支持简单的英文识别) 1737英语 1637粤语 1837四川话 1936普通话远场
2024-05-21 22:32:35 +08:00
" baidu_dev_pid " : 1536 ,
2023-04-01 16:36:27 +08:00
# azure 语音api配置, 使用azure语音识别和语音合成时需要
" azure_voice_api_key " : " " ,
" azure_voice_region " : " japaneast " ,
2023-08-19 11:20:47 +08:00
# elevenlabs 语音api配置
2024-06-12 19:14:09 +08:00
" xi_api_key " : " " , # 获取ap的方法可以参考https://docs.elevenlabs.io/api-reference/quick-start/authentication
" xi_voice_id " : " " , # ElevenLabs提供了9种英式、美式等英语发音id, 分别是“Adam/Antoni/Arnold/Bella/Domi/Elli/Josh/Rachel/Sam”
2023-03-27 14:40:19 +08:00
# 服务时间限制, 目前支持itchat
" chat_time_module " : False , # 是否开启服务时间限制
" chat_start_time " : " 00:00 " , # 服务开始时间
" chat_stop_time " : " 24:00 " , # 服务结束时间
2023-04-23 03:51:09 +08:00
# 翻译api
" translate " : " baidu " , # 翻译api, 支持baidu
# baidu翻译api的配置
" baidu_translate_app_id " : " " , # 百度翻译api的appid
" baidu_translate_app_key " : " " , # 百度翻译api的秘钥
2023-03-25 18:08:37 +08:00
# itchat的配置
2023-03-27 14:40:19 +08:00
" hot_reload " : False , # 是否开启热重载
2023-03-25 19:14:20 +08:00
# wechaty的配置
2023-03-27 14:40:19 +08:00
" wechaty_puppet_service_token " : " " , # wechaty的token
2023-03-30 01:01:00 +08:00
# wechatmp的配置
2023-04-17 01:00:08 +08:00
" wechatmp_token " : " " , # 微信公众平台的Token
" wechatmp_port " : 8080 , # 微信公众平台的端口,需要端口转发到80或443
2023-04-22 02:29:50 +08:00
" wechatmp_app_id " : " " , # 微信公众平台的appID
" wechatmp_app_secret " : " " , # 微信公众平台的appsecret
" wechatmp_aes_key " : " " , # 微信公众平台的EncodingAESKey, 加密模式需要
2023-04-20 08:31:42 +08:00
# wechatcom的通用配置
" wechatcom_corp_id " : " " , # 企业微信公司的corpID
# wechatcomapp的配置
" wechatcomapp_token " : " " , # 企业微信app的token
" wechatcomapp_port " : 9898 , # 企业微信app的服务端口,不需要端口转发
" wechatcomapp_secret " : " " , # 企业微信app的secret
" wechatcomapp_agent_id " : " " , # 企业微信app的agent_id
" wechatcomapp_aes_key " : " " , # 企业微信app的aes_key
2023-11-21 22:41:54 +08:00
# 飞书配置
" feishu_port " : 80 , # 飞书bot监听端口
2023-11-23 22:05:10 +08:00
" feishu_app_id " : " " , # 飞书机器人应用APP Id
" feishu_app_secret " : " " , # 飞书机器人APP secret
" feishu_token " : " " , # 飞书 verification token
" feishu_bot_name " : " " , # 飞书机器人的名字
2026-01-31 12:32:41 +08:00
" feishu_event_mode " : " websocket " , # 飞书事件接收模式: webhook(HTTP服务器) 或 websocket(长连接)
2023-11-30 10:41:34 +08:00
# 钉钉配置
2023-12-17 09:23:15 +08:00
" dingtalk_client_id " : " " , # 钉钉机器人Client ID
2024-06-04 11:23:45 +08:00
" dingtalk_client_secret " : " " , # 钉钉机器人Client Secret
" dingtalk_card_enabled " : False ,
2023-11-30 10:41:34 +08:00
2023-03-25 18:08:37 +08:00
# chatgpt指令自定义触发词
2023-04-17 01:00:08 +08:00
" clear_memory_commands " : [ " #清除记忆 " ] , # 重置会话指令,必须以#开头
2023-03-30 16:06:57 +08:00
# channel配置
2026-02-26 18:34:08 +08:00
" channel_type " : " " , # 通道类型,支持多渠道同时运行。单个: "feishu",多个: "feishu, dingtalk" 或 ["feishu", "dingtalk"]。可选值: web,feishu,dingtalk,wechatmp,wechatmp_service,wechatcom_app
" web_console " : True , # 是否自动启动Web控制台( 默认启动) 。设为False可禁用
2023-04-25 23:58:46 +08:00
" subscribe_msg " : " " , # 订阅消息, 支持: wechatmp, wechatmp_service, wechatcom_app
2023-04-04 14:02:14 +08:00
" debug " : False , # 是否开启debug模式, 开启后会打印更多日志
2023-04-17 01:24:39 +08:00
" appdata_dir " : " " , # 数据目录
2023-04-05 05:37:06 +08:00
# 插件配置
" plugin_trigger_prefix " : " $ " , # 规范插件提供聊天相关指令的前缀,建议不要和管理员指令前缀"#"冲突
2023-07-28 16:33:41 +08:00
# 是否使用全局插件配置
" use_global_plugin_config " : False ,
2024-06-12 19:14:09 +08:00
" max_media_send_count " : 3 , # 单次最大发送媒体资源的个数
2024-01-29 11:46:00 +08:00
" media_send_interval " : 1 , # 发送图片的事件间隔,单位秒
2024-02-05 12:15:28 +08:00
# 智谱AI 平台配置
" zhipu_ai_api_key " : " " ,
" zhipu_ai_api_base " : " https://open.bigmodel.cn/api/paas/v4 " ,
2024-03-27 15:02:51 +08:00
" moonshot_api_key " : " " ,
2026-02-14 15:27:44 +08:00
" moonshot_base_url " : " https://api.moonshot.cn/v1 " ,
2026-02-15 00:02:50 +08:00
# 豆包(火山方舟) 平台配置
" ark_api_key " : " " ,
" ark_base_url " : " https://ark.cn-beijing.volces.com/api/v3 " ,
2025-03-11 11:12:57 +08:00
#魔搭社区 平台配置
" modelscope_api_key " : " " ,
" modelscope_base_url " : " https://api-inference.modelscope.cn/v1/chat/completions " ,
2024-01-29 11:46:00 +08:00
# LinkAI平台配置
2023-06-08 23:57:59 +08:00
" use_linkai " : False ,
2023-05-29 15:52:26 +08:00
" linkai_api_key " : " " ,
2023-08-22 11:09:01 +08:00
" linkai_app_code " : " " ,
2024-05-03 14:10:07 +08:00
" linkai_api_base " : " https://api.link-ai.tech " , # linkAI服务地址
2026-02-23 15:06:31 +08:00
" cloud_host " : " client.link-ai.tech " ,
2026-03-11 19:42:37 +08:00
" cloud_deployment_id " : " " ,
2026-02-03 00:43:42 +08:00
" minimax_api_key " : " " ,
2024-06-12 19:14:09 +08:00
" Minimax_group_id " : " " ,
" Minimax_base_url " : " " ,
2024-11-26 14:09:20 +08:00
" web_port " : 9899 ,
2026-02-02 11:58:19 +08:00
" agent " : True , # 是否开启Agent模式
2026-02-01 12:31:58 +08:00
" agent_workspace " : " ~/cow " , # agent工作空间路径, 用于存储skills、memory等
2026-02-03 02:58:15 +08:00
" agent_max_context_tokens " : 50000 , # Agent模式下最大上下文tokens
2026-02-02 12:03:16 +08:00
" agent_max_context_turns " : 30 , # Agent模式下最大上下文记忆轮次
" agent_max_steps " : 15 , # Agent模式下单次运行最大决策步数
2023-03-25 18:08:37 +08:00
}
2023-03-27 14:40:19 +08:00
2023-03-25 18:08:37 +08:00
class Config ( dict ) :
2023-04-25 23:58:46 +08:00
def __init__ ( self , d = None ) :
super ( ) . __init__ ( )
if d is None :
d = { }
for k , v in d . items ( ) :
self [ k ] = v
2023-04-04 00:59:21 +08:00
# user_datas: 用户数据, key为用户名, value为用户数据, 也是dict
self . user_datas = { }
2023-03-25 18:08:37 +08:00
def __getitem__ ( self , key ) :
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if not key . startswith ( " _ " ) and key not in available_setting :
2026-02-02 11:48:53 +08:00
logger . warning ( " [Config] key ' {} ' not in available_setting, may not take effect " . format ( key ) )
2023-03-25 18:08:37 +08:00
return super ( ) . __getitem__ ( key )
def __setitem__ ( self , key , value ) :
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if not key . startswith ( " _ " ) and key not in available_setting :
2026-02-02 11:48:53 +08:00
logger . warning ( " [Config] key ' {} ' not in available_setting, may not take effect " . format ( key ) )
2023-03-25 18:08:37 +08:00
return super ( ) . __setitem__ ( key , value )
def get ( self , key , default = None ) :
2026-01-31 12:50:21 +08:00
# 跳过以下划线开头的注释字段
if key . startswith ( " _ " ) :
return super ( ) . get ( key , default )
# 如果key不在available_setting中, 直接返回default
if key not in available_setting :
return super ( ) . get ( key , default )
2023-03-27 14:40:19 +08:00
try :
2023-03-25 18:08:37 +08:00
return self [ key ]
except KeyError as e :
return default
except Exception as e :
raise e
2023-03-27 14:40:19 +08:00
2023-04-04 00:59:21 +08:00
# Make sure to return a dictionary to ensure atomic
def get_user_data ( self , user ) - > dict :
if self . user_datas . get ( user ) is None :
self . user_datas [ user ] = { }
return self . user_datas [ user ]
def load_user_datas ( self ) :
try :
2023-04-17 01:24:39 +08:00
with open ( os . path . join ( get_appdata_dir ( ) , " user_datas.pkl " ) , " rb " ) as f :
2023-04-04 00:59:21 +08:00
self . user_datas = pickle . load ( f )
2026-02-02 12:18:57 +08:00
logger . debug ( " [Config] User datas loaded. " )
2023-04-04 00:59:21 +08:00
except FileNotFoundError as e :
2026-02-07 11:17:58 +08:00
logger . debug ( " [Config] User datas file not found, ignore. " )
2023-04-04 00:59:21 +08:00
except Exception as e :
2026-02-07 11:17:58 +08:00
logger . warning ( " [Config] User datas error: {} " . format ( e ) )
2023-04-04 00:59:21 +08:00
self . user_datas = { }
def save_user_datas ( self ) :
try :
2023-04-17 01:24:39 +08:00
with open ( os . path . join ( get_appdata_dir ( ) , " user_datas.pkl " ) , " wb " ) as f :
2023-04-04 00:59:21 +08:00
pickle . dump ( self . user_datas , f )
logger . info ( " [Config] User datas saved. " )
except Exception as e :
logger . info ( " [Config] User datas error: {} " . format ( e ) )
2023-03-27 14:40:19 +08:00
2023-04-17 01:00:08 +08:00
2023-03-25 18:08:37 +08:00
config = Config ( )
2022-12-13 01:50:43 +08:00
2023-03-27 14:40:19 +08:00
2024-05-13 19:53:33 +08:00
def drag_sensitive ( config ) :
2024-06-04 12:50:59 +08:00
try :
if isinstance ( config , str ) :
conf_dict : dict = json . loads ( config )
conf_dict_copy = copy . deepcopy ( conf_dict )
for key in conf_dict_copy :
if " key " in key or " secret " in key :
2024-06-24 21:57:58 +08:00
if isinstance ( conf_dict_copy [ key ] , str ) :
2024-06-04 12:50:59 +08:00
conf_dict_copy [ key ] = conf_dict_copy [ key ] [ 0 : 3 ] + " * " * 5 + conf_dict_copy [ key ] [ - 3 : ]
return json . dumps ( conf_dict_copy , indent = 4 )
2024-05-13 19:53:33 +08:00
2024-06-04 12:50:59 +08:00
elif isinstance ( config , dict ) :
config_copy = copy . deepcopy ( config )
for key in config :
if " key " in key or " secret " in key :
2024-06-24 21:57:58 +08:00
if isinstance ( config_copy [ key ] , str ) :
2024-06-04 12:50:59 +08:00
config_copy [ key ] = config_copy [ key ] [ 0 : 3 ] + " * " * 5 + config_copy [ key ] [ - 3 : ]
return config_copy
except Exception as e :
logger . exception ( e )
return config
2024-05-13 19:53:33 +08:00
return config
2022-12-13 01:50:43 +08:00
def load_config ( ) :
global config
2026-02-02 12:18:57 +08:00
# 打印 ASCII Logo
logger . info ( " ____ _ _ " )
logger . info ( " / ___|_____ __ / \\ __ _ ___ _ __ | |_ " )
logger . info ( " | | / _ \\ \\ / \\ / // _ \\ / _` |/ _ \\ ' _ \\ | __| " )
logger . info ( " | |__| (_) \\ V V // ___ \\ (_| | __/ | | | |_ " )
logger . info ( " \\ ____ \\ ___/ \\ _/ \\ _//_/ \\ _ \\ __, | \\ ___|_| |_| \\ __| " )
logger . info ( " |___/ " )
2026-02-02 12:25:47 +08:00
logger . info ( " " )
2023-03-23 00:36:41 +08:00
config_path = " ./config.json "
2022-12-19 01:25:34 +08:00
if not os . path . exists ( config_path ) :
2023-04-17 01:00:08 +08:00
logger . info ( " 配置文件不存在, 将使用config-template.json模板 " )
2023-03-25 10:02:19 +08:00
config_path = " ./config-template.json "
2022-12-19 01:25:34 +08:00
config_str = read_file ( config_path )
2024-06-04 12:50:59 +08:00
logger . debug ( " [INIT] config str: {} " . format ( drag_sensitive ( config_str ) ) )
2023-03-26 02:00:35 +08:00
2022-12-19 01:25:34 +08:00
# 将json字符串反序列化为dict类型
2023-03-25 18:08:37 +08:00
config = Config ( json . loads ( config_str ) )
2023-03-25 10:02:19 +08:00
# override config with environment variables.
# Some online deployment platforms (e.g. Railway) deploy project from github directly. So you shouldn't put your secrets like api key in a config file, instead use environment variables to override the default config.
for name , value in os . environ . items ( ) :
2023-03-26 03:31:29 +08:00
name = name . lower ( )
2026-01-31 12:32:41 +08:00
# 跳过以下划线开头的注释字段
if name . startswith ( " _ " ) :
continue
2023-03-25 18:08:37 +08:00
if name in available_setting :
2023-04-22 12:01:29 +08:00
logger . info ( " [INIT] override config by environ args: {} = {} " . format ( name , value ) )
2023-03-26 03:31:29 +08:00
try :
config [ name ] = eval ( value )
2026-02-25 11:49:19 +00:00
except Exception :
2023-03-31 15:13:28 +08:00
if value == " false " :
config [ name ] = False
elif value == " true " :
config [ name ] = True
else :
config [ name ] = value
2023-03-25 10:02:19 +08:00
2023-04-04 15:59:56 +08:00
if config . get ( " debug " , False ) :
2023-04-04 14:02:14 +08:00
logger . setLevel ( logging . DEBUG )
2023-04-17 01:00:08 +08:00
logger . debug ( " [INIT] set log level to DEBUG " )
2023-04-04 14:02:14 +08:00
2024-06-04 12:50:59 +08:00
logger . info ( " [INIT] load config: {} " . format ( drag_sensitive ( config ) ) )
2022-12-19 01:25:34 +08:00
2026-02-02 12:18:57 +08:00
# 打印系统初始化信息
logger . info ( " [INIT] ======================================== " )
logger . info ( " [INIT] System Initialization " )
logger . info ( " [INIT] ======================================== " )
logger . info ( " [INIT] Channel: {} " . format ( config . get ( " channel_type " , " unknown " ) ) )
logger . info ( " [INIT] Model: {} " . format ( config . get ( " model " , " unknown " ) ) )
# Agent模式信息
if config . get ( " agent " , False ) :
workspace = config . get ( " agent_workspace " , " ~/cow " )
logger . info ( " [INIT] Mode: Agent (workspace: {} ) " . format ( workspace ) )
else :
2026-02-02 12:25:47 +08:00
logger . info ( " [INIT] Mode: Chat (在config.json中设置 \" agent \" :true 可启用Agent模式) " )
2026-02-02 12:18:57 +08:00
logger . info ( " [INIT] Debug: {} " . format ( config . get ( " debug " , False ) ) )
logger . info ( " [INIT] ======================================== " )
2026-03-09 11:37:45 +08:00
# Sync selected config values to environment variables so that
# subprocesses (e.g. shell skill scripts) can access them directly.
# Existing env vars are NOT overwritten (env takes precedence).
_CONFIG_TO_ENV = {
" open_ai_api_key " : " OPENAI_API_KEY " ,
" open_ai_api_base " : " OPENAI_API_BASE " ,
" linkai_api_key " : " LINKAI_API_KEY " ,
" linkai_api_base " : " LINKAI_API_BASE " ,
" claude_api_key " : " CLAUDE_API_KEY " ,
" claude_api_base " : " CLAUDE_API_BASE " ,
" gemini_api_key " : " GEMINI_API_KEY " ,
" gemini_api_base " : " GEMINI_API_BASE " ,
" minimax_api_key " : " MINIMAX_API_KEY " ,
" minimax_api_base " : " MINIMAX_API_BASE " ,
" zhipu_ai_api_key " : " ZHIPU_AI_API_KEY " ,
" zhipu_ai_api_base " : " ZHIPU_AI_API_BASE " ,
" moonshot_api_key " : " MOONSHOT_API_KEY " ,
" moonshot_api_base " : " MOONSHOT_API_BASE " ,
" ark_api_key " : " ARK_API_KEY " ,
" ark_api_base " : " ARK_API_BASE " ,
}
injected = 0
for conf_key , env_key in _CONFIG_TO_ENV . items ( ) :
if env_key not in os . environ :
val = config . get ( conf_key , " " )
if val :
os . environ [ env_key ] = str ( val )
injected + = 1
if injected :
logger . info ( " [INIT] Synced {} config values to environment variables " . format ( injected ) )
2023-04-04 00:59:21 +08:00
config . load_user_datas ( )
2022-12-13 01:50:43 +08:00
2023-04-17 01:00:08 +08:00
2022-12-13 01:50:43 +08:00
def get_root ( ) :
2023-03-27 14:40:19 +08:00
return os . path . dirname ( os . path . abspath ( __file__ ) )
2022-12-13 01:50:43 +08:00
def read_file ( path ) :
2023-04-17 01:00:08 +08:00
with open ( path , mode = " r " , encoding = " utf-8 " ) as f :
2022-12-13 01:50:43 +08:00
return f . read ( )
def conf ( ) :
2023-02-05 01:30:46 +08:00
return config
2023-04-09 11:59:31 +08:00
2023-04-17 01:24:39 +08:00
def get_appdata_dir ( ) :
data_path = os . path . join ( get_root ( ) , conf ( ) . get ( " appdata_dir " , " " ) )
2023-04-09 11:59:31 +08:00
if not os . path . exists ( data_path ) :
logger . info ( " [INIT] data path not exists, create it: {} " . format ( data_path ) )
os . makedirs ( data_path )
2023-04-17 01:24:39 +08:00
return data_path
2023-04-25 23:58:46 +08:00
def subscribe_msg ( ) :
trigger_prefix = conf ( ) . get ( " single_chat_prefix " , [ " " ] ) [ 0 ]
msg = conf ( ) . get ( " subscribe_msg " , " " )
return msg . format ( trigger_prefix = trigger_prefix )
2023-07-20 11:36:02 +08:00
# global plugin config
plugin_config = { }
def write_plugin_config ( pconf : dict ) :
"""
写入插件全局配置
: param pconf : 全量插件配置
"""
global plugin_config
for k in pconf :
plugin_config [ k . lower ( ) ] = pconf [ k ]
2024-12-02 16:38:21 +08:00
def remove_plugin_config ( name : str ) :
"""
移除待重新加载的插件全局配置
: param name : 待重载的插件名
"""
global plugin_config
plugin_config . pop ( name . lower ( ) , None )
2023-07-20 11:36:02 +08:00
def pconf ( plugin_name : str ) - > dict :
"""
根据插件名称获取配置
: param plugin_name : 插件名称
: return : 该插件的配置项
"""
return plugin_config . get ( plugin_name . lower ( ) )
2023-07-28 12:40:06 +08:00
# 全局配置,用于存放全局生效的状态
2024-06-12 19:14:09 +08:00
global_config = { " admin_users " : [ ] }