client.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import os
  2. import json
  3. import requests
  4. BASE_URL = os.environ.get('OLLAMA_HOST', 'http://localhost:11434')
  5. # Generate a response for a given prompt with a provided model. This is a streaming endpoint, so will be a series of responses.
  6. # The final response object will include statistics and additional data from the request. Use the callback function to override
  7. # the default handler.
  8. def generate(model_name, prompt, system=None, template=None, context=None, options=None, callback=None):
  9. try:
  10. url = f"{BASE_URL}/api/generate"
  11. payload = {
  12. "model": model_name,
  13. "prompt": prompt,
  14. "system": system,
  15. "template": template,
  16. "context": context,
  17. "options": options
  18. }
  19. # Remove keys with None values
  20. payload = {k: v for k, v in payload.items() if v is not None}
  21. with requests.post(url, json=payload, stream=True) as response:
  22. response.raise_for_status()
  23. # Creating a variable to hold the context history of the final chunk
  24. final_context = None
  25. # Variable to hold concatenated response strings if no callback is provided
  26. full_response = ""
  27. # Iterating over the response line by line and displaying the details
  28. for line in response.iter_lines():
  29. if line:
  30. # Parsing each line (JSON chunk) and extracting the details
  31. chunk = json.loads(line)
  32. # If a callback function is provided, call it with the chunk
  33. if callback:
  34. callback(chunk)
  35. else:
  36. # If this is not the last chunk, add the "response" field value to full_response and print it
  37. if not chunk.get("done"):
  38. response_piece = chunk.get("response", "")
  39. full_response += response_piece
  40. print(response_piece, end="", flush=True)
  41. # Check if it's the last chunk (done is true)
  42. if chunk.get("done"):
  43. final_context = chunk.get("context")
  44. # Return the full response and the final context
  45. return full_response, final_context
  46. except requests.exceptions.RequestException as e:
  47. print(f"An error occurred: {e}")
  48. return None, None
  49. # Create a model from a Modelfile. Use the callback function to override the default handler.
  50. def create(model_name, model_path, callback=None):
  51. try:
  52. url = f"{BASE_URL}/api/create"
  53. payload = {"name": model_name, "path": model_path}
  54. # Making a POST request with the stream parameter set to True to handle streaming responses
  55. with requests.post(url, json=payload, stream=True) as response:
  56. response.raise_for_status()
  57. # Iterating over the response line by line and displaying the status
  58. for line in response.iter_lines():
  59. if line:
  60. # Parsing each line (JSON chunk) and extracting the status
  61. chunk = json.loads(line)
  62. if callback:
  63. callback(chunk)
  64. else:
  65. print(f"Status: {chunk.get('status')}")
  66. except requests.exceptions.RequestException as e:
  67. print(f"An error occurred: {e}")
  68. # Pull a model from a the model registry. Cancelled pulls are resumed from where they left off, and multiple
  69. # calls to will share the same download progress. Use the callback function to override the default handler.
  70. def pull(model_name, insecure=False, callback=None):
  71. try:
  72. url = f"{BASE_URL}/api/pull"
  73. payload = {
  74. "name": model_name,
  75. "insecure": insecure
  76. }
  77. # Making a POST request with the stream parameter set to True to handle streaming responses
  78. with requests.post(url, json=payload, stream=True) as response:
  79. response.raise_for_status()
  80. # Iterating over the response line by line and displaying the details
  81. for line in response.iter_lines():
  82. if line:
  83. # Parsing each line (JSON chunk) and extracting the details
  84. chunk = json.loads(line)
  85. # If a callback function is provided, call it with the chunk
  86. if callback:
  87. callback(chunk)
  88. else:
  89. # Print the status message directly to the console
  90. print(chunk.get('status', ''), end='', flush=True)
  91. # If there's layer data, you might also want to print that (adjust as necessary)
  92. if 'digest' in chunk:
  93. print(f" - Digest: {chunk['digest']}", end='', flush=True)
  94. print(f" - Total: {chunk['total']}", end='', flush=True)
  95. print(f" - Completed: {chunk['completed']}", end='\n', flush=True)
  96. else:
  97. print()
  98. except requests.exceptions.RequestException as e:
  99. print(f"An error occurred: {e}")
  100. # Push a model to the model registry. Use the callback function to override the default handler.
  101. def push(model_name, insecure=False, callback=None):
  102. try:
  103. url = f"{BASE_URL}/api/push"
  104. payload = {
  105. "name": model_name,
  106. "insecure": insecure
  107. }
  108. # Making a POST request with the stream parameter set to True to handle streaming responses
  109. with requests.post(url, json=payload, stream=True) as response:
  110. response.raise_for_status()
  111. # Iterating over the response line by line and displaying the details
  112. for line in response.iter_lines():
  113. if line:
  114. # Parsing each line (JSON chunk) and extracting the details
  115. chunk = json.loads(line)
  116. # If a callback function is provided, call it with the chunk
  117. if callback:
  118. callback(chunk)
  119. else:
  120. # Print the status message directly to the console
  121. print(chunk.get('status', ''), end='', flush=True)
  122. # If there's layer data, you might also want to print that (adjust as necessary)
  123. if 'digest' in chunk:
  124. print(f" - Digest: {chunk['digest']}", end='', flush=True)
  125. print(f" - Total: {chunk['total']}", end='', flush=True)
  126. print(f" - Completed: {chunk['completed']}", end='\n', flush=True)
  127. else:
  128. print()
  129. except requests.exceptions.RequestException as e:
  130. print(f"An error occurred: {e}")
  131. # List models that are available locally.
  132. def list():
  133. try:
  134. response = requests.get(f"{BASE_URL}/api/tags")
  135. response.raise_for_status()
  136. data = response.json()
  137. models = data.get('models', [])
  138. return models
  139. except requests.exceptions.RequestException as e:
  140. print(f"An error occurred: {e}")
  141. return None
  142. # Copy a model. Creates a model with another name from an existing model.
  143. def copy(source, destination):
  144. try:
  145. # Create the JSON payload
  146. payload = {
  147. "source": source,
  148. "destination": destination
  149. }
  150. response = requests.post(f"{BASE_URL}/api/copy", json=payload)
  151. response.raise_for_status()
  152. # If the request was successful, return a message indicating that the copy was successful
  153. return "Copy successful"
  154. except requests.exceptions.RequestException as e:
  155. print(f"An error occurred: {e}")
  156. return None
  157. # Delete a model and its data.
  158. def delete(model_name):
  159. try:
  160. url = f"{BASE_URL}/api/delete"
  161. payload = {"name": model_name}
  162. response = requests.delete(url, json=payload)
  163. response.raise_for_status()
  164. return "Delete successful"
  165. except requests.exceptions.RequestException as e:
  166. print(f"An error occurred: {e}")
  167. return None
  168. # Show info about a model.
  169. def show(model_name):
  170. try:
  171. url = f"{BASE_URL}/api/show"
  172. payload = {"name": model_name}
  173. response = requests.post(url, json=payload)
  174. response.raise_for_status()
  175. # Parse the JSON response and return it
  176. data = response.json()
  177. return data
  178. except requests.exceptions.RequestException as e:
  179. print(f"An error occurred: {e}")
  180. return None
  181. def heartbeat():
  182. try:
  183. url = f"{BASE_URL}/"
  184. response = requests.head(url)
  185. response.raise_for_status()
  186. return "Ollama is running"
  187. except requests.exceptions.RequestException as e:
  188. print(f"An error occurred: {e}")
  189. return "Ollama is not running"