deepseek_client.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import time
  2. import json
  3. from typing import Dict, List, Optional, Any
  4. from tenacity import retry, stop_after_attempt, wait_exponential
  5. import logging
  6. from openai import OpenAI
  7. from .config import config
  8. logger = logging.getLogger(__name__)
  9. class DeepSeekClient:
  10. """DeepSeek API kliendi klass"""
  11. def __init__(self):
  12. self.client = OpenAI(
  13. api_key=config.deepseek_api_key,
  14. base_url=config.deepseek_base_url
  15. )
  16. self.logger = logging.getLogger(__name__)
  17. self.max_tokens = config.max_tokens
  18. @retry(
  19. stop=stop_after_attempt(3),
  20. wait=wait_exponential(multiplier=1, min=4, max=10)
  21. )
  22. def call_api(self, messages: List[Dict], temperature: float = 0.7) -> str:
  23. """Kutsu DeepSeek API-d"""
  24. try:
  25. response = self.client.chat.completions.create(
  26. model=config.deepseek_model,
  27. messages=messages,
  28. max_tokens=self.max_tokens,
  29. temperature=temperature
  30. )
  31. content = response.choices[0].message.content
  32. tokens_used = response.usage.total_tokens if hasattr(response, 'usage') else 0
  33. self.logger.info(f"API kutsutud, tokenid: {tokens_used}")
  34. return content
  35. except Exception as e:
  36. self.logger.error(f"API viga: {str(e)}")
  37. raise
  38. def create_summary(self, text: str, context: Dict) -> Dict:
  39. """Loo põhjalik kokkuvõte artikkelist"""
  40. self.logger.info("Loon artikli kokkuvõtte DeepSeek-iga...")
  41. # Koosta süsteemipromt
  42. system_prompt = f"""Sa oled transpordiplaneerimise spetsialist ja teadusartiklite analüütik.
  43. Loo põhjalik kokkuvõte antud teadusartiklist EESTI KEELES.
  44. Kokkuvõte peaks sisaldama järgmisi osi:
  45. 1. ARTIKLI PEAMISED PUNKTID:
  46. - Uurimisküsimused ja eesmärgid
  47. - Teaduslik tähtsus
  48. - Uudne panus valdkonda
  49. 2. KASUTATUD MEETODID:
  50. - Andmete kogumise meetodid
  51. - Analüüsimeetodid
  52. - Mudelid ja algoritmid
  53. 3. PEAMISED TULEMUSED:
  54. - Olulisemad leidud
  55. - Statistilised tulemused
  56. - Mudeli täpsus ja piirangud
  57. 4. JÄRELDUSED JA SOOVITUSED:
  58. - Peamised järeldused
  59. - Rakendussoovitused
  60. - Edasised uurimissuunad
  61. 5. TRANSFORDIPLANEERIMISE KONTEKST:
  62. - Kuidas aitab see artikkel paremat transpordisüsteemi kujundada?
  63. - Millised on praktilised rakendused?
  64. - Mida võiks Eesti tingimustes rakendada?
  65. Kasuta selget ja asjakohast keelt. Olge konkreetne ja viida konkreetsetele leidudele.
  66. """
  67. # Koosta kasutaja promt
  68. user_prompt = f"""Loo põhjalik kokkuvõte järgmisest teadusartiklist:
  69. ARTIKLI INFO:
  70. Pealkiri: {context.get('title', 'Teadmata')}
  71. Autorid: {', '.join(context.get('authors', []))}
  72. Aasta: {context.get('year', 'Teadmata')}
  73. Žurnaal: {context.get('journal', 'Teadmata')}
  74. ARTIKLI SISU (esimesed 6000 märki):
  75. {text[:6000]}
  76. Palun loo struktureeritud kokkuvõte ülaltoodud nõuete järgi.
  77. """
  78. messages = [
  79. {"role": "system", "content": system_prompt},
  80. {"role": "user", "content": user_prompt}
  81. ]
  82. summary = self.call_api(messages, temperature=0.7)
  83. return {
  84. "summary_et": summary,
  85. "summary_length": len(summary),
  86. "language": "et"
  87. }
  88. def extract_key_concepts(self, text: str, summary: str) -> List[str]:
  89. """Eralda artikli olulisemad mõisted ja võtmesõnad"""
  90. self.logger.info("Eraldan võtmesõnu...")
  91. system_prompt = """Sa oled teadusartiklite analüütik. Eralda antud artiklist 5-10 olulisemat
  92. mõistet/võtmesõna, mis iseloomustavad artikli põhisisu. Tagasta need komadega eraldatud nimekirjana.
  93. """
  94. user_prompt = f"""Artikli kokkuvõte:
  95. {summary[:1000]}
  96. Artikli tekst (osa):
  97. {text[:2000]}
  98. Palun eralda olulisemad mõisted. Tagasta VAID komadega eraldatud nimekiri.
  99. """
  100. messages = [
  101. {"role": "system", "content": system_prompt},
  102. {"role": "user", "content": user_prompt}
  103. ]
  104. response = self.call_api(messages, temperature=0.3)
  105. # Puhasta vastus
  106. concepts = [c.strip() for c in response.split(',') if c.strip()]
  107. concepts = concepts[:10] # Piirangu 10 mõistele
  108. return concepts
  109. def identify_methods(self, text: str) -> List[str]:
  110. """Tuvasta artiklis kasutatud meetodid"""
  111. self.logger.info("Tuvastan kasutatud meetodeid...")
  112. system_prompt = """Sa oled teadusmeetodite spetsialist. Tuvasta antud teadusartiklist
  113. kasutatud peamised meetodid (nt: regressioonanalüüs, simulatsioon, juhtumianalüüs jne).
  114. Tagasta komadega eraldatud nimekiri.
  115. """
  116. user_prompt = f"""Artikli tekst (osa):
  117. {text[:3000]}
  118. Palun tuvasta kasutatud meetodid. Tagasta VAID komadega eraldatud nimekiri.
  119. """
  120. messages = [
  121. {"role": "system", "content": system_prompt},
  122. {"role": "user", "content": user_prompt}
  123. ]
  124. response = self.call_api(messages, temperature=0.3)
  125. methods = [m.strip() for m in response.split(',') if m.strip()]
  126. return methods
  127. def analyze_transport_context(self, summary: str) -> Dict:
  128. """Analüüsi artikli tähtsus transpordiplaneerimise kontekstis"""
  129. self.logger.info("Analüüsin transpordi konteksti...")
  130. system_prompt = """Sa oled transpordiplaneerimise ekspert. Analüüsi antud teadusartikli
  131. tähtsust ja rakendatavust transpordisüsteemide planeerimisel.
  132. Hinda järgmisi aspekte:
  133. 1. Teoreetiline panus
  134. 2. Praktiline rakendatavus
  135. 3. Reaalsete probleemide lahendamine
  136. 4. Piirangud ja edasised vajadused
  137. """
  138. user_prompt = f"""Artikli kokkuvõte:
  139. {summary}
  140. Palun analüüsi artikli tähtsust transpordiplaneerimise kontekstis. Tagasta JSON formaadis:
  141. {{
  142. "theoretical_contribution": "lühikirjeldus",
  143. "practical_applicability": "lühikirjeldus",
  144. "problem_solving": "lühikirjeldus",
  145. "limitations": "lühikirjeldus",
  146. "relevance_score": 1-10 (kus 10 on kõige relevantsem)
  147. }}
  148. """
  149. messages = [
  150. {"role": "system", "content": system_prompt},
  151. {"role": "user", "content": user_prompt}
  152. ]
  153. response = self.call_api(messages, temperature=0.5)
  154. try:
  155. # Proovi parsida JSON vastust
  156. if response.startswith('{') and response.endswith('}'):
  157. return json.loads(response)
  158. except:
  159. pass
  160. # Kui JSON parsimine ei õnnestu, tagasta struktureeritud tekst
  161. return {
  162. "analysis": response,
  163. "relevance_score": 5 # Vaikimisi skoor
  164. }