FinTalk / backend.py
Fetii's picture
Update backend.py
4ef1c50 verified
raw
history blame
8.06 kB
import os
import re
from typing import Dict
from llama_cpp import Llama
from openai import OpenAI
import edge_tts
import asyncio
import reportlab
from huggingface_hub import hf_hub_download
# -----------------------------------------------------
# 1) MODEL YOLU (GGUF)
# -----------------------------------------------------
MODEL_REPO = "QuantFactory/Llama-3-8B-Instruct-Finance-RAG-GGUF"
MODEL_FILE = "Llama-3-8B-Instruct-Finance-RAG.Q4_K_S.gguf"
model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
# -----------------------------------------------------
# 2) LLAMA-CPP MODEL YÜKLEME
# -----------------------------------------------------
llm = Llama(
model_path=model_path,
n_ctx=4096,
n_threads=6,
n_batch=512,
verbose=False
)
# -----------------------------------------------------
# 3) OPENAI (Özetleme)
# -----------------------------------------------------
OPENAI_API_KEY = os.getenv("API_KEY")
if not OPENAI_API_KEY:
raise RuntimeError("API_KEY bulunamadı. Lütfen .env veya sistem değişkenlerine ekleyin.")
client = OpenAI(api_key=OPENAI_API_KEY)
SUMMARY_MODEL = os.getenv("SUMMARY_MODEL", "gpt-4o-mini")
# -----------------------------------------------------
# 4) PERSONA PROMPTLAR (sade)
# -----------------------------------------------------
SYSTEM_MODERATOR = (
"You are Selin, the moderator of an economics roundtable. "
"Be neutral, brief, and structured. Guide the flow without giving opinions."
)
SYSTEM_BULLISH = (
"""You are Bullish Investor, an optimistic economist who focuses on growth, market confidence, and positive catalysts.
Be analytical and persuasive. Mention at least two concrete macro or market factors that support your optimism
(e.g., improved investor sentiment, fiscal stimulus, or sector resilience).
Respond in 2–3 detailed paragraphs and conclude with one confident takeaway."""
)
SYSTEM_BEARISH = (
"You are Bearish Economist, a cautious macroeconomist who highlights downside risks "
"(inflation persistence, liquidity stress, policy uncertainty). Be analytical; end with one cautionary insight."
)
# -----------------------------------------------------
# 5) YARDIMCI: Post-process (meta notları, personayı ifşa eden satırları temizle)
# -----------------------------------------------------
_META_PATTERNS = [
r"(?i)\bnote:\b.*", # "Note:" ile başlayan meta
r"(?i)\bi am (selin|bullish|bearish).*$", # "I am ..." persona ifşaları
r"(?i)\bthis response was written\b.*",
r"(?i)\bplease review\b.*",
r"(?i)\bclarity and readability\b.*",
]
def _clean(text: str) -> str:
cleaned = text.strip()
for pat in _META_PATTERNS:
cleaned = re.sub(pat, "", cleaned, flags=re.MULTILINE)
# aşırı boşlukları toparla
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned).strip()
return cleaned
# -----------------------------------------------------
# 6) TEK PERSONA CEVABI (chat completion + context reset)
# -----------------------------------------------------
def generate_as(system_prompt: str, user_text: str, max_tokens: int = 480, temperature: float = 0.7) -> str:
"""
Her çağrıda temiz context: create_chat_completion kullanıyoruz.
"""
# olası KV cache etkisini azaltmak için reset
llm.reset()
out = llm.create_chat_completion(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_text}
],
max_tokens=max_tokens,
temperature=temperature,
top_p=0.9,
repeat_penalty=1.1,
)
text = out["choices"][0]["message"]["content"]
return _clean(text)
# -----------------------------------------------------
# 7) TARTIŞMA AKIŞI
# -----------------------------------------------------
def fintalk_discussion(news_text: str) -> Dict[str, str]:
print("🧩 FinTalk simulation started...\n")
# Ortak mesaj zinciri (tek context)
messages = []
# 1️⃣ Selin başlatıyor
selin_intro = generate_as(SYSTEM_MODERATOR, f"Open the discussion about: {news_text}.")
messages.append(f"Selin: {selin_intro}")
print("Moderator Intro:\n", selin_intro, "\n")
# 2️⃣ Bullish konuşuyor
bullish_view = generate_as(
SYSTEM_BULLISH,
f"The moderator introduced the topic: {news_text}. Respond with your opening bullish perspective."
)
messages.append(f"Bullish Investor: {bullish_view}")
print("Bullish Investor:\n", bullish_view, "\n")
# 3️⃣ Bearish karşılık veriyor
bearish_view = generate_as(
SYSTEM_BEARISH,
f"The moderator introduced the topic: {news_text}. "
f"The bullish economist said: {bullish_view}\n"
"Now respond with your cautious analysis."
)
messages.append(f"Bearish Economist: {bearish_view}")
print("Bearish Economist:\n", bearish_view, "\n")
# 4️⃣ Selin toparlıyor (konuya referans ver)
selin_wrap = generate_as(
SYSTEM_MODERATOR,
f"Based on the debate about {news_text}, summarize their main differences and close the panel politely."
)
messages.append(f"Selin: {selin_wrap}")
print("Moderator Wrap-up:\n", selin_wrap, "\n")
# 5️⃣ GPT özetleme
debate_text = "\n".join(messages)
summary_prompt = (
"Summarize this debate between a bullish and a bearish economist in 5 bullet points. "
"Keep it grounded in the topic and add a balanced conclusion.\n\n"
f"{debate_text}"
)
summary_resp = client.chat.completions.create(
model=SUMMARY_MODEL,
messages=[
{"role": "system", "content": "You are an expert economic summarizer."},
{"role": "user", "content": summary_prompt}
]
)
final_summary = summary_resp.choices[0].message.content.strip()
print("📊 GPT Summary:\n", final_summary)
return {
"moderator_intro": selin_intro,
"bullish_view": bullish_view,
"bearish_view": bearish_view,
"moderator_wrap": selin_wrap,
"summary": final_summary
}
def export_to_pdf(result: dict, filename="FinTalk_Report.pdf"):
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
styles = getSampleStyleSheet()
doc = SimpleDocTemplate(filename, pagesize=A4)
story = []
def add(title, text):
story.append(Paragraph(f"<b>{title}</b>", styles["Heading3"]))
story.append(Paragraph(text.replace("\n", "<br/>"), styles["BodyText"]))
story.append(Spacer(1, 12))
add("Topic", result.get("topic", "—"))
add("Moderator Intro", result["moderator_intro"])
add("Bullish Investor", result["bullish_view"])
add("Bearish Economist", result["bearish_view"])
add("Moderator Wrap-up", result["moderator_wrap"])
add("GPT-4 Summary", result["summary"])
story.append(Paragraph("<i>Generated by FinTalk – AI Economic Roundtable</i>", styles["Normal"]))
doc.build(story)
def generate_tts_files(result):
try:
pipe = pipeline("text-to-speech", model="facebook/fastspeech2-en-ljspeech")
print("🎙️ Offline TTS modeli yüklendi (FastSpeech2)")
except Exception as e:
print("⚠️ TTS modeli yüklenemedi:", e)
return
texts = {
"moderator_intro": result["moderator_intro"],
"bullish_view": result["bullish_view"],
"bearish_view": result["bearish_view"],
"moderator_wrap": result["moderator_wrap"]
}
for key, text in texts.items():
try:
print(f"🔊 {key} ses üretiliyor...")
audio_output = pipe(text)
audio = audio_output["audio"]
filename = f"{key}.wav"
sf.write(filename, audio, samplerate=16000)
print(f"✅ {filename} oluşturuldu (transformers offline)")
time.sleep(1)
except Exception as e:
print(f"TTS hatası ({key}):", e)