| | 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 |
| | from transformers import pipeline |
| | import soundfile as sf |
| | from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan |
| | import torch |
| | from datasets import load_dataset |
| | |
| |
|
| | |
| | |
| | |
| | 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) |
| |
|
| | |
| | |
| | |
| | llm = Llama( |
| | model_path=model_path, |
| | n_ctx=4096, |
| | n_threads=6, |
| | n_batch=512, |
| | verbose=False |
| | ) |
| |
|
| | |
| | |
| | |
| | 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") |
| |
|
| | |
| | |
| | |
| | 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." |
| | ) |
| |
|
| | |
| | |
| | |
| | _META_PATTERNS = [ |
| | r"(?i)\bnote:\b.*", |
| | r"(?i)\bi am (selin|bullish|bearish).*$", |
| | 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) |
| | |
| | cleaned = re.sub(r"\n{3,}", "\n\n", cleaned).strip() |
| | return cleaned |
| |
|
| | |
| | |
| | |
| | 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. |
| | """ |
| | |
| | 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) |
| |
|
| | |
| | |
| | |
| | def fintalk_discussion(news_text: str) -> Dict[str, str]: |
| | print("🧩 FinTalk simulation started...\n") |
| |
|
| | |
| | messages = [] |
| |
|
| | |
| | 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") |
| |
|
| | |
| | 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") |
| |
|
| | |
| | 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") |
| |
|
| | |
| | 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") |
| |
|
| | |
| | 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: |
| | processor = SpeechT5Processor.from_pretrained("facebook/speecht5_tts") |
| | model = SpeechT5ForTextToSpeech.from_pretrained("facebook/speecht5_tts") |
| | vocoder = SpeechT5HifiGan.from_pretrained("facebook/speecht5_hifigan") |
| | embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation") |
| | print("🎙️ Offline TTS modeli yüklendi (SpeechT5 + HiFiGAN)") |
| | except Exception as e: |
| | print("⚠️ Model yüklenemedi:", e) |
| | return |
| |
|
| | device = "cuda" if torch.cuda.is_available() else "cpu" |
| | model.to(device) |
| | vocoder.to(device) |
| |
|
| | |
| | speaker_embedding = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0).to(device) |
| |
|
| | 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...") |
| | inputs = processor(text=text, return_tensors="pt").to(device) |
| | speech = model.generate_speech(inputs["input_ids"], speaker_embedding, vocoder=vocoder) |
| | filename = f"{key}.wav" |
| | sf.write(filename, speech.cpu().numpy(), samplerate=16000) |
| | print(f"✅ {filename} oluşturuldu (SpeechT5 offline)") |
| | except Exception as e: |
| | print(f"TTS hatası ({key}):", e) |