Files
gemini_boy/config.py
2025-06-06 16:41:50 +08:00

169 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# config.py
import configparser
import os
import logging
# 获取根日志器确保日志配置已在utils.py中完成
logger = logging.getLogger(__name__)
CONFIG_FILE = "config.ini"
# 定义默认配置如果config.ini不存在或缺失将使用这些值
DEFAULT_CONFIG = {
"API": {
"GEMINI_API_BASE_URL": "https://generativelanguage.googleapis.com/v1beta",
"GEMINI_API_KEY": "YOUR_GEMINI_API_KEY_HERE", # 默认值,强烈建议用户手动修改
"DEFAULT_GEMINI_MODEL": "gemini-pro",
"MEMORY_UPDATE_MODEL": "gemini-pro",
},
"Application": {
"CONTEXT_WINDOW_SIZE": "6",
"MEMORY_RETENTION_TURNS": "18",
"MAX_SHORT_TERM_EVENTS": "20",
"FEATURES_DIR": "data/features",
"MEMORIES_DIR": "data/memories",
"CHAT_LOGS_DIR": "data/chat_logs",
"APP_LOG_FILE_PATH": "logs/app.log",
},
"Session": {
"CURRENT_ROLE_ID": "default_role",
"CURRENT_MEMORY_ID": "default_memory",
},
}
def load_config():
"""
从 config.ini 文件加载配置。
如果文件不存在或某些配置项缺失,则使用默认值并尝试创建/更新文件。
:return: 包含所有配置的字典。
"""
config = configparser.ConfigParser()
# 检查config.ini是否存在如果不存在则创建并写入默认配置
if not os.path.exists(CONFIG_FILE):
logger.info(f"config.ini 文件不存在,正在创建默认配置文件:{CONFIG_FILE}")
for section, options in DEFAULT_CONFIG.items():
config.add_section(section)
for key, value in options.items():
config.set(section, key, value)
try:
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
config.write(f)
logger.info("默认 config.ini 文件创建成功。")
except IOError as e:
logger.error(f"无法写入 config.ini 文件: {e}")
# 即使写入失败,也继续使用内存中的默认配置
else:
logger.info(f"{CONFIG_FILE} 加载配置...")
# 读取配置
try:
config.read(CONFIG_FILE, encoding="utf-8")
except Exception as e:
logger.error(f"读取 config.ini 文件时发生错误: {e},将使用默认配置。")
# 如果读取失败,清空 configparser 对象,让后续逻辑使用默认值
config = configparser.ConfigParser()
# 将配置转换为字典格式,并确保所有默认值都存在
app_config = {}
for section, options in DEFAULT_CONFIG.items():
app_config[section] = {}
for key, default_value in options.items():
# 使用 get() 方法获取值,如果不存在则使用默认值
# 对于整型或布尔型配置,需要手动转换
value = config.get(section, key, fallback=default_value)
# 尝试将特定配置项转换为数字类型
if section == "Application" and key in [
"CONTEXT_WINDOW_SIZE",
"MEMORY_RETENTION_TURNS",
"MAX_SHORT_TERM_EVENTS",
]:
try:
app_config[section][key] = int(value)
except ValueError:
logger.warning(
f"配置项 {section}.{key} 的值 '{value}' 不是有效数字,使用默认值 {default_value}"
)
app_config[section][key] = int(default_value)
elif section == "API" and key == "GEMINI_API_KEY":
# 优先从环境变量读取 GEMINI_API_KEY
env_key = os.getenv("GEMINI_API_KEY")
if env_key:
app_config[section][key] = env_key
logger.info("已从环境变量加载 GEMINI_API_KEY。")
else:
app_config[section][key] = value
else:
app_config[section][key] = value
# 如果存在config.ini但缺少某些默认值更新它
try:
updated = False
for section, options in DEFAULT_CONFIG.items():
if not config.has_section(section):
config.add_section(section)
updated = True
for key, default_value in options.items():
if not config.has_option(section, key):
config.set(section, key, str(default_value)) # 确保写入的是字符串
updated = True
if updated:
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
config.write(f)
logger.info("config.ini 文件已更新,补齐缺失配置项。")
except IOError as e:
logger.error(f"无法更新 config.ini 文件以补齐缺失配置项: {e}")
logger.info("配置加载完成。")
return app_config
def save_config(new_config):
"""
将给定的配置字典保存到 config.ini 文件。
它会读取现有配置,然后只更新 new_config 中提供的部分。
:param new_config: 包含要保存的所有配置的字典。
"""
config = configparser.ConfigParser()
# 首先读取现有配置,以保留未在 new_config 中提供的项
if os.path.exists(CONFIG_FILE):
try:
config.read(CONFIG_FILE, encoding="utf-8")
except Exception as e:
logger.error(f"读取现有 config.ini 文件时发生错误: {e},将只保存新配置。")
for section, options in new_config.items():
if not config.has_section(section):
config.add_section(section)
for key, value in options.items():
# 确保将值转换为字符串,因为 configparser 存储的是字符串
config.set(section, key, str(value))
try:
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
config.write(f)
logger.info(f"配置已成功保存到 {CONFIG_FILE}")
except IOError as e:
logger.error(f"保存配置到 {CONFIG_FILE} 失败: {e}")
# 全局变量,存储当前加载的配置
app_config = load_config()
def get_config():
"""获取当前加载的配置"""
return app_config
def set_config(new_config):
"""更新内存中的配置并保存到文件"""
global app_config
app_config = new_config
save_config(app_config)
logger.info("内存配置已更新并保存。")