client.py 9.0 KB

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