From 36bc7268cd038a21ec6ae1fc7690a935c7ba45f8 Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Wed, 24 Dec 2025 20:12:49 +0800 Subject: [PATCH 1/9] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 756dc13..576a510 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) # 🤖 复合多AI智能体股票团队分析系统 - 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎! From ece4112c79cada53baa04d92f9b53f68320c7ee8 Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Wed, 24 Dec 2025 20:15:19 +0800 Subject: [PATCH 2/9] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 576a510..399ceb1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) # 🤖 复合多AI智能体股票团队分析系统 - 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎! +## 点击zread图标,查看详细文档 +[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) + ## ⭐ 1214更新 - 净利增长策略 📈 新增“净利增长策略”选股板块,专注稳健成长股票: From c216f518ff8da12aecc9b317e8a0bb3995b180ec Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Wed, 24 Dec 2025 20:16:05 +0800 Subject: [PATCH 3/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 399ceb1..4f8ff6b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎! -## 点击zread图标,查看详细文档 +**点击zread图标,查看详细文档** [![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) ## ⭐ 1214更新 - 净利增长策略 📈 From 64d7a6ee54f9071a18cad06fa6e9911952d36f1c Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:41:20 +0800 Subject: [PATCH 4/9] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f8ff6b..d73c083 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # 🤖 复合多AI智能体股票团队分析系统 -- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎! +- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!欢迎加入qq群聊 +QQ_1766893237734 **点击zread图标,查看详细文档** [![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) From 624d953c473940de84ae40fe5427d3314de142d1 Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:44:47 +0800 Subject: [PATCH 5/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d73c083..7492a0b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # 🤖 复合多AI智能体股票团队分析系统 - 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!欢迎加入qq群聊 -QQ_1766893237734 +QQ_1766893237734 **点击zread图标,查看详细文档** [![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/oficcejo/aiagents-stock) From e43dc51664084a35bb38bcf82b60a0838202e126 Mon Sep 17 00:00:00 2001 From: oficcejo <136165145+oficcejo@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:46:44 +0800 Subject: [PATCH 6/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7492a0b..f75cbc6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🤖 复合多AI智能体股票团队分析系统 -- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!欢迎加入qq群聊 +- 初心:在股市摸爬滚打多年,自学自编各种指标,花冤柉钱学习了各种战法各种策略,也曾入各种小班,总是赚少赔多,逐渐失去在股市玩的信心。自从去年deepseek上市,一直探索用ai辅助分析,且近日受tradingagents项目启发(感谢原作),多agent结合跟踪主力资金战法(某指每年收费6000rmb),用各种ai辅助编程,拼凑了这么个小程序,根据软件提供的辅助信息,实盘测试盈率还是挺高的,并且逐步形成了自己的交易系统,近一个月来,账户也慢慢在扰亏为盈。开源此软件的目的,就是为了使像我一样的小散,不再迷范。也许这个软件不能让你发大财,但是他能给你足够的信心。最后提醒:股市有风险,入市需谨慎!欢迎加入qq群聊,群号:1059277514 QQ_1766893237734 **点击zread图标,查看详细文档** From eac6156a5857681ad1683e4232c0e5abfd02edaa Mon Sep 17 00:00:00 2001 From: jlzhao6 Date: Fri, 9 Jan 2026 17:07:40 +0800 Subject: [PATCH 7/9] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E5=A4=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=A8=A1=E5=9E=8B=E5=8F=AA=E8=83=BD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?deepseek=E5=AE=98=E6=96=B9=E7=9A=84=EF=BC=8C=E4=B8=94=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=90=8D=E7=A7=B0=E5=86=99=E6=AD=BB=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82env=E4=B8=AD=E5=A2=9E=E5=8A=A0=20DEEPSEEK=5FMODEL=5FNA?= =?UTF-8?q?ME=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2、历史数据存储没有放入data目录下,导致容器容器后数据丢失 --- .env.example | 2 + ai_agents.py | 23 ++++++++-- app.py | 85 ++++++++++++++++++++++++++++++++--- config.py | 70 ++++++++++++++++++++++++++++- config_manager.py | 7 +++ database.py | 21 +++++++-- deepseek_client.py | 87 ++++++++++++++++++++++++++++++++++-- env_example.txt | 1 + longhubang_agents.py | 19 ++++++-- longhubang_db.py | 15 +++++-- longhubang_engine.py | 15 +++++-- longhubang_ui.py | 11 +++-- low_price_bull_monitor.py | 15 +++++-- main_force_analysis.py | 19 ++++++-- main_force_batch_db.py | 20 +++++++-- main_force_ui.py | 3 +- monitor_db.py | 20 ++++++++- portfolio_db.py | 8 +++- portfolio_manager.py | 19 ++++++-- profit_growth_monitor.py | 15 +++++-- restart_service.sh | 35 +++++++++++++++ sector_strategy_agents.py | 19 ++++++-- sector_strategy_db.py | 15 +++++-- sector_strategy_engine.py | 18 +++++--- sector_strategy_scheduler.py | 3 +- sector_strategy_ui.py | 7 ++- smart_monitor_db.py | 15 +++++-- smart_monitor_deepseek.py | 77 ++++++++++++++++++++++++++++--- smart_monitor_engine.py | 18 +++++--- update_env_example.py | 4 ++ 30 files changed, 607 insertions(+), 79 deletions(-) create mode 100755 restart_service.sh diff --git a/.env.example b/.env.example index 5529c41..bfeeb47 100644 --- a/.env.example +++ b/.env.example @@ -15,6 +15,8 @@ DEEPSEEK_API_KEY=your_actual_deepseek_api_key_here # DeepSeek API基础URL(可选,使用默认值即可) DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 +# DeepSeek 模型名称,为空时取默认值 deepseek-chat +DEEPSEEK_MODEL_NAME=deepseek-chat # ========== Tushare数据接口(可选)========== # Tushare Token(可选,用于获取更多金融数据) diff --git a/ai_agents.py b/ai_agents.py index 75ea06e..c6efe57 100644 --- a/ai_agents.py +++ b/ai_agents.py @@ -1,13 +1,30 @@ from deepseek_client import DeepSeekClient from typing import Dict, Any import time +import config class StockAnalysisAgents: """股票分析AI智能体集合""" - def __init__(self, model="deepseek-chat"): - self.model = model - self.deepseek_client = DeepSeekClient(model=model) + def __init__(self, model=None): + # 调试:打印传入的参数和配置 + print(f"[StockAnalysisAgents.__init__] 传入参数: model={model}") + print(f"[StockAnalysisAgents.__init__] 配置文件中的 DEEPSEEK_MODEL_NAME: {config.DEEPSEEK_MODEL_NAME}") + + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[StockAnalysisAgents.__init__] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + print(f"[StockAnalysisAgents.__init__] 使用配置文件中的默认模型: {self.model}") + else: + self.model = model + print(f"[StockAnalysisAgents.__init__] 使用传入的模型参数: {self.model}") + + print(f"[StockAnalysisAgents.__init__] ✅ 最终使用的模型: {self.model}") + self.deepseek_client = DeepSeekClient(model=self.model) def technical_analyst_agent(self, stock_info: Dict, stock_data: Any, indicators: Dict) -> Dict[str, Any]: """技术面分析智能体""" diff --git a/app.py b/app.py index f030097..24dd612 100644 --- a/app.py +++ b/app.py @@ -18,6 +18,7 @@ from monitor_service import monitor_service from notification_service import notification_service from config_manager import config_manager +import config from main_force_ui import display_main_force_selector from sector_strategy_ui import display_sector_strategy from longhubang_ui import display_longhubang @@ -37,11 +38,22 @@ def model_selector(): st.sidebar.markdown("---") st.sidebar.subheader("🤖 AI模型选择") - + # 获取配置文件中的默认模型 + default_model = config.DEEPSEEK_MODEL_NAME + + # 如果配置的模型不在选项中,使用列表第一个 + if default_model not in model_options: + default_model = list(model_options.keys())[0] + + # 如果 session_state 中已有值,且该值在选项中,使用它;否则使用配置的默认值 + current_model = st.session_state.get('selected_model', default_model) + if current_model not in model_options: + current_model = default_model selected_model = st.sidebar.selectbox( "选择AI模型", options=list(model_options.keys()), + index=list(model_options.keys()).index(current_model) if current_model in model_options else 0, format_func=lambda x: model_options[x], help="DeepSeek Reasoner提供更强的推理能力,但响应时间可能更长" ) @@ -277,6 +289,10 @@ def model_selector(): """, unsafe_allow_html=True) def main(): + # 初始化:检查配置文件中的默认模型,如果session_state中没有或值无效,使用配置文件的值 + if 'selected_model' not in st.session_state or st.session_state.get('selected_model') not in model_options: + st.session_state.selected_model = config.DEEPSEEK_MODEL_NAME if config.DEEPSEEK_MODEL_NAME in model_options else list(model_options.keys())[0] + # 顶部标题栏 st.markdown("""
@@ -410,7 +426,19 @@ def main(): # 模型选择器 selected_model = model_selector() - st.session_state.selected_model = selected_model + + # 如果配置文件中的默认模型发生了变化,且用户没有主动选择其他模型,更新为配置文件的值 + config_default_model = config.DEEPSEEK_MODEL_NAME + if config_default_model in model_options: + # 如果 session_state 中的值不在有效选项中,或者配置文件的值与当前选择不同且用户未手动选择过,使用配置文件的值 + if (selected_model not in model_options) or \ + (st.session_state.get('selected_model') not in model_options): + selected_model = config_default_model + st.session_state.selected_model = selected_model + else: + st.session_state.selected_model = selected_model + else: + st.session_state.selected_model = selected_model st.markdown("---") @@ -812,7 +840,20 @@ def parse_stock_list(stock_input): return unique_list -def analyze_single_stock_for_batch(symbol, period, enabled_analysts_config=None, selected_model='deepseek-chat'): +def analyze_single_stock_for_batch(symbol, period, enabled_analysts_config=None, selected_model=None): + # 强制使用配置文件中的默认模型(忽略传入的旧值) + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + config_model = config.DEEPSEEK_MODEL_NAME + if selected_model is None or selected_model == "" or selected_model == "deepseek-chat": + selected_model = config_model + print(f"[analyze_single_stock_for_batch] 强制使用配置文件中的模型: {selected_model} (传入值被忽略)") + else: + # 如果传入的模型在选项中,使用传入的值;否则使用配置文件的值 + if selected_model not in model_options: + selected_model = config_model + print(f"[analyze_single_stock_for_batch] 传入的模型不在选项中,使用配置文件中的模型: {selected_model}") + else: + print(f"[analyze_single_stock_for_batch] 使用传入的模型: {selected_model}") """单个股票分析(用于批量分析) Args: @@ -970,7 +1011,14 @@ def run_batch_analysis(stock_list, period, batch_mode="顺序分析"): 'sentiment': st.session_state.get('enable_sentiment', False), 'news': st.session_state.get('enable_news', False) } - selected_model = st.session_state.get('selected_model', 'deepseek-chat') + # 强制使用配置文件中的默认模型(忽略 session_state 中的旧值) + config_model = config.DEEPSEEK_MODEL_NAME + if config_model in model_options: + selected_model = config_model + else: + selected_model = list(model_options.keys())[0] + + print(f"[run_batch_analysis] 使用模型: {selected_model} (来自配置文件: {config_model})") # 创建进度显示 st.subheader(f"📊 批量分析进行中 ({batch_mode})") @@ -1242,8 +1290,17 @@ def run_stock_analysis(symbol, period): # 6. 初始化AI分析系统 status_text.text("🤖 正在初始化AI分析系统...") - # 使用选择的模型 - selected_model = st.session_state.get('selected_model', 'deepseek-chat') + # 获取模型,强制使用配置文件中的默认模型(忽略 session_state 中的旧值) + # 如果配置文件中的模型不在选项中,则使用第一个选项 + config_model = config.DEEPSEEK_MODEL_NAME + if config_model in model_options: + selected_model = config_model + else: + selected_model = list(model_options.keys())[0] + + print(f"[run_stock_analysis] 使用模型: {selected_model} (来自配置文件: {config_model})") + print(f"[run_stock_analysis] session_state中的selected_model: {st.session_state.get('selected_model', 'None')}") + agents = StockAnalysisAgents(model=selected_model) progress_bar.progress(55) @@ -2141,6 +2198,21 @@ def display_config_manager(): ) st.session_state.temp_config["DEEPSEEK_BASE_URL"] = new_base_url + st.markdown("---") + + # DeepSeek Model Name + default_model_name = config.DEEPSEEK_MODEL_NAME + model_name_info = config_info.get("DEEPSEEK_MODEL_NAME", {"value": default_model_name, "description": "DeepSeek模型名称", "required": False, "type": "text"}) + current_model_name = st.session_state.temp_config.get("DEEPSEEK_MODEL_NAME", model_name_info.get("value", default_model_name)) + + new_model_name = st.text_input( + f"🤖 {model_name_info['description']}", + value=current_model_name, + help="配置要使用的模型名称,如:deepseek-chat、deepseek-reasoner等", + key="input_deepseek_model_name" + ) + st.session_state.temp_config["DEEPSEEK_MODEL_NAME"] = new_model_name + st.info("💡 如何获取DeepSeek API密钥?\n\n1. 访问 https://platform.deepseek.com\n2. 注册/登录账号\n3. 进入API密钥管理页面\n4. 创建新的API密钥\n5. 复制密钥并粘贴到上方输入框") with tab2: @@ -2480,6 +2552,7 @@ def display_config_manager(): # ========== DeepSeek API配置 ========== DEEPSEEK_API_KEY="{current_config.get('DEEPSEEK_API_KEY', '')}" DEEPSEEK_BASE_URL="{current_config.get('DEEPSEEK_BASE_URL', '')}" +DEEPSEEK_MODEL_NAME="{current_config.get('DEEPSEEK_MODEL_NAME', config.DEEPSEEK_MODEL_NAME)}" # ========== Tushare数据接口(可选)========== TUSHARE_TOKEN="{current_config.get('TUSHARE_TOKEN', '')}" diff --git a/config.py b/config.py index 5d3830b..b88c892 100644 --- a/config.py +++ b/config.py @@ -1,12 +1,78 @@ import os +from pathlib import Path from dotenv import load_dotenv -# 加载环境变量(override=True 强制覆盖已存在的环境变量) -load_dotenv(override=True) +# 获取当前文件的目录 +current_dir = Path(__file__).parent.absolute() + +# 尝试多个可能的 .env 文件路径 +env_paths = [ + current_dir / '.env', # 当前目录 + Path('.env'), # 工作目录 + Path('/app/.env'), # Docker 容器中的路径 +] + +env_loaded = False +env_file_path = None + +# 尝试加载 .env 文件 +for env_path in env_paths: + if env_path.exists(): + env_loaded = load_dotenv(env_path, override=True) + if env_loaded: + env_file_path = env_path + print(f"[config.py] ✅ 成功加载 .env 文件: {env_path}") + break + else: + print(f"[config.py] .env 文件不存在: {env_path}") + +# 如果都没有找到,尝试从当前目录加载(load_dotenv 的默认行为) +if not env_loaded: + env_loaded = load_dotenv(override=True) + print(f"[config.py] 尝试默认路径加载 .env: {'成功' if env_loaded else '失败'}") # DeepSeek API配置 DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "") DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com/v1") +DEEPSEEK_MODEL_NAME = os.getenv("DEEPSEEK_MODEL_NAME", "deepseek-chat") + +# 调试:打印配置值(隐藏敏感信息) +print(f"[config.py] =========================================") +print(f"[config.py] 配置加载结果:") +print(f"[config.py] DEEPSEEK_MODEL_NAME: {DEEPSEEK_MODEL_NAME}") +print(f"[config.py] DEEPSEEK_BASE_URL: {DEEPSEEK_BASE_URL}") +print(f"[config.py] DEEPSEEK_API_KEY: {'已设置' if DEEPSEEK_API_KEY else '未设置'}") +print(f"[config.py] 环境变量 DEEPSEEK_MODEL_NAME: {os.getenv('DEEPSEEK_MODEL_NAME', '未设置')}") + +# 如果 DEEPSEEK_MODEL_NAME 仍然是默认值,尝试从 .env 文件直接读取 +if DEEPSEEK_MODEL_NAME == "deepseek-chat": + print("[config.py] ⚠️ 警告: DEEPSEEK_MODEL_NAME 仍然是默认值 'deepseek-chat'") + print("[config.py] 尝试直接读取 .env 文件...") + + # 尝试所有可能的路径 + for env_path in env_paths: + if env_path.exists(): + print(f"[config.py] 检查 .env 文件: {env_path}") + try: + with open(env_path, 'r', encoding='utf-8') as f: + for line_num, line in enumerate(f, 1): + line = line.strip() + # 跳过空行和注释 + if not line or line.startswith('#'): + continue + if 'DEEPSEEK_MODEL_NAME' in line and '=' in line: + value = line.split('=', 1)[1].strip().strip('"').strip("'") + if value and value != "deepseek-chat": + DEEPSEEK_MODEL_NAME = value + # 更新环境变量 + os.environ['DEEPSEEK_MODEL_NAME'] = value + print(f"[config.py] ✅ 从 .env 文件直接读取到 DEEPSEEK_MODEL_NAME: {DEEPSEEK_MODEL_NAME} (第 {line_num} 行)") + break + except Exception as e: + print(f"[config.py] ❌ 读取 .env 文件失败 ({env_path}): {e}") + +print(f"[config.py] 最终使用的 DEEPSEEK_MODEL_NAME: {DEEPSEEK_MODEL_NAME}") +print(f"[config.py] =========================================") # 其他配置 TUSHARE_TOKEN = os.getenv("TUSHARE_TOKEN", "") diff --git a/config_manager.py b/config_manager.py index 3881b50..94be8ce 100644 --- a/config_manager.py +++ b/config_manager.py @@ -26,6 +26,12 @@ def __init__(self, env_file: str = ".env"): "required": False, "type": "text" }, + "DEEPSEEK_MODEL_NAME": { + "value": "deepseek-chat", + "description": "DeepSeek模型名称", + "required": False, + "type": "text" + }, "TUSHARE_TOKEN": { "value": "", "description": "Tushare数据接口Token(可选)", @@ -172,6 +178,7 @@ def write_env(self, config: Dict[str, str]) -> bool: lines.append("# ========== DeepSeek API配置 ==========") lines.append(f'DEEPSEEK_API_KEY="{config.get("DEEPSEEK_API_KEY", "")}"') lines.append(f'DEEPSEEK_BASE_URL="{config.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com/v1")}"') + lines.append(f'DEEPSEEK_MODEL_NAME="{config.get("DEEPSEEK_MODEL_NAME", "deepseek-chat")}"') lines.append("") # Tushare配置 diff --git a/database.py b/database.py index 07dd0db..6d72fa9 100644 --- a/database.py +++ b/database.py @@ -4,13 +4,28 @@ import os class StockAnalysisDatabase: - def __init__(self, db_path="stock_analysis.db"): - """初始化数据库连接""" - self.db_path = db_path + def __init__(self, db_path=None): + """初始化数据库连接 + + Args: + db_path: 数据库文件路径,如果为None,则使用data目录下的stock_analysis.db(确保持久化) + """ + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + data_dir = os.path.join(os.path.dirname(__file__), 'data') + # 确保data目录存在 + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'stock_analysis.db') + else: + self.db_path = db_path + # 确保数据库所在目录存在 db_dir = os.path.dirname(self.db_path) if db_dir and not os.path.exists(db_dir): os.makedirs(db_dir, exist_ok=True) + + print(f"[StockAnalysisDatabase] 数据库文件路径: {self.db_path}") self.init_database() def init_database(self): diff --git a/deepseek_client.py b/deepseek_client.py index 17db710..f90e952 100644 --- a/deepseek_client.py +++ b/deepseek_client.py @@ -2,16 +2,55 @@ import json from typing import Dict, List, Any, Optional import config +import logging +import os + +# 配置日志 +logger = logging.getLogger(__name__) +# 如果没有配置handler,则添加默认配置 +if not logger.handlers: + logging.basicConfig( + level=logging.INFO, + format='[%(asctime)s] %(levelname)s %(name)s: %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + ) class DeepSeekClient: """DeepSeek API客户端""" - def __init__(self, model="deepseek-chat"): - self.model = model + def __init__(self, model=None): + # 调试:打印传入的参数和配置 + logger.info(f"[DeepSeekClient.__init__] 传入参数: model={model}") + logger.info(f"[DeepSeekClient.__init__] 配置文件中的 DEEPSEEK_MODEL_NAME: {config.DEEPSEEK_MODEL_NAME}") + print(f"[DeepSeekClient.__init__] 传入参数: model={model}") + print(f"[DeepSeekClient.__init__] 配置文件中的 DEEPSEEK_MODEL_NAME: {config.DEEPSEEK_MODEL_NAME}") + print(f"[DeepSeekClient.__init__] 环境变量 DEEPSEEK_MODEL_NAME: {os.getenv('DEEPSEEK_MODEL_NAME', '未设置')}") + + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + logger.warning(f"[DeepSeekClient.__init__] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + print(f"[DeepSeekClient.__init__] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + logger.info(f"[DeepSeekClient.__init__] 使用配置文件中的默认模型: {self.model}") + print(f"[DeepSeekClient.__init__] ✅ 使用配置文件中的默认模型: {self.model}") + # 如果配置文件的模型仍然是默认值,发出警告 + if self.model == "deepseek-chat": + print(f"[DeepSeekClient.__init__] ⚠️ 警告: 模型仍然是默认值 'deepseek-chat',请检查 .env 文件中的 DEEPSEEK_MODEL_NAME 配置") + else: + self.model = model + logger.info(f"[DeepSeekClient.__init__] 使用传入的模型参数: {self.model}") + print(f"[DeepSeekClient.__init__] 使用传入的模型参数: {self.model}") + + self.base_url = config.DEEPSEEK_BASE_URL self.client = openai.OpenAI( api_key=config.DEEPSEEK_API_KEY, - base_url=config.DEEPSEEK_BASE_URL + base_url=self.base_url ) + logger.info(f"[DeepSeekClient] 初始化完成 - 最终使用的模型: {self.model}, API地址: {self.base_url}") + print(f"[DeepSeekClient] ✅ 初始化完成 - 最终使用的模型: {self.model}, API地址: {self.base_url}") def call_api(self, messages: List[Dict[str, str]], model: Optional[str] = None, temperature: float = 0.7, max_tokens: int = 2000) -> str: @@ -20,9 +59,38 @@ def call_api(self, messages: List[Dict[str, str]], model: Optional[str] = None, model_to_use = model or self.model # 对于 reasoner 模型,自动增加 max_tokens + original_max_tokens = max_tokens if "reasoner" in model_to_use.lower() and max_tokens <= 2000: max_tokens = 8000 # reasoner 模型需要更多 tokens 来输出推理过程 + # 计算输入消息的token估算(简单估算:字符数/4) + total_chars = sum(len(str(msg.get('content', ''))) for msg in messages) + estimated_tokens = total_chars // 4 + + # 准备消息摘要(安全处理) + message_summaries = [] + for msg in messages[:3]: + role = msg.get('role', 'unknown') + content = str(msg.get('content', '')) + if len(content) > 50: + content = content[:50] + '...' + message_summaries.append(f"{role}:{content}") + + # 输出模型调用信息(同时输出到日志和控制台) + log_msg = f""" +{'=' * 60} +[DeepSeekClient] 准备调用API + 模型名称: {model_to_use} + API地址: {self.base_url} + 消息数量: {len(messages)} + 估算输入Token: ~{estimated_tokens} + 温度参数: {temperature} + 最大输出Token: {max_tokens}{f' (已从{original_max_tokens}自动调整)' if max_tokens != original_max_tokens else ''} + 消息摘要: {message_summaries} +{'=' * 60}""" + logger.info(log_msg) + print(log_msg) # 同时输出到控制台,方便调试 + try: response = self.client.chat.completions.create( model=model_to_use, @@ -31,6 +99,17 @@ def call_api(self, messages: List[Dict[str, str]], model: Optional[str] = None, max_tokens=max_tokens ) + # 输出响应信息 + if response and hasattr(response, 'usage'): + usage = response.usage + usage_info = f""" +[DeepSeekClient] API调用成功 + 实际输入Token: {usage.prompt_tokens if hasattr(usage, 'prompt_tokens') else 'N/A'} + 实际输出Token: {usage.completion_tokens if hasattr(usage, 'completion_tokens') else 'N/A'} + 总Token: {usage.total_tokens if hasattr(usage, 'total_tokens') else 'N/A'}""" + logger.info(usage_info) + print(usage_info) # 同时输出到控制台 + # 处理 reasoner 模型的响应 message = response.choices[0].message @@ -49,6 +128,8 @@ def call_api(self, messages: List[Dict[str, str]], model: Optional[str] = None, return result if result else "API返回空响应" except Exception as e: + logger.error(f"[DeepSeekClient] API调用失败: {str(e)}") + logger.error(f" 模型: {model_to_use}, API地址: {self.base_url}") return f"API调用失败: {str(e)}" def technical_analysis(self, stock_info: Dict, stock_data: Any, indicators: Dict) -> str: diff --git a/env_example.txt b/env_example.txt index 2549f5b..5cb109f 100644 --- a/env_example.txt +++ b/env_example.txt @@ -6,6 +6,7 @@ # DeepSeek API配置 DEEPSEEK_API_KEY=your_deepseek_api_key_here DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 +DEEPSEEK_MODEL_NAME=deepseek-chat # Tushare数据源配置(备用数据源) TUSHARE_TOKEN=your_tushare_token_here diff --git a/longhubang_agents.py b/longhubang_agents.py index fba5a39..34ceab6 100644 --- a/longhubang_agents.py +++ b/longhubang_agents.py @@ -6,15 +6,26 @@ from deepseek_client import DeepSeekClient from typing import Dict, Any, List import time +import config class LonghubangAgents: """龙虎榜AI分析师集合""" - def __init__(self, model="deepseek-chat"): - self.model = model - self.deepseek_client = DeepSeekClient(model=model) - print(f"[智瞰龙虎] AI分析师系统初始化 (模型: {model})") + def __init__(self, model=None): + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[智瞰龙虎] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + print(f"[智瞰龙虎] AI分析师系统初始化 - 使用配置文件中的默认模型: {self.model}") + else: + self.model = model + print(f"[智瞰龙虎] AI分析师系统初始化 - 使用传入的模型参数: {self.model}") + self.deepseek_client = DeepSeekClient(model=self.model) + print(f"[智瞰龙虎] AI分析师系统初始化完成 - 最终使用的模型: {self.model}") def youzi_behavior_analyst(self, longhubang_data: str, summary: Dict) -> Dict[str, Any]: """ diff --git a/longhubang_db.py b/longhubang_db.py index e9db828..4991a93 100644 --- a/longhubang_db.py +++ b/longhubang_db.py @@ -13,14 +13,23 @@ class LonghubangDatabase: """龙虎榜数据库管理类""" - def __init__(self, db_path='longhubang.db'): + def __init__(self, db_path=None): """ 初始化数据库 Args: - db_path: 数据库文件路径 + db_path: 数据库文件路径,如果为None,则使用data目录下的longhubang.db(确保持久化) """ - self.db_path = db_path + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'longhubang.db') + else: + self.db_path = db_path + print(f"[LonghubangDatabase] 数据库文件路径: {self.db_path}") # 初始化日志 self.logger = logging.getLogger(__name__) if not self.logger.handlers: diff --git a/longhubang_engine.py b/longhubang_engine.py index 69ecd06..d5b825f 100644 --- a/longhubang_engine.py +++ b/longhubang_engine.py @@ -16,17 +16,26 @@ class LonghubangEngine: """龙虎榜综合分析引擎""" - def __init__(self, model="deepseek-chat", db_path='longhubang.db'): + def __init__(self, model=None, db_path=None): """ 初始化分析引擎 Args: - model: AI模型名称 + model: AI模型名称(如果不传入,则使用配置文件中的默认模型) db_path: 数据库路径 """ + import config + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[智瞰龙虎引擎] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + self.model = model self.data_fetcher = LonghubangDataFetcher() self.database = LonghubangDatabase(db_path) - self.agents = LonghubangAgents(model=model) + self.agents = LonghubangAgents(model=self.model) self.scoring = LonghubangScoring() # 初始化日志 self.logger = logging.getLogger(__name__) diff --git a/longhubang_ui.py b/longhubang_ui.py index e10dc60..87162c1 100644 --- a/longhubang_ui.py +++ b/longhubang_ui.py @@ -13,6 +13,7 @@ from longhubang_engine import LonghubangEngine from longhubang_pdf import LonghubangPDFGenerator +import config def display_longhubang(): @@ -183,9 +184,13 @@ def display_analysis_tab(): st.error(f"❌ 分析失败: {result.get('error', '未知错误')}") -def run_longhubang_analysis(model="deepseek-chat", date=None, days=1): +def run_longhubang_analysis(model=None, date=None, days=1): """运行龙虎榜分析""" + # 如果没有传入model,则使用配置文件中的默认模型 + if model is None: + model = config.DEEPSEEK_MODEL_NAME + # 进度显示 progress_bar = st.progress(0) status_text = st.empty() @@ -1397,7 +1402,7 @@ def run_longhubang_batch_analysis(): 'sentiment': False, 'news': False }, - selected_model='deepseek-chat' + selected_model=config.DEEPSEEK_MODEL_NAME ) results.append({ @@ -1428,7 +1433,7 @@ def analyze_one(code): 'sentiment': False, 'news': False }, - selected_model='deepseek-chat' + selected_model=config.DEEPSEEK_MODEL_NAME ) return {"code": code, "result": result} except Exception as e: diff --git a/low_price_bull_monitor.py b/low_price_bull_monitor.py index 4963eb9..61dec68 100644 --- a/low_price_bull_monitor.py +++ b/low_price_bull_monitor.py @@ -16,15 +16,24 @@ class LowPriceBullMonitor: """低价擒牛策略监控器""" - def __init__(self, db_path: str = "low_price_bull_monitor.db"): + def __init__(self, db_path: str = None): """ 初始化监控器 Args: - db_path: 数据库文件路径 + db_path: 数据库文件路径,如果为None,则使用data目录下的low_price_bull_monitor.db(确保持久化) """ self.logger = logging.getLogger(__name__) - self.db_path = db_path + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'low_price_bull_monitor.db') + else: + self.db_path = db_path + print(f"[LowPriceBullMonitor] 数据库文件路径: {self.db_path}") self._init_database() def _init_database(self): diff --git a/main_force_analysis.py b/main_force_analysis.py index f7de82a..902a9d5 100644 --- a/main_force_analysis.py +++ b/main_force_analysis.py @@ -14,14 +14,27 @@ import time import json +import config + class MainForceAnalyzer: """主力选股分析器 - 批量整体分析""" - def __init__(self, model='deepseek-chat'): + def __init__(self, model=None): + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[MainForceAnalyzer] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + print(f"[MainForceAnalyzer] 使用配置文件中的默认模型: {self.model}") + else: + self.model = model + print(f"[MainForceAnalyzer] 使用传入的模型参数: {self.model}") + print(f"[MainForceAnalyzer] ✅ 最终使用的模型: {self.model}") self.selector = main_force_selector self.fetcher = StockDataFetcher() - self.model = model - self.agents = StockAnalysisAgents(model=model) + self.agents = StockAnalysisAgents(model=self.model) self.deepseek_client = self.agents.deepseek_client self.raw_stocks = None self.final_recommendations = [] diff --git a/main_force_batch_db.py b/main_force_batch_db.py index 55093c7..716dbed 100644 --- a/main_force_batch_db.py +++ b/main_force_batch_db.py @@ -13,9 +13,23 @@ class MainForceBatchDatabase: """主力选股批量分析历史数据库管理类""" - def __init__(self, db_path: str = "main_force_batch.db"): - """初始化数据库连接""" - self.db_path = db_path + def __init__(self, db_path: str = None): + """ + 初始化数据库连接 + + Args: + db_path: 数据库文件路径,如果为None,则使用data目录下的main_force_batch.db(确保持久化) + """ + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'main_force_batch.db') + else: + self.db_path = db_path + print(f"[MainForceBatchDatabase] 数据库文件路径: {self.db_path}") self._init_database() def _init_database(self): diff --git a/main_force_ui.py b/main_force_ui.py index 5477f48..75a542d 100644 --- a/main_force_ui.py +++ b/main_force_ui.py @@ -10,6 +10,7 @@ from main_force_pdf_generator import display_report_download_section from main_force_history_ui import display_batch_history import pandas as pd +import config def display_main_force_selector(): """显示主力选股界面""" @@ -613,7 +614,7 @@ def run_main_force_batch_analysis(): 'sentiment': False, # 禁用以提升速度 'news': False # 禁用以提升速度 } - selected_model = 'deepseek-chat' + selected_model = config.DEEPSEEK_MODEL_NAME period = '1y' # 创建进度显示 diff --git a/monitor_db.py b/monitor_db.py index 0d9ca56..bbfaf4e 100644 --- a/monitor_db.py +++ b/monitor_db.py @@ -7,12 +7,28 @@ class StockMonitorDatabase: """股票监测数据库管理类""" - def __init__(self, db_path: str = "stock_monitor.db"): - self.db_path = db_path + def __init__(self, db_path: str = None): + """ + 初始化数据库 + + Args: + db_path: 数据库文件路径,如果为None,则使用data目录下的stock_monitor.db(确保持久化) + """ + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'stock_monitor.db') + else: + self.db_path = db_path + # 确保数据库所在目录存在 db_dir = os.path.dirname(self.db_path) if db_dir and not os.path.exists(db_dir): os.makedirs(db_dir, exist_ok=True) + + print(f"[StockMonitorDatabase] 数据库文件路径: {self.db_path}") self.init_database() def init_database(self): diff --git a/portfolio_db.py b/portfolio_db.py index 6b0f595..591b9e5 100644 --- a/portfolio_db.py +++ b/portfolio_db.py @@ -9,8 +9,12 @@ from typing import List, Dict, Optional, Tuple import os -# 数据库文件路径 -DB_PATH = "portfolio_stocks.db" +# 数据库文件路径(使用data目录确保持久化) +_data_dir = os.path.join(os.path.dirname(__file__), 'data') +if not os.path.exists(_data_dir): + os.makedirs(_data_dir, exist_ok=True) +DB_PATH = os.path.join(_data_dir, "portfolio_stocks.db") +print(f"[PortfolioDB] 数据库文件路径: {DB_PATH}") class PortfolioDB: diff --git a/portfolio_manager.py b/portfolio_manager.py index e23e85f..3ad8cb6 100644 --- a/portfolio_manager.py +++ b/portfolio_manager.py @@ -13,17 +13,30 @@ from portfolio_db import portfolio_db +import config + class PortfolioManager: """持仓管理器类""" - def __init__(self, model="deepseek-chat"): + def __init__(self, model=None): """ 初始化持仓管理器 Args: - model: AI模型(deepseek-chat 或 deepseek-reasoner) + model: AI模型(如果不传入,则使用配置文件中的默认模型) """ - self.model = model + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[PortfolioManager] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + print(f"[PortfolioManager] 使用配置文件中的默认模型: {self.model}") + else: + self.model = model + print(f"[PortfolioManager] 使用传入的模型参数: {self.model}") + print(f"[PortfolioManager] ✅ 最终使用的模型: {self.model}") self.db = portfolio_db # ==================== 持仓股票管理 ==================== diff --git a/profit_growth_monitor.py b/profit_growth_monitor.py index 869963a..061ac08 100644 --- a/profit_growth_monitor.py +++ b/profit_growth_monitor.py @@ -15,14 +15,23 @@ class ProfitGrowthMonitor: """净利增长策略监控数据库管理""" - def __init__(self, db_path: str = "profit_growth_monitor.db"): + def __init__(self, db_path: str = None): """ 初始化监控数据库 Args: - db_path: 数据库文件路径 + db_path: 数据库文件路径,如果为None,则使用data目录下的profit_growth_monitor.db(确保持久化) """ - self.db_path = db_path + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'profit_growth_monitor.db') + else: + self.db_path = db_path + print(f"[ProfitGrowthMonitor] 数据库文件路径: {self.db_path}") self.logger = logging.getLogger(__name__) self._init_database() diff --git a/restart_service.sh b/restart_service.sh new file mode 100755 index 0000000..909799e --- /dev/null +++ b/restart_service.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# 停止并重启 Docker 服务脚本 + +cd "$(dirname "$0")" + +echo "==========================================" +echo "停止并重启 Docker 服务" +echo "==========================================" +echo "" + +# 1. 停止服务 +echo "1. 停止现有服务..." +docker-compose down +echo "" + +# 2. 重新构建(使用 --no-cache 确保使用最新代码) +echo "2. 重新构建 Docker 镜像(这可能需要几分钟)..." +docker-compose build --no-cache +echo "" + +# 3. 启动服务 +echo "3. 启动服务..." +docker-compose up -d +echo "" + +# 4. 查看服务状态 +echo "4. 查看服务状态..." +sleep 3 +docker-compose ps +echo "" + +# 5. 查看日志 +echo "5. 查看最新日志(按 Ctrl+C 退出)..." +echo "==========================================" +docker-compose logs -f --tail=50 diff --git a/sector_strategy_agents.py b/sector_strategy_agents.py index 6383ba9..7b477e9 100644 --- a/sector_strategy_agents.py +++ b/sector_strategy_agents.py @@ -6,15 +6,26 @@ from deepseek_client import DeepSeekClient from typing import Dict, Any import time +import config class SectorStrategyAgents: """板块策略AI智能体集合""" - def __init__(self, model="deepseek-chat"): - self.model = model - self.deepseek_client = DeepSeekClient(model=model) - print(f"[智策] AI智能体系统初始化 (模型: {model})") + def __init__(self, model=None): + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[智策] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + print(f"[智策] AI智能体系统初始化 - 使用配置文件中的默认模型: {self.model}") + else: + self.model = model + print(f"[智策] AI智能体系统初始化 - 使用传入的模型参数: {self.model}") + self.deepseek_client = DeepSeekClient(model=self.model) + print(f"[智策] AI智能体系统初始化完成 - 最终使用的模型: {self.model}") def macro_strategist_agent(self, market_data: Dict, news_data: list) -> Dict[str, Any]: """ diff --git a/sector_strategy_db.py b/sector_strategy_db.py index 38b8253..8209d5b 100644 --- a/sector_strategy_db.py +++ b/sector_strategy_db.py @@ -13,14 +13,23 @@ class SectorStrategyDatabase: """智策板块数据库管理类""" - def __init__(self, db_path='sector_strategy.db'): + def __init__(self, db_path=None): """ 初始化数据库 Args: - db_path: 数据库文件路径 + db_path: 数据库文件路径,如果为None,则使用data目录下的sector_strategy.db(确保持久化) """ - self.db_path = db_path + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_path is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_path = os.path.join(data_dir, 'sector_strategy.db') + else: + self.db_path = db_path + print(f"[SectorStrategyDatabase] 数据库文件路径: {self.db_path}") # 初始化日志 self.logger = logging.getLogger(__name__) if not self.logger.handlers: diff --git a/sector_strategy_engine.py b/sector_strategy_engine.py index 5e39364..81668be 100644 --- a/sector_strategy_engine.py +++ b/sector_strategy_engine.py @@ -11,20 +11,28 @@ import json import pandas as pd import logging +import config class SectorStrategyEngine: """板块策略综合研判引擎""" - def __init__(self, model="deepseek-chat"): - self.model = model - self.agents = SectorStrategyAgents(model=model) - self.deepseek_client = DeepSeekClient(model=model) + def __init__(self, model=None): + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + print(f"[智策引擎] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + self.model = model + self.agents = SectorStrategyAgents(model=self.model) + self.deepseek_client = DeepSeekClient(model=self.model) self.database = SectorStrategyDatabase() self.logger = logging.getLogger(__name__) if not self.logger.handlers: logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s %(name)s: %(message)s') - print(f"[智策引擎] 初始化完成 (模型: {model})") + print(f"[智策引擎] 初始化完成 - 最终使用的模型: {self.model} (传入参数: {model}, 配置默认: {config.DEEPSEEK_MODEL_NAME})") def save_raw_data_with_fallback(self, data_type, data_df, data_date=None): """ diff --git a/sector_strategy_scheduler.py b/sector_strategy_scheduler.py index 60436e9..440914e 100644 --- a/sector_strategy_scheduler.py +++ b/sector_strategy_scheduler.py @@ -11,6 +11,7 @@ from sector_strategy_engine import SectorStrategyEngine from notification_service import notification_service import json +import config class SectorStrategyScheduler: @@ -128,7 +129,7 @@ def _run_analysis(self): # 2. 运行AI分析 print("[智策定时] [2/3] AI智能体分析中...") - engine = SectorStrategyEngine(model="deepseek-chat") + engine = SectorStrategyEngine(model=config.DEEPSEEK_MODEL_NAME) result = engine.run_comprehensive_analysis(data) if not result.get("success"): diff --git a/sector_strategy_ui.py b/sector_strategy_ui.py index dc5f13a..126c3cb 100644 --- a/sector_strategy_ui.py +++ b/sector_strategy_ui.py @@ -18,6 +18,7 @@ from sector_strategy_pdf import SectorStrategyPDFGenerator from sector_strategy_db import SectorStrategyDatabase from sector_strategy_scheduler import sector_strategy_scheduler +import config def _parse_json_field(value, default): @@ -261,9 +262,13 @@ def display_report_detail(report_id): st.info("当前版本仅提供报告摘要,详细页面已移除。") -def run_sector_strategy_analysis(model="deepseek-chat"): +def run_sector_strategy_analysis(model=None): """运行智策分析""" + # 如果没有传入model,则使用配置文件中的默认模型 + if model is None: + model = config.DEEPSEEK_MODEL_NAME + # 进度显示 progress_bar = st.progress(0) status_text = st.empty() diff --git a/smart_monitor_db.py b/smart_monitor_db.py index 7a22fd5..afee645 100644 --- a/smart_monitor_db.py +++ b/smart_monitor_db.py @@ -13,14 +13,23 @@ class SmartMonitorDB: """智能盯盘数据库""" - def __init__(self, db_file: str = 'smart_monitor.db'): + def __init__(self, db_file: str = None): """ 初始化数据库 Args: - db_file: 数据库文件路径 + db_file: 数据库文件路径,如果为None,则使用data目录下的smart_monitor.db(确保持久化) """ - self.db_file = db_file + # 如果没有指定路径,使用data目录下的数据库文件(确保容器重启后数据不丢失) + if db_file is None: + import os + data_dir = os.path.join(os.path.dirname(__file__), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir, exist_ok=True) + self.db_file = os.path.join(data_dir, 'smart_monitor.db') + else: + self.db_file = db_file + print(f"[SmartMonitorDB] 数据库文件路径: {self.db_file}") self.logger = logging.getLogger(__name__) self._init_database() diff --git a/smart_monitor_deepseek.py b/smart_monitor_deepseek.py index 622fe99..db27a6e 100644 --- a/smart_monitor_deepseek.py +++ b/smart_monitor_deepseek.py @@ -7,25 +7,43 @@ from typing import Dict, List, Optional from datetime import datetime, time import pytz +import config class SmartMonitorDeepSeek: """A股智能盯盘 - DeepSeek AI决策引擎""" - def __init__(self, api_key: str): + def __init__(self, api_key: str, base_url: str = None, model: str = None): """ 初始化DeepSeek客户端 Args: api_key: DeepSeek API密钥 + base_url: API基础URL(可选,默认使用配置文件的值) + model: 模型名称(可选,默认使用配置文件的值) """ self.api_key = api_key - self.base_url = "https://api.deepseek.com/v1" + # 如果没有传入base_url,则使用配置文件中的默认值 + if base_url is None or base_url == "": + self.base_url = config.DEEPSEEK_BASE_URL + else: + self.base_url = base_url + # 强制使用配置文件中的默认模型 + # 如果传入的是 None、空字符串或旧的默认值 "deepseek-chat",都使用配置文件的值 + if model is None or model == "" or model == "deepseek-chat": + self.model = config.DEEPSEEK_MODEL_NAME + if model == "deepseek-chat": + self.logger.warning(f"[SmartMonitorDeepSeek] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + print(f"[SmartMonitorDeepSeek] ⚠️ 检测到传入的模型是旧的默认值 'deepseek-chat',强制使用配置文件中的模型: {self.model}") + else: + self.model = model self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } self.logger = logging.getLogger(__name__) + self.logger.info(f"[SmartMonitorDeepSeek] 初始化完成 - 模型: {self.model}, API地址: {self.base_url}") + print(f"[SmartMonitorDeepSeek] 初始化完成 - 模型: {self.model}, API地址: {self.base_url}") def is_trading_time(self) -> bool: """ @@ -138,14 +156,14 @@ def get_trading_session(self) -> Dict: 'can_trade': False } - def chat_completion(self, messages: List[Dict], model: str = "deepseek-chat", + def chat_completion(self, messages: List[Dict], model: str = None, temperature: float = 0.7, max_tokens: int = 2000) -> Dict: """ 调用DeepSeek API Args: messages: 对话消息列表 - model: 模型名称 + model: 模型名称(如果不传入,则使用配置文件中的默认模型) temperature: 温度参数 max_tokens: 最大token数 @@ -154,8 +172,39 @@ def chat_completion(self, messages: List[Dict], model: str = "deepseek-chat", """ import requests + # 如果没有传入model,则使用配置文件中的默认模型 + model_to_use = model or self.model + + # 计算输入消息的token估算(简单估算:字符数/4) + total_chars = sum(len(str(msg.get('content', ''))) for msg in messages) + estimated_tokens = total_chars // 4 + + # 准备消息摘要(安全处理) + message_summaries = [] + for msg in messages[:3]: + role = msg.get('role', 'unknown') + content = str(msg.get('content', '')) + if len(content) > 50: + content = content[:50] + '...' + message_summaries.append(f"{role}:{content}") + + # 输出模型调用信息(同时输出到日志和控制台) + log_msg = f""" +{'=' * 60} +[SmartMonitorDeepSeek] 准备调用API + 模型名称: {model_to_use} + API地址: {self.base_url} + 消息数量: {len(messages)} + 估算输入Token: ~{estimated_tokens} + 温度参数: {temperature} + 最大输出Token: {max_tokens} + 消息摘要: {message_summaries} +{'=' * 60}""" + self.logger.info(log_msg) + print(log_msg) # 同时输出到控制台,方便调试 + payload = { - "model": model, + "model": model_to_use, "messages": messages, "temperature": temperature, "max_tokens": max_tokens @@ -169,9 +218,23 @@ def chat_completion(self, messages: List[Dict], model: str = "deepseek-chat", timeout=60 ) response.raise_for_status() - return response.json() + result = response.json() + + # 输出响应信息 + if result and 'usage' in result: + usage = result['usage'] + usage_info = f""" +[SmartMonitorDeepSeek] API调用成功 + 实际输入Token: {usage.get('prompt_tokens', 'N/A')} + 实际输出Token: {usage.get('completion_tokens', 'N/A')} + 总Token: {usage.get('total_tokens', 'N/A')}""" + self.logger.info(usage_info) + print(usage_info) # 同时输出到控制台 + + return result except Exception as e: - self.logger.error(f"DeepSeek API调用失败: {e}") + self.logger.error(f"[SmartMonitorDeepSeek] API调用失败: {e}") + self.logger.error(f" 模型: {model_to_use}, API地址: {self.base_url}") raise def analyze_stock_and_decide(self, stock_code: str, market_data: Dict, diff --git a/smart_monitor_engine.py b/smart_monitor_engine.py index 0c35798..a1d0468 100644 --- a/smart_monitor_engine.py +++ b/smart_monitor_engine.py @@ -15,6 +15,7 @@ from smart_monitor_db import SmartMonitorDB from notification_service import notification_service # 复用主程序的通知服务 from config_manager import config_manager # 复用主程序的配置管理器 +import config # 导入config模块以使用DEEPSEEK_BASE_URL和DEEPSEEK_MODEL_NAME class SmartMonitorEngine: @@ -33,23 +34,30 @@ def __init__(self, deepseek_api_key: str = None, qmt_account_id: str = None, self.logger = logging.getLogger(__name__) # 从配置管理器读取配置 - config = config_manager.read_env() + env_config = config_manager.read_env() # DeepSeek API if deepseek_api_key is None: - deepseek_api_key = config.get('DEEPSEEK_API_KEY', '') + deepseek_api_key = env_config.get('DEEPSEEK_API_KEY', '') # MiniQMT配置 if qmt_account_id is None: - qmt_account_id = config.get('MINIQMT_ACCOUNT_ID', '') + qmt_account_id = env_config.get('MINIQMT_ACCOUNT_ID', '') if use_simulator is None: # 如果MINIQMT_ENABLED=false,则使用模拟器 - miniqmt_enabled = config.get('MINIQMT_ENABLED', 'false').lower() == 'true' + miniqmt_enabled = env_config.get('MINIQMT_ENABLED', 'false').lower() == 'true' use_simulator = not miniqmt_enabled # 初始化各个模块 - self.deepseek = SmartMonitorDeepSeek(deepseek_api_key) + # 从config模块读取 base_url 和 model(从.env文件加载的配置) + deepseek_base_url = config.DEEPSEEK_BASE_URL + deepseek_model = config.DEEPSEEK_MODEL_NAME + self.deepseek = SmartMonitorDeepSeek( + api_key=deepseek_api_key, + base_url=deepseek_base_url, + model=deepseek_model + ) self.data_fetcher = SmartMonitorDataFetcher() self.db = SmartMonitorDB() self.notification = notification_service # 使用主程序的通知服务 diff --git a/update_env_example.py b/update_env_example.py index 9a054dc..94b5597 100644 --- a/update_env_example.py +++ b/update_env_example.py @@ -18,6 +18,10 @@ # DeepSeek API基础URL(可选,使用默认值即可) DEEPSEEK_BASE_URL=https://api.deepseek.com/v1 +# DeepSeek模型名称(可选,默认:deepseek-chat) +# 可选模型:deepseek-chat、deepseek-reasoner等 +DEEPSEEK_MODEL_NAME=deepseek-chat + # ========== Tushare数据接口(可选)========== # Tushare Token(可选,用于获取更多金融数据) From 7fffe31d24a08e6bf6fe3148e93b1bf7d7286113 Mon Sep 17 00:00:00 2001 From: jlzhao6 Date: Tue, 20 Jan 2026 14:14:12 +0800 Subject: [PATCH 8/9] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E5=A4=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=A8=A1=E5=9E=8B=E5=8F=AA=E8=83=BD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?deepseek=E5=AE=98=E6=96=B9=E7=9A=84=EF=BC=8C=E4=B8=94=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=90=8D=E7=A7=B0=E5=86=99=E6=AD=BB=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82env=E4=B8=AD=E5=A2=9E=E5=8A=A0=20DEEPSEEK=5FMODEL=5FNA?= =?UTF-8?q?ME=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2、历史数据存储没有放入data目录下,导致容器容器后数据丢失 --- .gitignore | 20 +- ...11\346\213\251\350\257\264\346\230\216.md" | 258 ++++++++ app.py | 101 ++-- check_qmt_status.py | 211 +++++++ cleanup_root_databases.sh | 40 ++ database_check_report.md | 110 ++++ database_fix_recommendations.md | 147 +++++ database_migration_summary.md | 183 ++++++ env/__init__.py | 0 ...46\265\213path\344\277\235\345\255\230.py" | 266 +++++++++ ...42\344\277\235\345\255\230\347\211\210.py" | 173 ++++++ longhubang.db | Bin 991232 -> 0 bytes longhubang_ui.py | 47 +- low_price_bull_monitor.db | Bin 20480 -> 0 bytes main_force_batch.db | Bin 7094272 -> 0 bytes main_force_batch_db.py | 248 +++++--- main_force_history_ui.py | 65 +++ main_force_ui.py | 551 +++++++++++------- migrate_all_databases_to_data.py | 185 ++++++ portfolio_manager.py | 23 +- portfolio_stocks.db | Bin 28672 -> 0 bytes portfolio_ui.py | 16 +- profit_growth_monitor.db | Bin 20480 -> 0 bytes sector_strategy.db | Bin 294912 -> 0 bytes sector_strategy_agents.py | 33 +- sector_strategy_ui.py | 39 +- smart_monitor.db | Bin 315392 -> 0 bytes stock_analysis.db | Bin 22032384 -> 0 bytes stock_monitor.db | Bin 20480 -> 0 bytes 29 files changed, 2330 insertions(+), 386 deletions(-) create mode 100644 "AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md" create mode 100755 check_qmt_status.py create mode 100755 cleanup_root_databases.sh create mode 100644 database_check_report.md create mode 100644 database_fix_recommendations.md create mode 100644 database_migration_summary.md create mode 100644 env/__init__.py create mode 100644 "env/miniQMT(1\347\216\257\345\242\203)\343\200\220\345\205\210\347\224\250\350\277\231\344\270\252\343\200\221-\347\273\210\347\253\257\347\216\257\345\242\203\346\243\200\346\265\213path\344\277\235\345\255\230.py" create mode 100644 "env/miniQMT(2\350\264\246\346\210\267)\346\237\245\350\257\242\344\277\235\345\255\230\347\211\210.py" delete mode 100644 longhubang.db delete mode 100644 low_price_bull_monitor.db delete mode 100644 main_force_batch.db create mode 100644 migrate_all_databases_to_data.py delete mode 100644 portfolio_stocks.db delete mode 100644 profit_growth_monitor.db delete mode 100644 sector_strategy.db delete mode 100644 smart_monitor.db delete mode 100644 stock_analysis.db delete mode 100644 stock_monitor.db diff --git a/.gitignore b/.gitignore index 1dfa6a0..98fb92c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,22 @@ .env /.cursor /openspec -TradEnv/ \ No newline at end of file +TradEnv/ +/.idea/inspectionProfiles/profiles_settings.xml +/.idea/inspectionProfiles/Project_Default.xml +/.idea/.gitignore +/.idea/aiagents-stock.iml +/.idea/misc.xml +/.idea/modules.xml +/.idea/vcs.xml +/data/longhubang.db +/data/low_price_bull_monitor.db +/data/main_force_batch.db +/data/portfolio_stocks.db +/data/profit_growth_monitor.db +/data/sector_strategy.db +/data/smart_monitor.db +/data/stock_analysis.db +/data/stock_monitor.db +/migrate_databases.sh +/migrate_databases_by_size.sh diff --git "a/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md" "b/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md" new file mode 100644 index 0000000..ccd0e32 --- /dev/null +++ "b/AI\346\250\241\345\236\213\351\200\211\346\213\251\350\257\264\346\230\216.md" @@ -0,0 +1,258 @@ +# AI模型选择机制说明 + +## 📋 问题回答 + +### 1. 左侧的AI模型选择会全局默认生效吗? + +**答案:部分生效,但不完全全局** + +**当前状态**: +- ✅ 模型选择器会保存到 `st.session_state.selected_model` +- ❌ 但很多功能模块**强制使用** `config.DEEPSEEK_MODEL_NAME`(从 `.env` 文件读取),**忽略**了 `session_state` 中的选择 +- ✅ 只有部分页面(如"主力选股")会使用页面内的模型选择 + +**具体表现**: +- **股票分析页面**:强制使用 `config.DEEPSEEK_MODEL_NAME`,忽略侧边栏选择 +- **批量分析功能**:强制使用 `config.DEEPSEEK_MODEL_NAME`,忽略侧边栏选择 +- **主力选股页面**:使用页面内的模型选择(不是侧边栏的) +- **智策板块页面**:强制使用 `config.DEEPSEEK_MODEL_NAME` + +### 2. 如果选择其他模型,模型信息在哪里配置? + +**答案:两个地方** + +#### 位置1:模型选项列表 - `model_config.py` + +**文件路径**:`model_config.py` + +**作用**:定义所有可用的AI模型选项 + +**内容示例**: +```python +model_options = { + "deepseek-chat": "DeepSeek Chat (默认)", + "deepseek-reasoner": "DeepSeek Reasoner (推理增强)", + "qwen-plus": "qwen-plus (阿里百炼)", + # ... 更多模型 +} +``` + +**如何添加新模型**: +1. 在 `model_config.py` 的 `model_options` 字典中添加新项 +2. 格式:`"模型ID": "显示名称"` + +#### 位置2:默认模型配置 - `.env` 文件 + +**文件路径**:`.env`(项目根目录) + +**作用**:设置系统默认使用的模型 + +**配置项**: +```bash +DEEPSEEK_MODEL_NAME=deepseek-chat +``` + +**如何修改默认模型**: +1. 编辑 `.env` 文件 +2. 修改 `DEEPSEEK_MODEL_NAME` 的值 +3. 值必须是 `model_config.py` 中 `model_options` 的键之一 + +--- + +## 🔍 代码实现分析 + +### 模型选择器(侧边栏) + +**位置**:`app.py` 的 `model_selector()` 函数 + +**代码**: +```python +def model_selector(): + """模型选择器""" + st.sidebar.subheader("🤖 AI模型选择") + + # 获取配置文件中的默认模型 + default_model = config.DEEPSEEK_MODEL_NAME + + # 从 session_state 获取当前选择 + current_model = st.session_state.get('selected_model', default_model) + + # 显示选择框 + selected_model = st.sidebar.selectbox( + "选择AI模型", + options=list(model_options.keys()), + ... + ) + + return selected_model +``` + +**问题**:虽然保存到 `session_state`,但很多地方不使用它 + +### 实际使用情况 + +#### ❌ 不生效的地方(强制使用配置文件) + +**1. 股票分析页面** (`app.py` 的 `run_stock_analysis`) +```python +# 强制使用配置文件中的默认模型(忽略 session_state 中的旧值) +config_model = config.DEEPSEEK_MODEL_NAME +if config_model in model_options: + selected_model = config_model +else: + selected_model = list(model_options.keys())[0] + +agents = StockAnalysisAgents(model=selected_model) # 使用配置文件的值 +``` + +**2. 批量分析功能** (`app.py` 的 `run_batch_analysis`) +```python +# 强制使用配置文件中的默认模型 +config_model = config.DEEPSEEK_MODEL_NAME +if config_model in model_options: + selected_model = config_model +else: + selected_model = list(model_options.keys())[0] +``` + +**3. 批量分析中的单个股票分析** (`app.py` 的 `analyze_single_stock_for_batch`) +```python +# 强制使用配置文件中的默认模型(忽略传入的旧值) +config_model = config.DEEPSEEK_MODEL_NAME +if selected_model is None or selected_model == "" or selected_model == "deepseek-chat": + selected_model = config_model +``` + +#### ✅ 生效的地方 + +**1. 主力选股页面** (`main_force_ui.py`) +```python +# 页面内有自己的模型选择 +model = st.selectbox( + "选择AI模型", + list(app_model_options.keys()), + ... +) + +analyzer = MainForceAnalyzer(model=model) # 使用页面选择的值 +``` + +--- + +## 🔧 如何让侧边栏选择全局生效? + +### 方案1:修改代码使用 session_state(推荐) + +修改所有强制使用 `config.DEEPSEEK_MODEL_NAME` 的地方,改为优先使用 `session_state.selected_model`: + +```python +# 修改前 +config_model = config.DEEPSEEK_MODEL_NAME +selected_model = config_model + +# 修改后 +selected_model = st.session_state.get('selected_model', config.DEEPSEEK_MODEL_NAME) +if selected_model not in model_options: + selected_model = config.DEEPSEEK_MODEL_NAME +``` + +**需要修改的文件**: +1. `app.py` - `run_stock_analysis()` 函数 +2. `app.py` - `run_batch_analysis()` 函数 +3. `app.py` - `analyze_single_stock_for_batch()` 函数 + +### 方案2:保持现状,使用配置文件 + +**优点**: +- 配置持久化(重启后仍然有效) +- 不依赖 Streamlit session + +**缺点**: +- 需要修改 `.env` 文件才能改变模型 +- 不能通过UI快速切换 + +--- + +## 📝 模型配置详细说明 + +### model_config.py 结构 + +```python +model_options = { + # 键:模型ID(用于API调用) + # 值:显示名称(在UI中显示) + "deepseek-chat": "DeepSeek Chat (默认)", + "deepseek-reasoner": "DeepSeek Reasoner (推理增强)", + # ... +} +``` + +### 添加新模型的步骤 + +1. **确定模型ID**:从API文档获取模型标识符 +2. **添加到 model_config.py**: + ```python + model_options = { + # ... 现有模型 + "new-model-id": "新模型显示名称", + } + ``` +3. **(可选)设置为默认**:在 `.env` 文件中设置 + ```bash + DEEPSEEK_MODEL_NAME=new-model-id + ``` + +### 当前可用的模型 + +根据 `model_config.py`,当前支持以下模型: + +| 模型ID | 显示名称 | 说明 | +|--------|----------|------| +| `deepseek-chat` | DeepSeek Chat (默认) | 默认模型 | +| `deepseek-reasoner` | DeepSeek Reasoner (推理增强) | 推理能力更强 | +| `qwen-plus` | qwen-plus (阿里百炼) | 阿里云模型 | +| `qwen-plus-latest` | qwen-plus-latest (阿里百炼) | 最新版本 | +| `qwen-flash` | qwen-flash (阿里百炼) | 快速版本 | +| `qwen-turbo` | qwen-turbo (阿里百炼) | 加速版本 | +| `qwen3-max` | qwen-max (阿里百炼) | 最大版本 | +| `qwen-long` | qwen-long (阿里百炼) | 长文本版本 | +| `deepseek-ai/DeepSeek-R1-0528-Qwen3-8B` | DeepSeek-R1 免费(硅基流动) | 免费模型 | +| `Qwen/Qwen2.5-7B-Instruct` | Qwen 免费(硅基流动) | 免费模型 | +| `Pro/deepseek-ai/DeepSeek-V3.1-Terminus` | DeepSeek-V3.1-Terminus (硅基流动) | 专业版 | +| `deepseek-ai/DeepSeek-R1` | DeepSeek-R1 (硅基流动) | R1版本 | +| `Qwen/Qwen3-235B-A22B-Thinking-2507` | Qwen3-235B (硅基流动) | 大模型 | +| `zai-org/GLM-4.6` | 智谱(硅基流动) | 智谱模型 | +| `moonshotai/Kimi-K2-Instruct-0905` | Kimi (硅基流动) | Kimi模型 | +| `Ring-1T` | 蚂蚁百灵 (硅基流动) | 蚂蚁模型 | +| `step3` | 阶跃星辰(硅基流动) | 阶跃模型 | + +--- + +## 🎯 建议 + +### 短期方案(保持现状) + +1. **修改默认模型**:编辑 `.env` 文件,修改 `DEEPSEEK_MODEL_NAME` +2. **主力选股页面**:使用页面内的模型选择(已生效) + +### 长期方案(推荐) + +修改代码,让侧边栏的模型选择真正全局生效: + +1. 修改 `app.py` 中所有使用模型的地方 +2. 优先使用 `st.session_state.selected_model` +3. 如果不存在或无效,回退到 `config.DEEPSEEK_MODEL_NAME` + +这样可以: +- ✅ 通过UI快速切换模型 +- ✅ 配置持久化(通过 `.env`) +- ✅ 用户体验更好 + +--- + +## 📚 相关文件 + +- **模型选项定义**:`model_config.py` +- **默认模型配置**:`.env` 文件中的 `DEEPSEEK_MODEL_NAME` +- **模型选择器**:`app.py` 的 `model_selector()` 函数 +- **配置文件加载**:`config.py` diff --git a/app.py b/app.py index 24dd612..609fec7 100644 --- a/app.py +++ b/app.py @@ -60,6 +60,30 @@ def model_selector(): return selected_model + +def get_selected_model(): + """ + 获取当前选择的AI模型 + 优先使用session_state中的选择,如果不存在或无效,则使用配置文件中的默认值 + + Returns: + str: 模型ID + """ + # 优先使用session_state中的选择 + selected_model = st.session_state.get('selected_model') + + # 如果session_state中有值且在有效选项中,使用它 + if selected_model and selected_model in model_options: + return selected_model + + # 否则使用配置文件中的默认值 + default_model = config.DEEPSEEK_MODEL_NAME + if default_model in model_options: + return default_model + + # 如果配置文件的值也不在选项中,使用第一个选项 + return list(model_options.keys())[0] + # 自定义CSS样式 - 专业版 st.markdown("""