Skip to content

Patchouli-CN/GensokyoAI

Repository files navigation

🌸 GensokyoAI - 幻想乡 AI 角色扮演引擎

Python Version License Code Style

一个专为角色扮演设计的通用 Python AI Agent 工具包与运行时,支持 Ollama / OpenAI / OpenRouter / DeepSeek / OpenAI Responses / Claude / Gemini 等多种 LLM Provider,提供三层记忆系统、会话管理、工具调用、Provider 抽象和稳定 Runtime API。

使用指南 项目设计 默认配置示例 Q群!快来!

项目定位

GensokyoAI 是一个 Python 纯后端工具包。它不绑定任何具体 UI、桌面程序、Web 程序或聊天平台(但自带CLI,所以也可以直接用),而是把角色扮演 Agent 的核心能力封装为可复用的 Python 包与 Runtime API。

核心边界:

  • Python 包负责 Agent、记忆、会话、工具、Provider 调用和可选依赖管理。
  • 外部调用方通过公开 Python API 或 Runtime RPC 使用这些能力。
  • OpenAI、Claude、Gemini、Ollama 等 Provider 的真实调用逻辑位于 Python 后端。
  • Provider SDK 依赖保持可选,不会强制安装全部模型服务依赖。
  • 任意客户端、脚本、服务端适配器或第三方程序都可以在不理解内部实现的情况下调用 Runtime API。

Runtime API

GensokyoAI 提供前端无关的 Runtime 边界:

  • GensokyoAI/runtime/service.py:通用 RuntimeService
  • GensokyoAI/runtime/rpc.py:RPC 方法注册、分发与 legacy 方法兼容。
  • GensokyoAI/runtime/dependencies.py:可选 Provider 依赖检测与白名单安装。
  • bridge_main.py:通用 JSON Lines RPC 入口,可被本地客户端或其他进程启动。

当前 Runtime RPC 支持:

  • runtime.info
  • runtime.health
  • runtime.shutdown
  • agent.init
  • agent.send_message
  • character.list
  • model.list
  • model.info
  • session.create
  • session.list
  • session.resume
  • dependency.status
  • dependency.install
  • external_tool.status

旧方法名仍保留兼容:initsend_messagelist_characterscreate_sessionlist_sessionsresume_sessionshutdowndependency_statusinstall_dependenciesexternal_tool_status

可选 Provider 依赖

Provider SDK 保持可选安装:

  • ollama = ["ollama"]
  • openai = ["openai>=1.0.0"]
  • openrouter = ["openai>=1.0.0"]
  • deepseek = ["openai>=1.0.0"]
  • openai_responses = ["openai>=1.0.0"]
  • claude = ["anthropic>=0.20.0"]
  • gemini = ["google-genai>=1.0.0"]
  • all = [...]

依赖检测与安装由后端白名单控制。调用方只能请求 Provider 名称,例如:

{"providers":["openai","deepseek"]}

后端会自行映射到允许安装的 Python 包,不接受任意 pip 包名或 shell 命令。

✨ 核心亮点

快速知道 GensokyoAI 能带来什么体验。

真人般的对话体验

GensokyoAI 不是简单的问答机器人,而是围绕“角色扮演”设计的对话引擎。角色可以拥有稳定的人设、说话习惯、问候语和示例对话,在长期交流中更容易保持一致的性格与表达方式。

具有更真实的记忆

对话不会只停留在当前一句话。角色可以保留近期上下文,也能把长期交流压缩成记忆,并围绕话题建立联系;后续对话中,系统会尝试检索相关记忆,帮助角色更自然地想起过去内容。

记忆管理不是简单地“全部塞进上下文”。在启用工具调用且模型选择调用记忆工具时,角色可以根据对话内容主动记住或回忆信息,并借助话题和遗忘机制让记忆更像真实交流中的印象,而不是僵硬的记录本。

角色有自然活动

启用静默思考后,角色可以在空闲时回顾已有话题、整理思绪;当系统判断时机合适时,还可以主动开口。这让角色不只是被动回答,而更像拥有自己的内心世界。

更好的会话管理

支持创建、保存、恢复和列出会话;Agent 与内置 CLI 支持回滚上一轮对话,Runtime RPC 当前暴露创建、列出和恢复会话,暂未暴露回滚方法。说错话可以撤回,历史会话可以继续,不同角色也可以分别维护自己的交流记录。

可选择不同模型服务

你可以按需求选择本地模型、OpenAI 兼容服务、DeepSeek、Claude 或 Gemini。想要本地免费运行、接入云端大模型,或混合使用不同服务,都可以通过配置完成。

更稳定的 API 调用

