mirror of
https://github.com/laoxong/nofx.git
synced 2026-06-04 09:58:22 +08:00
fix: save raw AI response for debugging and require calculated numbers
- Add RawResponse field to FullDecision and DecisionRecord - Save raw AI response to database for debugging parse failures - Add IMPORTANT note in prompt: all numeric values must be calculated numbers, not formulas
This commit is contained in:
+5
-4
@@ -137,6 +137,7 @@ type FullDecision struct {
|
||||
UserPrompt string `json:"user_prompt"` // Input prompt sent to AI
|
||||
CoTTrace string `json:"cot_trace"` // Chain of thought analysis (AI output)
|
||||
Decisions []Decision `json:"decisions"` // Specific decision list
|
||||
RawResponse string `json:"raw_response"` // Raw AI response (for debugging when parsing fails)
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
// AIRequestDurationMs records AI API call duration (milliseconds) for troubleshooting latency issues
|
||||
AIRequestDurationMs int64 `json:"ai_request_duration_ms,omitempty"`
|
||||
@@ -212,6 +213,7 @@ func GetFullDecisionWithStrategy(ctx *Context, mcpClient mcp.AIClient, engine *S
|
||||
decision.SystemPrompt = systemPrompt
|
||||
decision.UserPrompt = userPrompt
|
||||
decision.AIRequestDurationMs = aiCallDuration.Milliseconds()
|
||||
decision.RawResponse = aiResponse // Save raw response for debugging
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -350,15 +352,13 @@ func GetFullDecisionWithCustomPrompt(ctx *Context, mcpClient mcp.AIClient, custo
|
||||
decision.SystemPrompt = systemPrompt // Save system prompt
|
||||
decision.UserPrompt = userPrompt // Save input prompt
|
||||
decision.AIRequestDurationMs = aiCallDuration.Milliseconds()
|
||||
decision.RawResponse = aiResponse // Save raw response for debugging
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return decision, fmt.Errorf("failed to parse AI response: %w", err)
|
||||
}
|
||||
|
||||
decision.Timestamp = time.Now()
|
||||
decision.SystemPrompt = systemPrompt // Save system prompt
|
||||
decision.UserPrompt = userPrompt // Save input prompt
|
||||
return decision, nil
|
||||
}
|
||||
|
||||
@@ -581,7 +581,8 @@ func buildSystemPrompt(accountEquity float64, btcEthLeverage, altcoinLeverage in
|
||||
sb.WriteString("## Field Descriptions\n\n")
|
||||
sb.WriteString("- `action`: open_long | open_short | close_long | close_short | hold | wait\n")
|
||||
sb.WriteString("- `confidence`: 0-100 (opening recommended ≥75)\n")
|
||||
sb.WriteString("- Required for opening: leverage, position_size_usd, stop_loss, take_profit, confidence, risk_usd\n\n")
|
||||
sb.WriteString("- Required for opening: leverage, position_size_usd, stop_loss, take_profit, confidence, risk_usd\n")
|
||||
sb.WriteString("- **IMPORTANT**: All numeric values must be calculated numbers, NOT formulas/expressions (e.g., use `27.76` not `3000 * 0.01`)\n\n")
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
@@ -839,7 +839,8 @@ func (e *StrategyEngine) BuildSystemPrompt(accountEquity float64, variant string
|
||||
sb.WriteString("## Field Description\n\n")
|
||||
sb.WriteString("- `action`: open_long | open_short | close_long | close_short | hold | wait\n")
|
||||
sb.WriteString(fmt.Sprintf("- `confidence`: 0-100 (opening recommended ≥ %d)\n", riskControl.MinConfidence))
|
||||
sb.WriteString("- Required when opening: leverage, position_size_usd, stop_loss, take_profit, confidence, risk_usd\n\n")
|
||||
sb.WriteString("- Required when opening: leverage, position_size_usd, stop_loss, take_profit, confidence, risk_usd\n")
|
||||
sb.WriteString("- **IMPORTANT**: All numeric values must be calculated numbers, NOT formulas/expressions (e.g., use `27.76` not `3000 * 0.01`)\n\n")
|
||||
|
||||
// 8. Custom Prompt
|
||||
if e.config.CustomPrompt != "" {
|
||||
|
||||
+8
-3
@@ -22,6 +22,7 @@ type DecisionRecord struct {
|
||||
InputPrompt string `json:"input_prompt"`
|
||||
CoTTrace string `json:"cot_trace"`
|
||||
DecisionJSON string `json:"decision_json"`
|
||||
RawResponse string `json:"raw_response"` // Raw AI response for debugging
|
||||
CandidateCoins []string `json:"candidate_coins"`
|
||||
ExecutionLog []string `json:"execution_log"`
|
||||
Success bool `json:"success"`
|
||||
@@ -90,6 +91,7 @@ func (s *DecisionStore) initTables() error {
|
||||
input_prompt TEXT DEFAULT '',
|
||||
cot_trace TEXT DEFAULT '',
|
||||
decision_json TEXT DEFAULT '',
|
||||
raw_response TEXT DEFAULT '',
|
||||
candidate_coins TEXT DEFAULT '',
|
||||
execution_log TEXT DEFAULT '',
|
||||
success BOOLEAN DEFAULT 0,
|
||||
@@ -108,6 +110,9 @@ func (s *DecisionStore) initTables() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Migration: add raw_response column if not exists
|
||||
s.db.Exec(`ALTER TABLE decision_records ADD COLUMN raw_response TEXT DEFAULT ''`)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -127,13 +132,13 @@ func (s *DecisionStore) LogDecision(record *DecisionRecord) error {
|
||||
result, err := s.db.Exec(`
|
||||
INSERT INTO decision_records (
|
||||
trader_id, cycle_number, timestamp, system_prompt, input_prompt,
|
||||
cot_trace, decision_json, candidate_coins, execution_log,
|
||||
cot_trace, decision_json, raw_response, candidate_coins, execution_log,
|
||||
success, error_message, ai_request_duration_ms
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`,
|
||||
record.TraderID, record.CycleNumber, record.Timestamp.Format(time.RFC3339),
|
||||
record.SystemPrompt, record.InputPrompt, record.CoTTrace, record.DecisionJSON,
|
||||
string(candidateCoinsJSON), string(executionLogJSON),
|
||||
record.RawResponse, string(candidateCoinsJSON), string(executionLogJSON),
|
||||
record.Success, record.ErrorMessage, record.AIRequestDurationMs,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -402,6 +402,7 @@ func (at *AutoTrader) runCycle() error {
|
||||
record.SystemPrompt = aiDecision.SystemPrompt // Save system prompt
|
||||
record.InputPrompt = aiDecision.UserPrompt
|
||||
record.CoTTrace = aiDecision.CoTTrace
|
||||
record.RawResponse = aiDecision.RawResponse // Save raw AI response for debugging
|
||||
if len(aiDecision.Decisions) > 0 {
|
||||
decisionJSON, _ := json.MarshalIndent(aiDecision.Decisions, "", " ")
|
||||
record.DecisionJSON = string(decisionJSON)
|
||||
|
||||
Reference in New Issue
Block a user