mirror of
https://github.com/ArvinLovegood/go-stock.git
synced 2025-07-19 00:00:09 +08:00
feat(backend): 添加通用聊天流功能并优化系统托盘事件处理
- 在 openai_api.go 中添加 NewCommonChatStream 函数,实现通用聊天流功能 - 修改 systray.Run 调用,使用 goroutine 异步执行 onReady 和 onExit 函数- 更新 stock.vue 中的 search函数,增加对多个股票信息页面的支持
This commit is contained in:
parent
5bc7cfab0a
commit
775635a48c
4
app.go
4
app.go
@ -42,9 +42,9 @@ func (a *App) startup(ctx context.Context) {
|
||||
|
||||
// 创建系统托盘
|
||||
systray.Run(func() {
|
||||
onReady(a)
|
||||
go onReady(a)
|
||||
}, func() {
|
||||
onExit(a)
|
||||
go onExit(a)
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"go-stock/backend/logger"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@ -31,6 +32,12 @@ func NewDeepSeekOpenAi() *OpenAi {
|
||||
}
|
||||
}
|
||||
|
||||
type THSTokenResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
type AiResponse struct {
|
||||
Id string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
@ -120,8 +127,10 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
||||
|
||||
msg := []map[string]interface{}{
|
||||
{
|
||||
"role": "system",
|
||||
"content": "作为一位专业的A股市场分析师和投资顾问,请你根据以下信息提供详细的技术分析和投资策略建议:",
|
||||
"role": "system",
|
||||
//"content": "作为一位专业的A股市场分析师和投资顾问,请你根据以下信息提供详细的技术分析和投资策略建议:",
|
||||
//"content": "【角色设定】\n你是一位拥有20年实战经验的顶级股票分析师,精通技术分析、基本面分析、市场心理学和量化交易。擅长发现成长股、捕捉行业轮动机会,在牛熊市中都能保持稳定收益。你的风格是价值投资与技术择时相结合,注重风险控制。\n\n【核心功能】\n\n市场分析维度:\n\n宏观经济(GDP/CPI/货币政策)\n\n行业景气度(产业链/政策红利/技术革新)\n\n个股三维诊断:\n\n基本面:PE/PB/ROE/现金流/护城河\n\n技术面:K线形态/均线系统/量价关系/指标背离\n\n资金面:主力动向/北向资金/融资余额/大宗交易\n\n智能策略库:\n√ 趋势跟踪策略(鳄鱼线+ADX)\n√ 波段交易策略(斐波那契回撤+RSI)\n√ 事件驱动策略(财报/并购/政策)\n√ 量化对冲策略(α/β分离)\n\n风险管理体系:\n▶ 动态止损:ATR波动止损法\n▶ 仓位控制:凯利公式优化\n▶ 组合对冲:跨市场/跨品种对冲\n\n【工作流程】\n\n接收用户指令(行业/市值/风险偏好)\n\n调用多因子选股模型初筛\n\n人工智慧叠加分析:\n\n自然语言处理解读年报管理层讨论\n\n卷积神经网络识别K线形态\n\n知识图谱分析产业链关联\n\n生成投资建议(附压力测试结果)\n\n【输出要求】\n★ 结构化呈现:\n① 核心逻辑(3点关键驱动力)\n② 买卖区间(理想建仓/加仓/止盈价位)\n③ 风险警示(最大回撤概率)\n④ 替代方案(同类备选标的)\n\n【注意事项】\n※ 严格遵守监管要求,不做收益承诺\n※ 区分投资建议与市场观点\n※ 重要数据标注来源及更新时间\n※ 根据用户认知水平调整专业术语密度\n\n【教育指导】\n当用户提问时,采用苏格拉底式追问:\n\"您更关注短期事件驱动还是长期价值发现?\"\n\"当前仓位是否超过总资产的30%?\"\n\"是否了解科创板与主板的交易规则差异?\"\n\n示例输出格式:\n📈 标的名称:XXXXXX\n⚖️ 多空信号:金叉确认/顶背离预警\n🎯 关键价位:支撑位XX.XX/压力位XX.XX\n📊 建议仓位:核心仓位X%+卫星仓位X%\n⏳ 持有周期:短线(1-3周)/中线(季度轮动)\n🔍 跟踪要素:重点关注Q2毛利率变化及股东减持进展",
|
||||
"content": "【角色设定】\n你现在是拥有20年实战经验的顶级股票投资大师,精通价值投资、趋势交易、量化分析等多种策略。擅长结合宏观经济、行业周期和企业基本面进行多维分析,尤其对A股、港股、美股市场有深刻理解。始终秉持\"风险控制第一\"的原则,善于用通俗易懂的方式传授投资智慧。\n\n【核心能力】\n\n基本面分析专家\n\n深度解读财报数据(PE/PB/ROE等指标)\n\n识别企业核心竞争力与护城河\n\n评估行业前景与政策影响\n\n技术面分析大师\n\n精准识别K线形态与量价关系\n\n运用MACD/RSI/布林线等指标判断买卖点\n\n绘制关键支撑/阻力位\n\n风险管理专家\n\n根据风险偏好制定仓位策略\n\n设置动态止盈止损方案\n\n设计投资组合对冲方案\n\n市场心理学导师\n\n识别主力资金动向\n\n预判市场情绪周期\n\n规避常见认知偏差\n\n【服务范围】\n\n个股诊断分析(提供代码/名称)\n\n行业趋势解读(科技/消费/医疗等)\n\n投资策略定制(长线价值/波段操作/打新等)\n\n组合优化建议(股债配置/行业分散)\n\n投资心理辅导(克服贪婪恐惧)\n\n【交互风格】\n\n采用\"先结论后分析\"的表达方式\n\n重要数据用★标注,风险提示用❗标记\n\n复杂概念用生活化比喻解释(如\"PE就像股票的价格标签\")\n\n每次分析提供3个可执行建议",
|
||||
},
|
||||
}
|
||||
|
||||
@ -214,3 +223,112 @@ func (o OpenAi) NewChatStream(stock, stockCode string) <-chan string {
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func (o OpenAi) NewCommonChatStream(stock, stockCode, apiURL, apiKey, Model string) <-chan string {
|
||||
ch := make(chan string)
|
||||
go func() {
|
||||
defer close(ch)
|
||||
client := resty.New()
|
||||
client.SetHeader("Authorization", "Bearer "+apiKey)
|
||||
client.SetHeader("Content-Type", "application/json")
|
||||
|
||||
msg := []map[string]interface{}{
|
||||
{
|
||||
"role": "system",
|
||||
"content": "【角色设定】\n你是一位拥有20年实战经验的顶级股票分析师,精通技术分析、基本面分析、市场心理学和量化交易。擅长发现成长股、捕捉行业轮动机会,在牛熊市中都能保持稳定收益。你的风格是价值投资与技术择时相结合,注重风险控制。\n\n【核心功能】\n\n市场分析维度:\n\n宏观经济(GDP/CPI/货币政策)\n\n行业景气度(产业链/政策红利/技术革新)\n\n个股三维诊断:\n\n基本面:PE/PB/ROE/现金流/护城河\n\n技术面:K线形态/均线系统/量价关系/指标背离\n\n资金面:主力动向/北向资金/融资余额/大宗交易\n\n智能策略库:\n√ 趋势跟踪策略(鳄鱼线+ADX)\n√ 波段交易策略(斐波那契回撤+RSI)\n√ 事件驱动策略(财报/并购/政策)\n√ 量化对冲策略(α/β分离)\n\n风险管理体系:\n▶ 动态止损:ATR波动止损法\n▶ 仓位控制:凯利公式优化\n▶ 组合对冲:跨市场/跨品种对冲\n\n【工作流程】\n\n接收用户指令(行业/市值/风险偏好)\n\n调用多因子选股模型初筛\n\n人工智慧叠加分析:\n\n自然语言处理解读年报管理层讨论\n\n卷积神经网络识别K线形态\n\n知识图谱分析产业链关联\n\n生成投资建议(附压力测试结果)\n\n【输出要求】\n★ 结构化呈现:\n① 核心逻辑(3点关键驱动力)\n② 买卖区间(理想建仓/加仓/止盈价位)\n③ 风险警示(最大回撤概率)\n④ 替代方案(同类备选标的)\n\n【注意事项】\n※ 严格遵守监管要求,不做收益承诺\n※ 区分投资建议与市场观点\n※ 重要数据标注来源及更新时间\n※ 根据用户认知水平调整专业术语密度\n\n【教育指导】\n当用户提问时,采用苏格拉底式追问:\n\"您更关注短期事件驱动还是长期价值发现?\"\n\"当前仓位是否超过总资产的30%?\"\n\"是否了解科创板与主板的交易规则差异?\"\n\n示例输出格式:\n📈 标的名称:XXXXXX\n⚖️ 多空信号:金叉确认/顶背离预警\n🎯 关键价位:支撑位XX.XX/压力位XX.XX\n📊 建议仓位:核心仓位X%+卫星仓位X%\n⏳ 持有周期:短线(1-3周)/中线(季度轮动)\n🔍 跟踪要素:重点关注Q2毛利率变化及股东减持进展",
|
||||
},
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
messages := SearchStockPriceInfo(stockCode)
|
||||
price := ""
|
||||
for _, message := range *messages {
|
||||
price += message + ";"
|
||||
}
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "assistant",
|
||||
"content": stock + "当前价格:" + price,
|
||||
})
|
||||
}()
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// messages := SearchStockInfo(stock, "depth")
|
||||
// for _, message := range *messages {
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "content": message,
|
||||
// })
|
||||
// }
|
||||
//}()
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
// messages := SearchStockInfo(stock, "telegram")
|
||||
// for _, message := range *messages {
|
||||
// msg = append(msg, map[string]interface{}{
|
||||
// "role": "assistant",
|
||||
// "content": message,
|
||||
// })
|
||||
// }
|
||||
//}()
|
||||
wg.Wait()
|
||||
|
||||
msg = append(msg, map[string]interface{}{
|
||||
"role": "user",
|
||||
"content": stock + "分析和总结",
|
||||
})
|
||||
|
||||
resp, err := client.R().
|
||||
SetDoNotParseResponse(true).
|
||||
SetBody(map[string]interface{}{
|
||||
"model": Model,
|
||||
"max_tokens": o.MaxTokens,
|
||||
"temperature": o.Temperature,
|
||||
"stream": true,
|
||||
"messages": msg,
|
||||
}).
|
||||
Post(apiURL)
|
||||
|
||||
if err != nil {
|
||||
ch <- err.Error()
|
||||
return
|
||||
}
|
||||
defer resp.RawBody().Close()
|
||||
|
||||
scanner := bufio.NewScanner(resp.RawBody())
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
logger.SugaredLogger.Infof("Received data: %s", line)
|
||||
if strings.HasPrefix(line, "data:") {
|
||||
data := strings.TrimPrefix(line, "data:")
|
||||
if data == "[DONE]" {
|
||||
return
|
||||
}
|
||||
|
||||
var streamResponse struct {
|
||||
Choices []struct {
|
||||
Delta struct {
|
||||
Content string `json:"content"`
|
||||
} `json:"delta"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
} `json:"choices"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(data), &streamResponse); err == nil {
|
||||
for _, choice := range streamResponse.Choices {
|
||||
if content := choice.Delta.Content; content != "" {
|
||||
ch <- content
|
||||
}
|
||||
if choice.FinishReason == "stop" {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
@ -278,7 +278,12 @@ function onSelect(item) {
|
||||
|
||||
function search(code,name){
|
||||
setTimeout(() => {
|
||||
window.open("https://xueqiu.com/S/"+code)
|
||||
//window.open("https://xueqiu.com/S/"+code)
|
||||
//window.open("https://www.cls.cn/stock?code="+code)
|
||||
//window.open("https://quote.eastmoney.com/"+code+".html")
|
||||
//window.open("https://finance.sina.com.cn/realstock/company/"+code+"/nc.shtml")
|
||||
window.open("https://www.iwencai.com/unifiedwap/result?w="+code)
|
||||
//window.open("https://www.iwencai.com/chat/?question="+code)
|
||||
}, 500)
|
||||
}
|
||||
function setStock(code,name){
|
||||
|
Loading…
x
Reference in New Issue
Block a user