GensokyoAI 针对外部 AI 服务调用做了稳定性优化:

  • 服务商偶发 500 / 502 / 503 / 504 等临时错误时,会自动等待并重试,减少网络波动导致的中断。
  • embeddings 向量调用也复用同一套重试和错误处理逻辑,记忆检索、语义搜索等功能更稳定。
  • 遇到代理或网关返回的大段 HTML 错误页时,会整理成更容易理解的错误提示。
  • OpenAI、OpenAI 兼容服务、OpenAI Responses、OpenRouter、自定义代理等 API 地址写法更加宽容。
  • 支持真正任意 api_path:默认路径继续走 SDK,SDK 固定 resource path 无法表达的代理路径会自动切换到自定义 HTTP 调用层。
  • 支持 extra_headers、Provider 能力声明、ProviderDefinition 控制面、模型列表查询和更完整的流式元信息。
  • 支持通过统一模型元数据注册表合并 Provider /models、内置快照、缓存和用户 override,从模型列表和元数据中推断 web_search 等模型级能力;第三方 OpenAI 兼容端点默认不会被高估为支持图片能力。
  • 支持显式开启真实联网搜索执行层:OpenAI Responses 可注入 web_search_preview,Gemini 可映射 Google Search grounding;也支持自有 web_search 工具走 Bing/API 搜索;默认关闭,不会自动联网。
  • 工具注入由 ToolBuildService 统一决策,会根据模型 tools 能力、工具总开关、builtin_tools 白名单和 Provider 内置搜索配置选择工具 schema 与附加 instructions。
  • 工具错误返回保留旧 content / is_error 字段,同时提供结构化 error_codetechnical_messageuser_messagerecoverableaction_hintdetails,便于 UI 展示与恢复动作。
  • 可通过 retry_max_attemptsretry_initial_delayretry_backoff_factorretry_status_codes 调整自动重试策略。
  • 支持可选 OAuth / Bearer token refresh 基础设施,可在 401 后刷新 token 并重试一次,认证事件会自动清洗敏感字段。
  • 支持模型调用 timing 观测,记录请求总耗时、首 chunk、首 token、首 reasoning、推理片段统计、usage 和 finish_reason。
  • 支持统一图片生成与视觉输入抽象,OpenAI 图片生成、OpenAI / Responses / Gemini / Claude 视觉消息转换已接入。
  • 流式输出增加首包和中途卡住的超时保护,避免模型服务无响应时一直等待。
  • Ollama、Gemini、Claude 等非 OpenAI Provider 的流式工具调用和结束事件更统一。
  • 流式工具调用参数解析失败时会保留 raw_arguments,方便排查模型输出或网关截断问题。
  • OpenAI Responses 流式 failed / incomplete 事件会转换成更明确的错误信息。

完整配置示例见 默认配置

快速配置 Provider

OpenAI 官方 Chat Completions

model:
  provider: "openai"
  name: "gpt-4o"
  api_key: "sk-..."
  base_url: null

OpenAI Responses API

model:
  provider: "openai_responses"
  name: "gpt-5"
  api_key: "sk-..."
  base_url: null
  web_search_enabled: true
  web_search_strategy: "explicit"
  web_search_context_size: "medium"

OpenRouter

model:
  provider: "openrouter"
  name: "openai/gpt-4o"
  api_key: "sk-or-..."
  base_url: null  # 默认 https://openrouter.ai/api/v1
  extra_headers:  # 可选;覆盖内置 HTTP-Referer / X-Title
    HTTP-Referer: "https://your-site.example"
    X-Title: "GensokyoAI"

OpenRouter 也兼容旧写法:provider: "openai" + base_url: "https://openrouter.ai/api"。推荐使用独立 openrouter Provider,因为它会内置 OpenRouter 推荐 headers,并从 /models 元数据中保留 context_lengthinput_modalitiesoutput_modalitiessupported_parameterssupported_featurespricingtop_providerper_request_limits 等字段。

OpenRouter Provider 会把常见模型元数据映射为统一能力:toolsvisionreasoningweb_searchstructured_output。如果 OpenRouter 返回的模型元数据不完整,可以继续通过 model_capabilities_add / model_capabilities_remove 修正能力判断。

Web search 执行层

真实联网搜索默认关闭。Provider 内置搜索需要在模型配置中显式开启:

model:
  provider: "openai_responses"  # 或 gemini
  web_search_enabled: true
  web_search_strategy: "explicit"
  web_search_allow_fallback: true

OpenAI Responses 会在请求中注入 web_search_preview 工具,并把 url_citation 等注解转换为统一引用;Gemini 会映射 Google Search grounding,并从 grounding_metadata 中提取引用。非流式响应和流式 finish chunk 都可携带 web_search_referencesweb_search_diagnostics,便于展示来源、记录搜索状态和排查降级原因。

不支持 Provider 内置搜索但支持工具调用的模型,可以开启 GensokyoAI 自有 web_search 工具:

