Spaces:
Running
Running
File size: 4,398 Bytes
faf123b b44478d faf123b b44478d faf123b b44478d 16c61ea cfea2d4 b44478d 70e1667 b44478d ea7a6ee faf123b 5a2f067 faf123b 5a2f067 faf123b d9d2959 b44478d faf123b b44478d d9d2959 faf123b d9d2959 faf123b b44478d faf123b 16c61ea faf123b ea7a6ee faf123b b44478d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | from google import genai
from google.genai import types
import traceback
from ..config import db, get_user_keys
class AiModalEngine:
@staticmethod
def _get_client(api_key):
return genai.Client(api_key=api_key)
@staticmethod
def initialize_firebase_session(uid, context):
try:
keys = get_user_keys(uid)
api_key = keys.get('gemini_key')
if not api_key:
return "Error: No API Key found in Settings."
client = AiModalEngine._get_client(api_key)
# Parsona
instruction = f"""
PERSONA:
You are the QuantVAT AI Trading Journal Auditor, a senior Risk Manager and Trading Psychologist with 50 years trading experience like a Market Wizard.
Speak with veteran authority. Tone is blunt but constructive.
MANDATE:
1. Analyze the 'WHY' behind execution based on the provided logs.
2. STRUCTURE:
- ## ๐ OVERVIEW: 2-sentence performance reality check.
- ## ๐ฉ RED FLAGS: Top 2 execution errors (FOMO, sizing, fear, etc).
- ## ๐ก THE REMEDY: One specific, actionable rule for the next session.
3. FORMAT: Use bold text for emphasis.
4. NO TABLES: Use bullet points only.
5. INTERACTION: End with a provocative question about a specific trade.
TRADING LEDGER (CSV FORMAT):
{context}
"""
prompt = "Analyze my execution performance based on the CSV data above. End with: 'I have analyzed your data. Ready for audit.'"
response = client.models.generate_content(
model='gemini-3-flash-preview',
contents=prompt,
config=types.GenerateContentConfig(
system_instruction=instruction
)
)
history = [
{"role": "user", "parts": [{"text": prompt}]},
{"role": "model", "parts": [{"text": response.text}]}
]
db.collection('users').document(uid).set({
"ai_history": history,
"ai_context": context
}, merge=True)
return response.text
except Exception as e:
print(f"AI Init Error: {traceback.format_exc()}")
return f"System Error: {str(e)}"
@staticmethod
def continue_firebase_chat(uid, prompt):
try:
user_doc = db.collection('users').document(uid).get()
data = user_doc.to_dict() if user_doc.exists else {}
history = data.get("ai_history", [])
context = data.get("ai_context", "")
api_key = get_user_keys(uid).get('gemini_key')
if not api_key:
return "Error: API Key missing."
client = AiModalEngine._get_client(api_key)
# Robust mapping
contents = []
for h in history:
p = h['parts'][0]
text_content = p['text'] if isinstance(p, dict) else str(p)
contents.append(types.Content(
role=h['role'],
parts=[types.Part.from_text(text=text_content)]
))
contents.append(types.Content(role="user", parts=[types.Part.from_text(text=prompt)]))
# Re-injects Persona
instruction = f"PERSONA: QuantVAT AI Trading Journal Auditor. Senior Risk Manager.\nDATA:\n{context}"
response = client.models.generate_content(
model='gemini-3-flash-preview',
contents=contents,
config=types.GenerateContentConfig(
system_instruction=instruction
)
)
# Append new turn and sync to Firestore
history.append({"role": "user", "parts": [{"text": prompt}]})
history.append({"role": "model", "parts": [{"text": response.text}]})
db.collection('users').document(uid).set({"ai_history": history}, merge=True)
return response.text
except Exception as e:
print(f"AI Chat Error: {traceback.format_exc()}")
return f"Auditor Error: {str(e)}" |