import time import json from typing import Dict, List, Optional, Any from tenacity import retry, stop_after_attempt, wait_exponential import logging from openai import OpenAI from .config import config logger = logging.getLogger(__name__) class DeepSeekClient: """DeepSeek API kliendi klass""" def __init__(self): self.client = OpenAI( api_key=config.deepseek_api_key, base_url=config.deepseek_base_url ) self.logger = logging.getLogger(__name__) self.max_tokens = config.max_tokens @retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10) ) def call_api(self, messages: List[Dict], temperature: float = 0.7) -> str: """Kutsu DeepSeek API-d""" try: response = self.client.chat.completions.create( model=config.deepseek_model, messages=messages, max_tokens=self.max_tokens, temperature=temperature ) content = response.choices[0].message.content tokens_used = response.usage.total_tokens if hasattr(response, 'usage') else 0 self.logger.info(f"API kutsutud, tokenid: {tokens_used}") return content except Exception as e: self.logger.error(f"API viga: {str(e)}") raise def create_summary(self, text: str, context: Dict) -> Dict: """Loo põhjalik kokkuvõte artikkelist""" self.logger.info("Loon artikli kokkuvõtte DeepSeek-iga...") # Koosta süsteemipromt system_prompt = f"""Sa oled transpordiplaneerimise spetsialist ja teadusartiklite analüütik. Loo põhjalik kokkuvõte antud teadusartiklist EESTI KEELES. Kokkuvõte peaks sisaldama järgmisi osi: 1. ARTIKLI PEAMISED PUNKTID: - Uurimisküsimused ja eesmärgid - Teaduslik tähtsus - Uudne panus valdkonda 2. KASUTATUD MEETODID: - Andmete kogumise meetodid - Analüüsimeetodid - Mudelid ja algoritmid 3. PEAMISED TULEMUSED: - Olulisemad leidud - Statistilised tulemused - Mudeli täpsus ja piirangud 4. JÄRELDUSED JA SOOVITUSED: - Peamised järeldused - Rakendussoovitused - Edasised uurimissuunad 5. TRANSFORDIPLANEERIMISE KONTEKST: - Kuidas aitab see artikkel paremat transpordisüsteemi kujundada? - Millised on praktilised rakendused? - Mida võiks Eesti tingimustes rakendada? Kasuta selget ja asjakohast keelt. Olge konkreetne ja viida konkreetsetele leidudele. """ # Koosta kasutaja promt user_prompt = f"""Loo põhjalik kokkuvõte järgmisest teadusartiklist: ARTIKLI INFO: Pealkiri: {context.get('title', 'Teadmata')} Autorid: {', '.join(context.get('authors', []))} Aasta: {context.get('year', 'Teadmata')} Žurnaal: {context.get('journal', 'Teadmata')} ARTIKLI SISU (esimesed 6000 märki): {text[:6000]} Palun loo struktureeritud kokkuvõte ülaltoodud nõuete järgi. """ messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ] summary = self.call_api(messages, temperature=0.7) return { "summary_et": summary, "summary_length": len(summary), "language": "et" } def extract_key_concepts(self, text: str, summary: str) -> List[str]: """Eralda artikli olulisemad mõisted ja võtmesõnad""" self.logger.info("Eraldan võtmesõnu...") system_prompt = """Sa oled teadusartiklite analüütik. Eralda antud artiklist 5-10 olulisemat mõistet/võtmesõna, mis iseloomustavad artikli põhisisu. Tagasta need komadega eraldatud nimekirjana. """ user_prompt = f"""Artikli kokkuvõte: {summary[:1000]} Artikli tekst (osa): {text[:2000]} Palun eralda olulisemad mõisted. Tagasta VAID komadega eraldatud nimekiri. """ messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ] response = self.call_api(messages, temperature=0.3) # Puhasta vastus concepts = [c.strip() for c in response.split(',') if c.strip()] concepts = concepts[:10] # Piirangu 10 mõistele return concepts def identify_methods(self, text: str) -> List[str]: """Tuvasta artiklis kasutatud meetodid""" self.logger.info("Tuvastan kasutatud meetodeid...") system_prompt = """Sa oled teadusmeetodite spetsialist. Tuvasta antud teadusartiklist kasutatud peamised meetodid (nt: regressioonanalüüs, simulatsioon, juhtumianalüüs jne). Tagasta komadega eraldatud nimekiri. """ user_prompt = f"""Artikli tekst (osa): {text[:3000]} Palun tuvasta kasutatud meetodid. Tagasta VAID komadega eraldatud nimekiri. """ messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ] response = self.call_api(messages, temperature=0.3) methods = [m.strip() for m in response.split(',') if m.strip()] return methods def analyze_transport_context(self, summary: str) -> Dict: """Analüüsi artikli tähtsus transpordiplaneerimise kontekstis""" self.logger.info("Analüüsin transpordi konteksti...") system_prompt = """Sa oled transpordiplaneerimise ekspert. Analüüsi antud teadusartikli tähtsust ja rakendatavust transpordisüsteemide planeerimisel. Hinda järgmisi aspekte: 1. Teoreetiline panus 2. Praktiline rakendatavus 3. Reaalsete probleemide lahendamine 4. Piirangud ja edasised vajadused """ user_prompt = f"""Artikli kokkuvõte: {summary} Palun analüüsi artikli tähtsust transpordiplaneerimise kontekstis. Tagasta JSON formaadis: {{ "theoretical_contribution": "lühikirjeldus", "practical_applicability": "lühikirjeldus", "problem_solving": "lühikirjeldus", "limitations": "lühikirjeldus", "relevance_score": 1-10 (kus 10 on kõige relevantsem) }} """ messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ] response = self.call_api(messages, temperature=0.5) try: # Proovi parsida JSON vastust if response.startswith('{') and response.endswith('}'): return json.loads(response) except: pass # Kui JSON parsimine ei õnnestu, tagasta struktureeritud tekst return { "analysis": response, "relevance_score": 5 # Vaikimisi skoor }