tool:
  enabled: true
  web_search:
    enabled: true
    provider: "bing"   # bing / api / mixed
    max_results: 10

自有 web_search 工具默认走 Bing HTML 搜索;如果需要接入 Tavily、BoCha、企业搜索等 JSON API,可使用通用 API Provider:

tool:
  web_search:
    enabled: true
    provider: "api"
    api:
      endpoint: "https://api.tavily.com/search"
      method: "POST"
      api_key: "tvly-..."
      results_path: "results"
      title_path: "title"
      url_path: "url"
      snippet_path: "content"

provider: "mixed" 会并行执行 Bing 和 API 搜索,并按来源优先级与结果质量排序、去重、截断结果。搜索工具成功时返回 JSON,包含 itemsdiagnostics,便于模型引用来源并排查搜索状态;配置禁用、Provider 不支持、Provider 失败或无结果等可诊断失败会通过结构化工具错误返回,例如 web_search.disabledweb_search.unsupported_providerweb_search.provider_failedweb_search.no_results

自定义 OpenAI 兼容服务

model:
  provider: "openai"
  name: "your-model-name"
  api_key: "sk-..."
  base_url: "https://your-api.example.com"

自定义代理路径

model:
  provider: "openai"
  name: "your-model-name"
  api_key: "sk-..."
  base_url: "https://proxy.example.com"
  api_path: "/custom/chat/completions"  # 也支持 /custom/generate 这类非标准路径
  extra_headers:
    X-Custom-Gateway: "gensokyo"

自动重试策略

model:
  retry_max_attempts: 3
  retry_initial_delay: 1.0
  retry_backoff_factor: 2.0
  retry_status_codes: [500, 502, 503, 504]

默认只重试临时服务端错误。如果你使用的服务商把 429 作为“稍后重试”,可以显式加入:

model:
  retry_status_codes: [500, 502, 503, 504, 429]

不建议盲目重试 400401403404,这些通常代表配置、鉴权或请求参数问题。

模型能力覆盖

模型列表中的能力会尽量从 Provider 声明、远端 /models 元数据和模型名中推断。对于 OpenAI 兼容服务、OpenRouter、Responses、Gemini 等,系统可以标记 reasoningvisionweb_searchstructured_output 等模型级能力。OpenRouter 的 supported_parameterssupported_featurespricing.internal_reasoninginput_modalities 等字段会参与推断。

OpenAI 官方端点会默认声明图片输入与图片生成能力;第三方 OpenAI-compatible endpoint 默认只声明通用文本、工具、embedding 和自定义端点能力,避免把所有兼容服务都误判成支持图片。若第三方服务实际支持图片,可通过远端模型 metadata 或下面的配置显式补充。

如果服务商元数据不完整,或者你确定某个模型能力被误判,可以用配置增补或移除能力:

model:
  provider: "openai"
  name: "your-model-name"
  model_capabilities_add:
    - "web_search"
  model_capabilities_remove:
    - "image_generation"

注意:web_search 能力元信息本身不会自动执行联网搜索;只有同时开启 web_search_enabled: trueweb_search_strategy 不是 off 时,Provider 才会注入内置搜索配置。模型能力查询可通过 ModelRegistryService 统一获得,它会合并 Provider 远端列表、内置 fallback 快照、内存缓存和用户能力修正。

配置合并语义

用户配置文件会保留 model 字段出现信息,因此可以区分“未配置”和“显式配置为默认值”。例如默认配置或上游配置把 temperature 设为 1.2 时,用户仍可以在自己的配置中显式写回 0.7,并按用户意图覆盖:

model:
  temperature: 0.7
  max_tokens: 2048
  timeout: 60
  retry_max_attempts: 3

这同样适用于 providernamestreamthinkapi_pathextra_headersmodel_capabilities_add / model_capabilities_removemodel 字段。环境变量仍会在配置文件合并后作为最后一层覆盖。

OAuth / token refresh

适用于需要动态 Bearer token 的 OpenAI 兼容服务、Responses API 或内部网关:

model:
  provider: "openai"
  name: "your-model-name"
  base_url: "https://your-api.example.com"
  auth:
    auth_type: "bearer"
    token_url: "https://auth.example.com/oauth/token"
    client_id: "your-client-id"
    client_secret: "your-client-secret"
    refresh_token: "your-refresh-token"
    refresh_before_seconds: 60
    allow_401_refresh: true

也可以通过环境变量覆盖常用认证字段:

  • GENSOKYOAI_AUTH_TYPE
  • GENSOKYOAI_TOKEN_URL
  • GENSOKYOAI_ACCESS_TOKEN
  • GENSOKYOAI_REFRESH_TOKEN
  • GENSOKYOAI_CLIENT_ID
  • GENSOKYOAI_CLIENT_SECRET

图片生成

