* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* Fix/interface home (#182)
* [fix]Fix the interface for statistics of recent activities and applications
* [changes]Modify the code based on the AI review
1.Use the boolean auxiliary methods provided by SQLAlchemy instead of using == True in the is_active filter.
2.The calculation of the "PROJECT_ROOT" has now been hardcoded with five levels of nested os.path.dirname calls.
* [fix]Fix the interface for statistics of recent activities and applications
* [changes]Modify the code based on the AI review
1.Use the boolean auxiliary methods provided by SQLAlchemy instead of using == True in the is_active filter.
2.The calculation of the "PROJECT_ROOT" has now been hardcoded with five levels of nested os.path.dirname calls.
* Fix/optimize inerface (#183)
* [changes]Optimize the time consumption of the "/end_users" interface
* [fix]Optimize the time consumption of the "/hot_memory_tags" interface
* [changes]Optimize the time consumption of the "/end_users" interface
* [fix]Optimize the time consumption of the "/hot_memory_tags" interface
* [changes]Improve the code based on AI review
* Fix/memory mcp2 1 (#184)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* Fix/memory mcp2 1 (#185)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* Fix/memory mcp2 1 (#188)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* 解决冲突
* 解决冲突
* feat(home page): version description update
* Fix/memory mcp2 1 (#190)
* 优化快速检索的回复内容
* 优化快速检索的回复内容
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* 路径的BUG修复
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* LLM生存缺少config_id认证,修复BUG
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* 深度检索优化,搜索不到数据/提问的概念过于蘑菇,以引导的方式继续提问
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* feat(web): memory related interface parameter transfer adjustment
* 感知meta_data字段BUG修复
* Fix/memory bug fix (#171)
* feat(sandbox): add Python 3 code execution sandbox support
* feat(workflow): emit SSE events for node exception output
* perf(sandbox): optimize code encryption handling
* perf(workflow): update standard node output structure
* [add] migration script
* [modify] migration script
* feat(web): add workflow runtime info
* fix(web): handleSSE bugfix
* fix(sandbox): prevent imports from being blocked when network is disabled
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* Fix/memory bug fix (#199)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* user_id->显示为config_id_old传输
* feat(web): update read_all_config select valueKey
* user_id->显示为config_id_old传输
* feat(workflow): Add a new node for executing code
* fix(web): KnowledgeConfigModal bugfix
* fix(web): iteration's variable add parameter-extractor node
* fix(sandbox): treat non-zero exit codes as errors instead of relying only on stderr
* Fix/memory bug fix (#200)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* Refactor/benchmark test (#196)
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]Benchmark test adaptation for end_user_id
* [changes]refactor locomo_test
* [fix]Fix the circular import of ModelParameters
* [changes]The benchmark test can run stably.
* [fix]Complete end-to-end LoCoMo repair
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [fix]Complete the end-to-end longmemeval and memsciqa fixes
* [changes]Complete the benchmark test description document to ensure that the configuration parameters take effect.
* [changes]Benchmark test adaptation for end_user_id
* [modify] migration script
* delete benchmark-test (#204)
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Restore .gitmodules
* feat(web): workflow add code node
* 检查需要更改的格式问题
* Fix/redbear benchmark (#205)
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Update submodule reference
* Refactor: Move evaluation folder to redbear-mem-benchmark submodule
* [changes]Update submodule reference
* Remove duplicate evaluation submodule, use redbear-mem-benchmark instead
* Fix/memory bug fix (#207)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* fix(web): remove URI decode and encode
* [add] plugin system and base sso module
* 修复宿主列表获取memory_config_idBUG
* Fix/memory bug fix (#209)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* [modify] file local server url
* [add] migration script
* fix(workflow): fix activation and branch control issues in streaming output
* fix(workflow): fix function cache not taking effect and potential list index overflow
* style(workflow): enforce PEP8 style and remove redundant imports
* fix(workflow): fix streaming output error when variable is not a string
* [fix]remove aspose-slides
* perf(workflow): enhance streaming output node activation performance
* feat(workflow): store token usage in message table
* feat(web): add PageEmpty component
* feat(web): add PageTabs component
* perf(workflow): make memory configuration backward compatible
* feat(web): update model management
* config_id做映射
* config_id做映射
* Fix/memory bug fix (#211)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(web): getModelListUrl add is_active param
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* feat(web): remove file url replace
* Fix/memory bug fix (#212)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* feat(web): model logo update
* 应用层memory_content->memory_config
* fix(web): correct spelling
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* Fix/memory bug fix (#215)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* fix(web): model loading update
* 统一字段为config_id_old
* 统一字段为config_id_old
* feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics
* 统一字段为config_id_old
* 统一字段为config_id_old
* memory_content暂时不修改
* memory_content暂时不修改
* Fix/memory bug fix (#217)
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 图谱数据量限制数量去掉
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 用户详情优化
* 读取的接口,去掉全局锁
* 输出数组
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化1.0(优化隐私输出、时间检索)
* 反思优化测试接口
* 反思优化测试接口
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 读取接口内层嵌套BUG修复
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 新增中翻英功能(记忆时间线)(用户摘要)(兴趣分布接口)(查询核心档案)(记忆洞察)-接口添加翻译字段
* 把group_id替换end_user_id
* 把group_id替换end_user_id_
* 把group_id替换end_user_id_
* config_config替换成memory_config
* config_config替换成memory_config
* [fix]Fix the memory interface to use end_user_id.
* config_config替换成memory_config
* config_config替换成memory_config
* config_config替换成memory_config
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID
* config_id字段改成UUID,与develop校对恢复
* 检查项目,修复group_id的遗留问题
* 检查项目,修复group_id的遗留问题
* 解决冲突
* 解决冲突
* end_user_id清理干净
* end_user_id清理干净
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 修复遗留合并BUG
* 感知meta_data字段BUG修复
* user_id->现实为config_id_old
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* user_id->显示为config_id_old传输
* 检查需要更改的格式问题
* 修复宿主列表获取memory_config_idBUG
* config_id做映射
* config_id做映射
* config_id做映射+1
* config_id做映射+1
* config_id做映射+1
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 应用层memory_content->memory_config
* 统一字段为config_id_old
* 统一字段为config_id_old
* 统一字段为config_id_old
* 统一字段为config_id_old
* memory_content暂时不修改
* memory_content暂时不修改
---------
Co-authored-by: lanceyq <1982376970@qq.com>
* feat(web): add app statistics
* fix(workflow): fix streaming output issues with multi-output End nodes
End nodes with multiple output segments could cause cursor errors or leave some
segments inactive, resulting in incorrect final outputs.
Unified _emit_active_chunks and _update_scope_activate to ensure all segments
are activated in order and streamed correctly.
* feat(web): add apps statistics api
* fix(web): agent's knowledge_bases bugfix
* Revert "feat(web): update read_all_config select valueKey"
This reverts commit 46f0f3cee9.
* [add] migrations script
* perf(workflow): make memory write node backward-compatible and defer config validation
* 旧数据兼容
* 旧数据兼容
* 旧数据兼容
* 旧数据兼容
* fix(web): model bugfix
* fix(web): model bugfix
* 提交遗漏 (#228)
* [fix] chat api for workflow
* [fix] web search set for v1 api
* fix(web): model bugfix
* fix(web): model list remove is_active
* fix(model): bug fix
* [add]migration script
* [fix] api
* [fix] api
* fix(web): model bugfix
* fix(model): the model type does not allow modification, delete tts and speech2text type
* fix(model): bug fix
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* Add/develop memory (#239)
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* feat(web): model ui update
* feat(web): model ui update
* Add/develop memory (#243)
* 遗漏的历史映射
* 遗漏的历史映射
* fix(model): bug fix
* feat(web): model ui update
* Add/develop memory (#247)
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* 遗漏的历史映射
* [modify] migration script
* [add] migration script
* fix(web): change form message
* fix(web): the memoryContent field is compatible with numbers and strings
* feat(web): code node hidden
* fix(model):
1. create a basic model to check if the name and provider are duplicated.
2. The result shows error models because the provider created API Keys for all matching models.
---------
Co-authored-by: lixinyue <2569494688@qq.com>
Co-authored-by: lanceyq <1982376970@qq.com>
Co-authored-by: yujiangping <yujiangping@taofen8.com>
Co-authored-by: 乐力齐 <162269739+lanceyq@users.noreply.github.com>
Co-authored-by: lixinyue11 <94037597+lixinyue11@users.noreply.github.com>
Co-authored-by: yingzhao <zhaoyingyz@126.com>
Co-authored-by: Timebomb2018 <18868801967@163.com>
Co-authored-by: Mark <zhuwenhui5566@163.com>
Co-authored-by: zhaoying <yzhao96@best-inc.com>
Co-authored-by: Eternity <1533512157@qq.com>
Co-authored-by: lixiangcheng1 <lixiangcheng1@wanda.cn>
604 lines
24 KiB
Python
604 lines
24 KiB
Python
from fastapi import APIRouter, Depends, status, Query
|
||
from sqlalchemy.orm import Session
|
||
from typing import Optional
|
||
import uuid
|
||
|
||
from app.core.error_codes import BizCode
|
||
from app.core.exceptions import BusinessException
|
||
from app.db import get_db
|
||
from app.dependencies import get_current_user
|
||
from app.models.models_model import ModelProvider, ModelType, LoadBalanceStrategy
|
||
from app.models.user_model import User
|
||
from app.repositories.model_repository import ModelConfigRepository
|
||
from app.schemas import model_schema
|
||
from app.core.response_utils import success
|
||
from app.schemas.response_schema import ApiResponse, PageData
|
||
from app.services.model_service import ModelConfigService, ModelApiKeyService, ModelBaseService
|
||
from app.core.logging_config import get_api_logger
|
||
|
||
# 获取API专用日志器
|
||
api_logger = get_api_logger()
|
||
|
||
router = APIRouter(
|
||
prefix="/models",
|
||
tags=["Models"],
|
||
)
|
||
|
||
@router.get("/type", response_model=ApiResponse)
|
||
def get_model_types():
|
||
return success(msg="获取模型类型成功", data=list(ModelType))
|
||
|
||
|
||
@router.get("/provider", response_model=ApiResponse)
|
||
def get_model_providers():
|
||
providers = [p for p in ModelProvider if p != ModelProvider.COMPOSITE]
|
||
return success(msg="获取模型提供商成功", data=providers)
|
||
|
||
@router.get("/strategy", response_model=ApiResponse)
|
||
def get_model_strategies():
|
||
return success(msg="获取模型策略成功", data=list(LoadBalanceStrategy))
|
||
|
||
|
||
@router.get("", response_model=ApiResponse)
|
||
def get_model_list(
|
||
type: Optional[list[str]] = Query(None, description="模型类型筛选(支持多个,如 ?type=LLM 或 ?type=LLM,EMBEDDING)"),
|
||
provider: Optional[model_schema.ModelProvider] = Query(None, description="提供商筛选(基于API Key)"),
|
||
is_active: Optional[bool] = Query(None, description="激活状态筛选"),
|
||
is_public: Optional[bool] = Query(None, description="公开状态筛选"),
|
||
search: Optional[str] = Query(None, description="搜索关键词"),
|
||
page: int = Query(1, ge=1, description="页码"),
|
||
pagesize: int = Query(10, ge=1, le=100, description="每页数量"),
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取模型配置列表
|
||
|
||
支持多个 type 参数:
|
||
- 单个:?type=LLM
|
||
- 多个(逗号分隔):?type=LLM,EMBEDDING
|
||
- 多个(重复参数):?type=LLM&type=EMBEDDING
|
||
"""
|
||
api_logger.info(
|
||
f"获取模型配置列表请求: type={type}, provider={provider}, page={page}, pagesize={pagesize}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
# 解析 type 参数(支持逗号分隔)
|
||
type_list = []
|
||
if type is not None:
|
||
flat_type = []
|
||
for item in type:
|
||
split_items = [t.strip() for t in item.split(',') if t.strip()]
|
||
flat_type.extend(split_items)
|
||
|
||
unique_flat_type = list(dict.fromkeys(flat_type))
|
||
type_list = [ModelType(t.lower()) for t in unique_flat_type]
|
||
|
||
api_logger.error(f"获取模型type_list: {type_list}")
|
||
query = model_schema.ModelConfigQuery(
|
||
type=type_list,
|
||
provider=provider,
|
||
is_active=is_active,
|
||
is_public=is_public,
|
||
search=search,
|
||
page=page,
|
||
pagesize=pagesize
|
||
)
|
||
|
||
api_logger.debug(f"开始获取模型配置列表: {query.dict()}")
|
||
result_orm = ModelConfigService.get_model_list(db=db, query=query, tenant_id=current_user.tenant_id)
|
||
result = PageData.model_validate(result_orm)
|
||
api_logger.info(f"模型配置列表获取成功: 总数={result.page.total}, 当前页={len(result.items)}")
|
||
return success(data=result, msg="模型配置列表获取成功")
|
||
except Exception as e:
|
||
api_logger.error(f"获取模型配置列表失败: {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.get("/new", response_model=ApiResponse)
|
||
def get_model_list_new(
|
||
type: Optional[list[str]] = Query(None, description="模型类型筛选(支持多个,如 ?type=LLM 或 ?type=LLM,EMBEDDING)"),
|
||
provider: Optional[model_schema.ModelProvider] = Query(None, description="提供商筛选(基于ModelConfig)"),
|
||
is_active: Optional[bool] = Query(None, description="激活状态筛选"),
|
||
is_public: Optional[bool] = Query(None, description="公开状态筛选"),
|
||
search: Optional[str] = Query(None, description="搜索关键词"),
|
||
is_composite: Optional[bool] = Query(None, description="组合模型筛选"),
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取模型配置列表
|
||
|
||
支持多个 type 参数:
|
||
- 单个:?type=LLM
|
||
- 多个(逗号分隔):?type=LLM,EMBEDDING
|
||
- 多个(重复参数):?type=LLM&type=EMBEDDING
|
||
"""
|
||
api_logger.info(f"获取模型配置列表请求: type={type}, provider={provider}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
# 解析 type 参数(支持逗号分隔)
|
||
type_list = []
|
||
if type is not None:
|
||
flat_type = []
|
||
for item in type:
|
||
split_items = [t.strip() for t in item.split(',') if t.strip()]
|
||
flat_type.extend(split_items)
|
||
|
||
unique_flat_type = list(dict.fromkeys(flat_type))
|
||
type_list = [ModelType(t.lower()) for t in unique_flat_type]
|
||
|
||
api_logger.info(f"获取模型type_list: {type_list}")
|
||
query = model_schema.ModelConfigQueryNew(
|
||
type=type_list,
|
||
provider=provider,
|
||
is_active=is_active,
|
||
is_public=is_public,
|
||
is_composite=is_composite,
|
||
search=search
|
||
)
|
||
|
||
api_logger.debug(f"开始获取模型配置列表: {query.model_dump()}")
|
||
result = ModelConfigService.get_model_list_new(db=db, query=query, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"模型配置列表获取成功: 分组数={len(result)}, 总模型数={sum(len(item['models']) for item in result)}")
|
||
return success(data=result, msg="模型配置列表获取成功")
|
||
except Exception as e:
|
||
api_logger.error(f"获取模型配置列表失败: {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.get("/model_plaza", response_model=ApiResponse)
|
||
def get_model_plaza_list(
|
||
type: Optional[ModelType] = Query(None, description="模型类型"),
|
||
provider: Optional[ModelProvider] = Query(None, description="供应商"),
|
||
is_official: Optional[bool] = Query(None, description="是否官方模型"),
|
||
is_deprecated: Optional[bool] = Query(None, description="是否弃用"),
|
||
search: Optional[str] = Query(None, description="搜索关键词"),
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""模型广场查询接口(按供应商分组)"""
|
||
|
||
query = model_schema.ModelBaseQuery(
|
||
type=type,
|
||
provider=provider,
|
||
is_official=is_official,
|
||
is_deprecated=is_deprecated,
|
||
search=search
|
||
)
|
||
result = ModelBaseService.get_model_base_list(db=db, query=query, tenant_id=current_user.tenant_id)
|
||
return success(data=result, msg="模型广场列表获取成功")
|
||
|
||
|
||
@router.get("/model_plaza/{model_base_id}", response_model=ApiResponse)
|
||
def get_model_base_by_id(
|
||
model_base_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""获取基础模型详情"""
|
||
|
||
result = ModelBaseService.get_model_base_by_id(db=db, model_base_id=model_base_id)
|
||
return success(data=model_schema.ModelBase.model_validate(result), msg="基础模型获取成功")
|
||
|
||
|
||
@router.post("/model_plaza", response_model=ApiResponse)
|
||
def create_model_base(
|
||
data: model_schema.ModelBaseCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""创建基础模型"""
|
||
|
||
result = ModelBaseService.create_model_base(db=db, data=data)
|
||
return success(data=model_schema.ModelBase.model_validate(result), msg="基础模型创建成功")
|
||
|
||
|
||
@router.put("/model_plaza/{model_base_id}", response_model=ApiResponse)
|
||
def update_model_base(
|
||
model_base_id: uuid.UUID,
|
||
data: model_schema.ModelBaseUpdate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""更新基础模型"""
|
||
|
||
# 不允许更改type类型
|
||
if data.type is not None or data.provider is not None:
|
||
raise BusinessException("不允许更改模型类型和供应商", BizCode.INVALID_PARAMETER)
|
||
|
||
result = ModelBaseService.update_model_base(db=db, model_base_id=model_base_id, data=data)
|
||
return success(data=model_schema.ModelBase.model_validate(result), msg="基础模型更新成功")
|
||
|
||
|
||
@router.delete("/model_plaza/{model_base_id}", response_model=ApiResponse)
|
||
def delete_model_base(
|
||
model_base_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""删除基础模型"""
|
||
|
||
ModelBaseService.delete_model_base(db=db, model_base_id=model_base_id)
|
||
return success(msg="基础模型删除成功")
|
||
|
||
|
||
@router.post("/model_plaza/{model_base_id}/add", response_model=ApiResponse)
|
||
def add_model_from_plaza(
|
||
model_base_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""从模型广场添加模型到模型列表"""
|
||
|
||
result = ModelBaseService.add_model_from_plaza(db=db, model_base_id=model_base_id, tenant_id=current_user.tenant_id)
|
||
return success(data=model_schema.ModelConfig.model_validate(result), msg="模型添加成功")
|
||
|
||
|
||
@router.get("/{model_id}", response_model=ApiResponse)
|
||
def get_model_by_id(
|
||
model_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
根据ID获取模型配置
|
||
"""
|
||
api_logger.info(f"获取模型配置请求: model_id={model_id}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始获取模型配置: model_id={model_id}")
|
||
result_orm = ModelConfigService.get_model_by_id(db=db, model_id=model_id, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"模型配置获取成功: {result_orm.name}")
|
||
|
||
# 将ORM对象转换为Pydantic模型
|
||
result_pydantic = model_schema.ModelConfig.model_validate(result_orm)
|
||
|
||
return success(data=result_pydantic, msg="模型配置获取成功")
|
||
except Exception as e:
|
||
api_logger.error(f"获取模型配置失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.post("", response_model=ApiResponse)
|
||
async def create_model(
|
||
model_data: model_schema.ModelConfigCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
创建模型配置
|
||
|
||
- 创建模型配置基础信息
|
||
- 如果包含 API Key,会先验证配置有效性,然后创建
|
||
- 验证失败时会抛出异常,不会创建配置
|
||
- 可通过 skip_validation=true 跳过验证
|
||
"""
|
||
api_logger.info(f"创建模型配置请求: {model_data.name}, 用户: {current_user.username}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始创建模型配置: {model_data.name}")
|
||
result_orm = await ModelConfigService.create_model(db=db, model_data=model_data, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"模型配置创建成功: {result_orm.name} (ID: {result_orm.id})")
|
||
|
||
# 将ORM对象转换为Pydantic模型
|
||
result = model_schema.ModelConfig.model_validate(result_orm)
|
||
|
||
return success(data=result, msg="模型配置创建成功")
|
||
except Exception as e:
|
||
api_logger.error(f"创建模型配置失败: {model_data.name} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.post("/composite", response_model=ApiResponse)
|
||
async def create_composite_model(
|
||
model_data: model_schema.CompositeModelCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
创建组合模型
|
||
|
||
- 绑定一个或多个现有的 API Key
|
||
- 所有 API Key 必须来自非组合模型
|
||
- 所有 API Key 关联的模型类型必须与组合模型类型一致
|
||
"""
|
||
api_logger.info(f"创建组合模型请求: {model_data.name}, 用户: {current_user.username}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
result_orm = await ModelConfigService.create_composite_model(db=db, model_data=model_data, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"组合模型创建成功: {result_orm.name} (ID: {result_orm.id})")
|
||
|
||
result = model_schema.ModelConfig.model_validate(result_orm)
|
||
return success(data=result, msg="组合模型创建成功")
|
||
except Exception as e:
|
||
api_logger.error(f"创建组合模型失败: {model_data.name} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.put("/composite/{model_id}", response_model=ApiResponse)
|
||
async def update_composite_model(
|
||
model_id: uuid.UUID,
|
||
model_data: model_schema.CompositeModelCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""更新组合模型"""
|
||
api_logger.info(f"更新组合模型请求: model_id={model_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
if model_data.type is not None:
|
||
raise BusinessException("不允许更改模型类型和供应商", BizCode.INVALID_PARAMETER)
|
||
result_orm = await ModelConfigService.update_composite_model(db=db, model_id=model_id, model_data=model_data, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"组合模型更新成功: {result_orm.name} (ID: {model_id})")
|
||
|
||
result = model_schema.ModelConfig.model_validate(result_orm)
|
||
return success(data=result, msg="组合模型更新成功")
|
||
except Exception as e:
|
||
api_logger.error(f"更新组合模型失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.delete("/composite/{model_id}", response_model=ApiResponse)
|
||
def delete_composite_model(
|
||
model_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""删除组合模型"""
|
||
api_logger.info(f"删除组合模型请求: model_id={model_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
ModelConfigService.delete_model(db=db, model_id=model_id, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"组合模型删除成功: model_id={model_id}")
|
||
return success(msg="组合模型删除成功")
|
||
except Exception as e:
|
||
api_logger.error(f"删除组合模型失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.put("/{model_id}", response_model=ApiResponse)
|
||
def update_model(
|
||
model_id: uuid.UUID,
|
||
model_data: model_schema.ModelConfigUpdate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
更新模型配置
|
||
"""
|
||
api_logger.info(f"更新模型配置请求: model_id={model_id}, 用户: {current_user.username}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始更新模型配置: model_id={model_id}")
|
||
result_orm = ModelConfigService.update_model(db=db, model_id=model_id, model_data=model_data, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"模型配置更新成功: {result_orm.name} (ID: {model_id})")
|
||
|
||
# 将ORM对象转换为Pydantic模型
|
||
result_pydantic = model_schema.ModelConfig.model_validate(result_orm)
|
||
|
||
return success(data=result_pydantic, msg="模型配置更新成功")
|
||
except Exception as e:
|
||
api_logger.error(f"更新模型配置失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.delete("/{model_id}", response_model=ApiResponse)
|
||
def delete_model(
|
||
model_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
删除模型配置
|
||
"""
|
||
api_logger.info(f"删除模型配置请求: model_id={model_id}, 用户: {current_user.username}, tenant_id={current_user.tenant_id}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始删除模型配置: model_id={model_id}")
|
||
ModelConfigService.delete_model(db=db, model_id=model_id, tenant_id=current_user.tenant_id)
|
||
api_logger.info(f"模型配置删除成功: model_id={model_id}")
|
||
return success(msg="模型配置删除成功")
|
||
except Exception as e:
|
||
api_logger.error(f"删除模型配置失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
# API Key 相关接口
|
||
@router.get("/{model_id}/apikeys", response_model=ApiResponse)
|
||
def get_model_api_keys(
|
||
model_id: uuid.UUID,
|
||
is_active: bool = Query(True, description="是否只获取活跃的API Key"),
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
获取模型的API Key列表
|
||
"""
|
||
api_logger.info(f"获取模型API Key列表请求: model_id={model_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始获取模型API Key列表: model_id={model_id}")
|
||
result_orm = ModelApiKeyService.get_api_keys_by_model(
|
||
db=db, model_config_id=model_id, is_active=is_active
|
||
)
|
||
|
||
# 将ORM对象列表转换为Pydantic模型列表
|
||
result_pydantic = [model_schema.ModelApiKey.model_validate(item) for item in result_orm]
|
||
|
||
api_logger.info(f"模型API Key列表获取成功: 数量={len(result_pydantic)}")
|
||
return success(data=result_pydantic, msg="模型API Key列表获取成功")
|
||
except Exception as e:
|
||
api_logger.error(f"获取模型API Key列表失败: model_id={model_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.post("/provider/apikeys", response_model=ApiResponse)
|
||
async def create_model_api_key_by_provider(
|
||
api_key_data: model_schema.ModelApiKeyCreateByProvider,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
根据供应商为所有匹配的模型创建API Key
|
||
"""
|
||
api_logger.info(f"创建API Key请求: provider={api_key_data.provider}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
# 根据tenant_id和provider筛选model_config_id列表
|
||
model_config_ids = api_key_data.model_config_ids
|
||
if not model_config_ids:
|
||
model_config_ids = ModelConfigRepository.get_model_config_ids_by_provider(
|
||
db=db,
|
||
tenant_id=current_user.tenant_id,
|
||
provider=api_key_data.provider
|
||
)
|
||
|
||
if not model_config_ids:
|
||
raise BusinessException(f"未找到供应商 {api_key_data.provider} 的模型配置", BizCode.MODEL_NOT_FOUND)
|
||
|
||
# 构造schema并调用service
|
||
create_data = model_schema.ModelApiKeyCreateByProvider(
|
||
provider=api_key_data.provider,
|
||
api_key=api_key_data.api_key,
|
||
api_base=api_key_data.api_base,
|
||
description=api_key_data.description,
|
||
config=api_key_data.config,
|
||
is_active=api_key_data.is_active,
|
||
priority=api_key_data.priority,
|
||
model_config_ids=model_config_ids
|
||
)
|
||
created_keys, failed_models = await ModelApiKeyService.create_api_key_by_provider(db=db, data=create_data)
|
||
|
||
api_logger.info(f"API Key创建成功: 关联{len(created_keys)}个模型")
|
||
# result_list = [model_schema.ModelApiKey.model_validate(key) for key in created_keys]
|
||
result = "API Key已存在" if len(created_keys) == 0 and len(failed_models) == 0 else \
|
||
f"成功为 {len(created_keys)} 个模型创建API Key, 失败模型列表{failed_models}"
|
||
return success(data=result, msg=f"成功为 {len(created_keys)} 个模型创建API Key")
|
||
except Exception as e:
|
||
api_logger.error(f"创建API Key失败: {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.post("/{model_id}/apikeys", response_model=ApiResponse, status_code=status.HTTP_201_CREATED)
|
||
async def create_model_api_key(
|
||
model_id: uuid.UUID,
|
||
api_key_data: model_schema.ModelApiKeyCreate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
为模型创建API Key
|
||
"""
|
||
api_logger.info(f"创建模型API Key请求: model_id={model_id}, model_name={api_key_data.model_name}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
# 设置模型配置ID
|
||
api_key_data.model_config_ids = [model_id]
|
||
|
||
api_logger.debug(f"开始创建模型API Key: {api_key_data.model_name}")
|
||
result_orm = await ModelApiKeyService.create_api_key(db=db, api_key_data=api_key_data)
|
||
api_logger.info(f"模型API Key创建成功: {result_orm.model_name} (ID: {result_orm.id})")
|
||
result = model_schema.ModelApiKey.model_validate(result_orm)
|
||
return success(data=result, msg="模型API Key创建成功")
|
||
except Exception as e:
|
||
api_logger.error(f"创建模型API Key失败: {api_key_data.model_name} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.get("/apikeys/{api_key_id}", response_model=ApiResponse)
|
||
def get_api_key_by_id(
|
||
api_key_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
根据ID获取API Key
|
||
"""
|
||
api_logger.info(f"获取API Key请求: api_key_id={api_key_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始获取API Key: api_key_id={api_key_id}")
|
||
result = ModelApiKeyService.get_api_key_by_id(db=db, api_key_id=api_key_id)
|
||
api_logger.info(f"API Key获取成功: {result.model_name}")
|
||
return success(data=result, msg="API Key获取成功")
|
||
except Exception as e:
|
||
api_logger.error(f"获取API Key失败: api_key_id={api_key_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.put("/apikeys/{api_key_id}", response_model=ApiResponse)
|
||
async def update_api_key(
|
||
api_key_id: uuid.UUID,
|
||
api_key_data: model_schema.ModelApiKeyUpdate,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
更新API Key
|
||
"""
|
||
api_logger.info(f"更新API Key请求: api_key_id={api_key_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始更新API Key: api_key_id={api_key_id}")
|
||
result = await ModelApiKeyService.update_api_key(db=db, api_key_id=api_key_id, api_key_data=api_key_data)
|
||
api_logger.info(f"API Key更新成功: {result.model_name} (ID: {api_key_id})")
|
||
result_pydantic = model_schema.ModelApiKey.model_validate(result)
|
||
return success(data=result_pydantic, msg="API Key更新成功")
|
||
except Exception as e:
|
||
api_logger.error(f"更新API Key失败: api_key_id={api_key_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.delete("/apikeys/{api_key_id}", response_model=ApiResponse)
|
||
def delete_api_key(
|
||
api_key_id: uuid.UUID,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
删除API Key
|
||
"""
|
||
api_logger.info(f"删除API Key请求: api_key_id={api_key_id}, 用户: {current_user.username}")
|
||
|
||
try:
|
||
api_logger.debug(f"开始删除API Key: api_key_id={api_key_id}")
|
||
ModelApiKeyService.delete_api_key(db=db, api_key_id=api_key_id)
|
||
api_logger.info(f"API Key删除成功: api_key_id={api_key_id}")
|
||
return success(msg="API Key删除成功")
|
||
except Exception as e:
|
||
api_logger.error(f"删除API Key失败: api_key_id={api_key_id} - {str(e)}")
|
||
raise
|
||
|
||
|
||
@router.post("/validate", response_model=ApiResponse)
|
||
async def validate_model_config(
|
||
validate_data: model_schema.ModelValidateRequest,
|
||
db: Session = Depends(get_db),
|
||
current_user: User = Depends(get_current_user)
|
||
):
|
||
"""
|
||
验证模型配置是否有效
|
||
|
||
支持验证不同类型的模型:
|
||
- llm: 大语言模型
|
||
- chat: 对话模型
|
||
- embedding: 向量模型
|
||
- rerank: 重排序模型
|
||
"""
|
||
api_logger.info(f"验证模型配置请求: {validate_data.model_name} ({validate_data.model_type}), 用户: {current_user.username}")
|
||
|
||
result = await ModelConfigService.validate_model_config(
|
||
db=db,
|
||
model_name=validate_data.model_name,
|
||
provider=validate_data.provider,
|
||
api_key=validate_data.api_key,
|
||
api_base=validate_data.api_base,
|
||
model_type=validate_data.model_type,
|
||
test_message=validate_data.test_message
|
||
)
|
||
|
||
return success(data=model_schema.ModelValidateResponse(**result), msg="验证完成")
|
||
|
||
|