#
# ==================================================================================
from flask import Blueprint, request, jsonify
+from trainingmgr.service.agent_service import AgentClient
agent_controller = Blueprint("agent_controller", __name__)
+# Singleton instance of AgentClient
+_agent_client = AgentClient()
+
+# Initialize the agent once when the module is loaded
+_agent_client.initialize_agent()
+
@agent_controller.route("/modelInfo", methods=["GET"])
def model_info():
return jsonify({
"llm": {
- "model": ""
+ "model": "",
}
}), 200
def generate_content():
body = request.get_json(silent=True) or {}
text = body.get("text")
+
if not isinstance(text, str) or not text.strip():
return jsonify({
"title": "Bad Request",
"status": 400,
"detail": "The 'text' field is required and must be a non-empty string."
}), 400
- dry_run = bool(body.get("dry_run", True))
- return jsonify({
- "action": "noop",
- "request": {"text": text, "dry_run": dry_run},
- "response": {"note": "Received successfully"},
- "status": "ok",
- "error_message": None
- }), 200
\ No newline at end of file
+
+ try:
+ result = _agent_client.process_user_request(text)
+ if result['success']:
+ return jsonify({
+ "action": "completed",
+ "request": {"text": text},
+ "response": {"result": result['result']},
+ "status": "ok",
+ "error_message": None
+ }), 200
+ else:
+ return jsonify({
+ "action": "failed",
+ "request": {"text": text},
+ "response": {"error": result['error']},
+ "status": "error",
+ "error_message": result['error']
+ }), 500
+
+ except Exception as err:
+ return jsonify({
+ "action": "failed",
+ "request": {"text": text},
+ "response": {"error": str(err)},
+ "status": "error",
+ "error_message": str(err)
+ }), 500
\ No newline at end of file
--- /dev/null
+# ==================================================================================
+#
+# Copyright (c) 2025 Taeil Jung <wjdxodlf0123@gmail.com> All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ==================================================================================
+import dspy
+import os
+from trainingmgr.common.trainingmgr_config import TrainingMgrConfig
+from trainingmgr.common.exceptions_utls import TMException
+from threading import Lock
+
+LOGGER = TrainingMgrConfig().logger
+
+# Define the agent signature
+class AgentSignature(dspy.Signature):
+ """A signature for the DSPy agent."""
+ query: str = dspy.InputField(desc= "The user's natural language request for creating feature group or registering model")
+ final: str = dspy.OutputField(desc= "Message that summarize the process result")
+
+
+class AgentClient:
+ """Encapsulates the DSPy agent. Implements Singleton pattern if desired."""
+
+ _instance = None
+ _lock = Lock()
+
+ def __new__(cls, *args, **kwargs):
+ """Singleton: ensure only one instance is created."""
+ if cls._instance is None:
+ with cls._lock:
+ if cls._instance is None:
+ cls._instance = super().__new__(cls, *args, **kwargs)
+ return cls._instance
+
+ def __init__(self):
+ self._agent = None
+ self._initialized = False
+
+ def initialize_agent(self) -> bool:
+ """Initialize the DSPy agent with tools."""
+ if self._initialized:
+ return True
+
+ try:
+ agent_model = os.getenv("LLM_AGENT_MODEL_FOR_TM")
+ agent_token = os.getenv("LLM_AGENT_MODEL_TOKEN_FOR_TM")
+
+ if not agent_model:
+ LOGGER.error("LLM_AGENT_MODEL_FOR_TM not specified")
+ return False
+ elif not agent_token:
+ LOGGER.error("LLM_AGENT_MODEL_TOKEN_FOR_TM not found")
+ return False
+
+ # LM configuration
+ lm = dspy.LM(agent_model, api_key=agent_token)
+ dspy.configure(lm=lm)
+
+ # Agent configuration
+ self._agent = dspy.ReAct(
+ AgentSignature,
+ tools=[],
+ max_iters=6
+ )
+
+ self._initialized = True
+ LOGGER.info("Agent initialized successfully.")
+ return True
+
+ except Exception as err:
+ raise TMException(f"fail to initialize agent exception : {str(err)}")
+
+ def process_user_request(self, user_text_request):
+ """Process user request with agent tools."""
+ if not self._initialized or self._agent is None:
+ raise TMException("Agent not initialized")
+
+ try:
+ result = self._agent(query=user_text_request)
+ response = result.final
+ return {
+ 'success': True,
+ 'result': response,
+ }
+ except Exception as err:
+ LOGGER.error(f"Error processing user request: {str(err)}")
+ return {
+ 'success': False,
+ 'error': str(err),
+ }
+