OpenAI Provider 提供统一图片生成入口:

from GensokyoAI.core.agent.model_client import ModelClient
from GensokyoAI.core.config import ModelConfig

client = ModelClient(
    ModelConfig(provider="openai", name="gpt-image-1", api_key="sk-...")
)

result = await client.generate_image(
    "画一只在博丽神社喝茶的猫",
    size="1024x1024",
    n=1,
)

print(result.images[0].url or result.images[0].data)

返回值会统一为 ImageGenerationResult,每张图为 GeneratedImage,支持 URL、base64 data、mime_type、revised_prompt 和 metadata。

视觉输入

聊天消息的 content 可以继续使用字符串,也可以使用统一多模态片段:

from GensokyoAI.core.agent.types import ImageInput, MessageContentPart

messages = [
    {
        "role": "user",
        "content": [
            MessageContentPart(type="text", text="请描述这张图"),
            MessageContentPart(
                type="image",
                image=ImageInput(url="https://example.com/image.png", detail="low"),
            ),
        ],
    }
]

response = await client.chat(messages)

Provider 会自动转换为目标服务格式:

  • OpenAI Chat Completions:text / image_url
  • OpenAI Responses:input_text / input_image
  • Gemini:text / inline_data / file_data
  • Claude:text / image content blocks

API 调用层能力

GensokyoAI 的模型调用层采用 Provider 抽象,统一封装不同模型服务的差异。

  • Provider 会声明自身支持的能力,例如 chat、stream、tools、embeddings、reasoning、vision、image_generation、image_edit、responses_api、custom_endpoint、web_search。
  • OpenAI 兼容 Provider 支持拉取 /models,失败时会返回当前配置模型作为 fallback;Claude 当前返回配置模型作为稳定 fallback。
  • OpenAI 官方端点默认声明图片能力;第三方 OpenAI-compatible endpoint 默认不声明图片能力,需要依赖远端 metadata 或 model_capabilities_add 显式补充。
  • 模型级能力会结合远端 metadata、模型名和 model_capabilities_add / model_capabilities_remove 配置推断;真实联网搜索由 web_search_enabledweb_search_strategy 显式控制。
  • chat、chat_stream、embeddings、generate_image 会尽量使用统一的错误归一化、自动重试、认证准备和事件记录逻辑。
  • 流式响应现在也有首包和迭代超时保护,模型服务长时间无响应时会给出明确超时错误。
  • 流式响应块可携带 statuserrorusagefinish_reason,便于 UI、日志和上层运行时感知重试、结束原因和 token 用量。
  • Ollama、Gemini、Claude 的工具调用和结束事件会尽量按统一 tool_call / finish 形式输出。
  • 流式工具调用参数解析失败时会在 tool_info.raw_arguments 保留原始参数文本,帮助排查工具调用问题。
  • OpenAI Responses 流式失败或不完整事件会转成明确错误,避免表现为无提示中断。
  • MODEL_CALL_TIMING 事件可用于记录 chat、chat_stream、embeddings、generate_image 的调用耗时与推理统计。
  • MODEL_AUTH 事件可用于观察 token 刷新开始、完成和失败,事件数据会清洗密钥与 token。
  • 自定义 Provider 可以通过 capabilities、supports 和 list_models 接入统一能力体系。
  • Provider 控制面由 ProviderDefinition 集中描述,新增 Provider 时主要补充一处定义表和 Provider 实现。
  • 模型元数据查询由 ModelRegistryService 统一处理,可在 Provider API 失败时使用缓存或内置快照 fallback。
  • 工具 schema 与工具说明由 ToolBuildService 统一构建,ToolRegistry 主要负责发现和注册工具。
  • 工具执行失败会产生结构化 ToolErrorToolExecutor 返回旧字段兼容的 tool message,同时在 error 字段和 TOOL_CALL_FAILED 事件中提供 error_code、用户提示、技术原因、恢复建议和 details。

交流讨论

欢迎来提供功能建议、BUG 反馈以及纯粹交流ᗜᴗᗜ!

贡献指南

欢迎提交 Issue 和 Pull Request!

如果你:

  • 写了新的角色配置文件,欢迎分享到 characters/ 目录。
  • 开发了新的 Provider、工具、记忆能力或 Runtime 适配器,欢迎 PR。
  • 发现了 bug 或有功能建议,请提交 Issue。

待办事项

  • HTTP / WebSocket Runtime adapter
  • 多角色同时对话
  • 语音输入 / 输出
  • 更多内置工具

许可证

MIT License - 详见 LICENSE 文件。

🙏 致谢

🌟 Star History

Star History Chart


Made with ❤️ and 🍵 in Gensokyo

“只有华丽并不是魔法,弹幕最重要的是火力 DA⭐ZE!” —— 雾雨魔理沙

About

AI角色扮演框架

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages