ollama_client.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """
  2. Ollama API client for translation requests.
  3. """
  4. import requests
  5. from typing import Optional
  6. class OllamaClient:
  7. """Client for communicating with Ollama server."""
  8. MASTER_PROMPT = (
  9. "You are a professional Japanese (日本語) to English translator. "
  10. "Your task is to translate the following Japanese (日本語) text into English. "
  11. "IMPORTANT: You MUST always provide a translation, even if the text is fragmented, unclear, or lacks context. "
  12. "Do not refuse to translate or provide explanations - translate everything provided, making your best interpretation. "
  13. "Convey the meaning and nuances of the original text while adhering to English grammar and vocabulary. "
  14. "Output ONLY the English translation with no explanations, commentary, or meta-discussion. "
  15. "Translate the following Japanese (日本語) text into English:"
  16. )
  17. def __init__(self, base_url: str, model: str):
  18. """
  19. Initialize Ollama client.
  20. Args:
  21. base_url: Base URL for Ollama server (e.g., http://ai-house:11434/)
  22. model: Model name (e.g., translategemma:12b)
  23. """
  24. self.base_url = base_url.rstrip('/')
  25. self.model = model
  26. self.api_endpoint = f"{self.base_url}/api/generate"
  27. def translate(self, text: str, timeout: int = 300) -> Optional[str]:
  28. """
  29. Translate Japanese text to English using Ollama.
  30. Args:
  31. text: Japanese text to translate
  32. timeout: Request timeout in seconds
  33. Returns:
  34. Translated English text or None if translation fails
  35. """
  36. prompt = f"{self.MASTER_PROMPT}\n\n{text}"
  37. try:
  38. import sys
  39. print(f"[Ollama] Sending request to {self.api_endpoint}...", file=sys.stderr)
  40. sys.stderr.flush()
  41. response = requests.post(
  42. self.api_endpoint,
  43. json={
  44. "model": self.model,
  45. "prompt": prompt,
  46. "stream": False,
  47. },
  48. timeout=timeout
  49. )
  50. print(f"[Ollama] Got response, status: {response.status_code}", file=sys.stderr)
  51. sys.stderr.flush()
  52. response.raise_for_status()
  53. result = response.json()
  54. if 'response' in result:
  55. translated = result['response'].strip()
  56. print(f"[Ollama] Translation complete ({len(translated)} chars)", file=sys.stderr)
  57. sys.stderr.flush()
  58. return translated
  59. return None
  60. except requests.exceptions.Timeout as e:
  61. print(f"[Ollama] Timeout after {timeout}s: {e}", file=sys.stderr)
  62. return None
  63. except requests.exceptions.RequestException as e:
  64. print(f"[Ollama] Error: {e}", file=sys.stderr)
  65. return None
  66. except (KeyError, ValueError) as e:
  67. print(f"[Ollama] Parse error: {e}", file=sys.stderr)
  68. return None
  69. def is_available(self) -> bool:
  70. """Check if Ollama server is available."""
  71. try:
  72. response = requests.get(
  73. f"{self.base_url}/api/tags",
  74. timeout=5
  75. )
  76. return response.status_code == 200
  77. except requests.exceptions.RequestException:
  78. return False
  79. def get_model_info(self) -> Optional[dict]:
  80. """Get information about the model."""
  81. try:
  82. response = requests.post(
  83. f"{self.base_url}/api/show",
  84. json={"name": self.model},
  85. timeout=10
  86. )
  87. response.raise_for_status()
  88. return response.json()
  89. except requests.exceptions.RequestException:
  90. return None