Coverage for mindsdb / api / http / namespaces / chatbots.py: 79%
151 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1from http import HTTPStatus
3from flask import request
4from flask_restx import Resource
6from mindsdb.api.http.namespaces.configs.projects import ns_conf
7from mindsdb.interfaces.agents.agents_controller import AgentsController
8from mindsdb.api.executor.controllers.session_controller import SessionController
9from mindsdb.api.http.utils import http_error
10from mindsdb.metrics.metrics import api_endpoint_metrics
11from mindsdb.interfaces.chatbot.chatbot_controller import ChatBotController
12from mindsdb.interfaces.model.functions import PredictorRecordNotFound
13from mindsdb.interfaces.storage.db import Predictor
14from mindsdb.utilities.exception import EntityNotExistsError
17def create_chatbot(project_name, name, chatbot):
18 if name is None:
19 return http_error(HTTPStatus.BAD_REQUEST, "Missing field", 'Missing "name" field for chatbot')
21 model_name = chatbot.get("model_name", None)
22 agent_name = chatbot.get("agent_name", None)
23 if model_name is None and agent_name is None:
24 return http_error(
25 HTTPStatus.BAD_REQUEST,
26 "Missing field",
27 'Must include either "model_name" or "agent_name" field for chatbot',
28 )
30 session_controller = SessionController()
32 if "database_id" in chatbot or "database_name" in chatbot or ("db_engine" in chatbot and "db_params" in chatbot):
33 try:
34 database_id = get_or_create_database_for_chatbot(chatbot, session_controller)
35 except ValueError as value_error:
36 return http_error(HTTPStatus.NOT_FOUND, "Database not found", str(value_error))
38 else:
39 return http_error(
40 HTTPStatus.BAD_REQUEST,
41 "Missing field",
42 'Missing "database_id" or ("db_engine" and "database_param") fields for chatbot',
43 )
45 is_running = chatbot.get("is_running", False)
46 params = chatbot.get("params", {})
48 chatbot_controller = ChatBotController()
50 # Chatbot can't already exist.
51 # TODO all checks should be inside of controller
53 try:
54 existing_chatbot = chatbot_controller.get_chatbot(name, project_name=project_name)
55 except EntityNotExistsError:
56 # Project must exist.
57 return http_error(HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist")
58 if existing_chatbot is not None: 58 ↛ 59line 58 didn't jump to line 59 because the condition on line 58 was never true
59 return http_error(
60 HTTPStatus.CONFLICT,
61 "Chatbot already exists",
62 f"Chatbot with name {name} already exists. Please use a different name",
63 )
65 # Model and agent need to exist.
66 if agent_name is not None: 66 ↛ 67line 66 didn't jump to line 67 because the condition on line 66 was never true
67 agent = AgentsController().get_agent(agent_name, project_name)
68 if agent is None:
69 return http_error(HTTPStatus.NOT_FOUND, "Agent not found", f"Agent with name {agent_name} not found")
70 model_name = agent.model_name
72 model_name_no_version, version = Predictor.get_name_and_version(model_name)
73 try:
74 session_controller.model_controller.get_model(model_name_no_version, version=version, project_name=project_name)
75 except PredictorRecordNotFound:
76 return http_error(HTTPStatus.NOT_FOUND, "Model not found", f"Model with name {model_name} not found")
78 created_chatbot = chatbot_controller.add_chatbot(
79 name,
80 project_name,
81 model_name=model_name,
82 agent_name=agent_name,
83 database_id=database_id,
84 is_running=is_running,
85 params=params,
86 )
87 return created_chatbot.as_dict(), HTTPStatus.CREATED
90def get_or_create_database_for_chatbot(chatbot: dict, session_controller: SessionController) -> int:
91 """
92 Get or create a database for a chatbot, based on the chatbot configuration provided in the request.
94 Args:
95 chatbot (dict): The chatbot configuration.
96 session_controller (SessionController): The session controller.
98 Returns:
99 int: The database ID.
100 """
101 if "database_id" in chatbot:
102 database_record = session_controller.integration_controller.get_by_id(chatbot["database_id"])
103 if database_record: 103 ↛ 106line 103 didn't jump to line 106 because the condition on line 103 was always true
104 return database_record["id"]
105 else:
106 raise ValueError(f"Database with ID {chatbot['database_id']} not found")
108 elif "database_name" in chatbot: 108 ↛ 109line 108 didn't jump to line 109 because the condition on line 108 was never true
109 database_record = session_controller.integration_controller.get(chatbot["database_name"])
110 if database_record:
111 return database_record["id"]
112 else:
113 raise ValueError(f"Database with name {chatbot['database_name']} not found")
115 if "db_params" in chatbot and "db_engine" in chatbot: 115 ↛ 116line 115 didn't jump to line 116 because the condition on line 115 was never true
116 db_name = chatbot["name"] + "_db"
118 # try to drop
119 existing_db = session_controller.integration_controller.get(db_name)
120 if existing_db:
121 # drop
122 session_controller.integration_controller.delete(db_name)
124 return session_controller.integration_controller.add(db_name, chatbot["db_engine"], chatbot["db_params"])
126 return None
129@ns_conf.route("/<project_name>/chatbots")
130class ChatBotsResource(Resource):
131 @ns_conf.doc("list_chatbots")
132 @api_endpoint_metrics("GET", "/chatbots")
133 def get(self, project_name):
134 """List all chatbots"""
135 chatbot_controller = ChatBotController()
136 try:
137 all_bots = chatbot_controller.get_chatbots(project_name)
138 except (ValueError, EntityNotExistsError):
139 # Project needs to exist.
140 return http_error(
141 HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist"
142 )
143 return all_bots
145 @ns_conf.doc("create_chatbot")
146 @api_endpoint_metrics("POST", "/chatbots")
147 def post(self, project_name):
148 """Create a chatbot"""
150 # Check for required parameters.
151 if "chatbot" not in request.json:
152 return http_error(
153 HTTPStatus.BAD_REQUEST, "Missing parameter", 'Must provide "chatbot" parameter in POST body'
154 )
156 chatbot = request.json["chatbot"]
158 name = chatbot.get("name")
159 return create_chatbot(project_name, name, chatbot)
162@ns_conf.route("/<project_name>/chatbots/<chatbot_name>")
163@ns_conf.param("project_name", "Name of the project")
164@ns_conf.param("chatbot_name", "Name of the chatbot")
165class ChatBotResource(Resource):
166 @ns_conf.doc("get_chatbot")
167 @api_endpoint_metrics("GET", "/chatbots/chatbot")
168 def get(self, project_name, chatbot_name):
169 """Gets a chatbot by name"""
170 chatbot_controller = ChatBotController()
171 try:
172 existing_chatbot = chatbot_controller.get_chatbot(chatbot_name, project_name=project_name)
173 if existing_chatbot is None:
174 return http_error(
175 HTTPStatus.NOT_FOUND, "Chatbot not found", f"Chatbot with name {chatbot_name} does not exist"
176 )
177 return existing_chatbot
178 except (ValueError, EntityNotExistsError):
179 # Project needs to exist.
180 return http_error(
181 HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist"
182 )
184 @ns_conf.doc("update_chatbot")
185 @api_endpoint_metrics("PUT", "/chatbots/chatbot")
186 def put(self, project_name, chatbot_name):
187 """Updates a chatbot by name, creating one if it doesn't exist"""
189 # Check for required parameters.
190 if "chatbot" not in request.json:
191 return http_error(
192 HTTPStatus.BAD_REQUEST, "Missing parameter", 'Must provide "chatbot" parameter in POST body'
193 )
194 chatbot_controller = ChatBotController()
196 try:
197 existing_chatbot = chatbot_controller.get_chatbot(chatbot_name, project_name=project_name)
198 except EntityNotExistsError:
199 # Project needs to exist.
200 return http_error(
201 HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist"
202 )
204 session = SessionController()
206 chatbot = request.json["chatbot"]
207 name = chatbot.get("name", None)
208 agent_name = chatbot.get("agent_name", None)
209 model_name = chatbot.get("model_name", None)
210 try:
211 database_id = get_or_create_database_for_chatbot(chatbot, session)
212 except ValueError as value_error:
213 return http_error(HTTPStatus.NOT_FOUND, "Database not found", str(value_error))
214 is_running = chatbot.get("is_running", None)
215 params = chatbot.get("params", None)
217 # Model needs to exist.
218 if model_name is not None:
219 model_name_no_version, version = Predictor.get_name_and_version(model_name)
220 try:
221 session.model_controller.get_model(model_name_no_version, version=version, project_name=project_name)
222 except PredictorRecordNotFound:
223 return http_error(HTTPStatus.NOT_FOUND, "Model not found", f"Model with name {model_name} not found")
225 # Agent needs to exist.
226 if agent_name is not None: 226 ↛ 227line 226 didn't jump to line 227 because the condition on line 226 was never true
227 agent = session.agents_controller.get_agent(agent_name, project_name)
228 if agent is None:
229 return http_error(HTTPStatus.NOT_FOUND, "Agent not found", f"Agent with name {agent_name} not found")
231 # Chatbot must not exist with new name.
232 if name is not None:
233 if name != chatbot_name: 233 ↛ 234line 233 didn't jump to line 234 because the condition on line 233 was never true
234 chatbot_with_new_name = chatbot_controller.get_chatbot(name, project_name=project_name)
235 if chatbot_with_new_name is not None:
236 return http_error(
237 HTTPStatus.CONFLICT,
238 "Chatbot already exists",
239 f"Chatbot with name {name} already exists. Please choose a different one.",
240 )
242 if existing_chatbot is None:
243 # Create
244 return create_chatbot(project_name, name, chatbot)
246 # Update
247 updated_chatbot = chatbot_controller.update_chatbot(
248 chatbot_name,
249 project_name=project_name,
250 name=name,
251 model_name=model_name,
252 agent_name=agent_name,
253 database_id=database_id,
254 is_running=is_running,
255 params=params,
256 )
257 return updated_chatbot.as_dict()
259 @ns_conf.doc("delete_chatbot")
260 @api_endpoint_metrics("DELETE", "/chatbots/chatbot")
261 def delete(self, project_name, chatbot_name):
262 """Deletes a chatbot by name"""
263 chatbot_controller = ChatBotController()
264 try:
265 existing_chatbot = chatbot_controller.get_chatbot(chatbot_name, project_name=project_name)
266 if existing_chatbot is None:
267 return http_error(
268 HTTPStatus.NOT_FOUND, "Chatbot not found", f"Chatbot with name {chatbot_name} does not exist"
269 )
270 except EntityNotExistsError:
271 # Project needs to exist.
272 return http_error(
273 HTTPStatus.NOT_FOUND, "Project not found", f"Project with name {project_name} does not exist"
274 )
276 chatbot_controller.delete_chatbot(chatbot_name, project_name=project_name)
277 return "", HTTPStatus.NO_CONTENT