Handling AI Interactions with the Chat Service Layer in PHP
Handling AI Interactions with the Chat Service Layer
In the previous lesson, we explored the ChatManager class, which plays a crucial role in managing chat data within our application. Now, we will take the next step in our journey by building the Chat Service Layer. This layer is essential for integrating the language model with chat sessions, allowing us to process user messages and generate AI responses. By the end of this lesson, you will understand how to set up the ChatService class, create chat sessions, and process messages using OpenAI's API.
The service layer acts as a bridge between the model layer, where data is managed, and the AI model, which generates responses. It is responsible for orchestrating the flow of data and ensuring that user interactions are handled smoothly. Let's dive into the details of setting up this important component.
Setting Up the ChatService Class
Creating a New Chat Session
Processing User Messages
Example: Simulating a Chat Session
Summary and Next Steps
In this lesson, we explored the ChatService class and its role in integrating the language model with chat sessions. We learned how to set up the class, load the system prompt, create chat sessions, and process user messages. The service layer is a vital component of our chatbot application, ensuring that user interactions are handled smoothly and efficiently.
As you move on to the practice exercises, take the opportunity to experiment with the ChatService functionality. This hands-on practice will reinforce the concepts covered in this lesson and prepare you for the next steps in our course. Keep up the great work, and I look forward to seeing your progress!
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal
The ChatService class is the heart of our service layer. It is responsible for managing chat sessions and interacting with the OpenAI client to generate AI responses. To begin, we need to set up the class and its components.
First, we include the necessary files, including the ChatManager from our previous lesson and the OpenAI client. We also use PHP's uniqid() function to generate unique chat IDs. Here’s how the class is initialized:
PHP
<?phpnamespace App\Services;use App\Models\ChatManager;use Symfony\Component\HttpFoundation\RequestStack;use OpenAI\Client;use Exception;class ChatService { private ChatManager $chatManager; private Client $openaiClient; private string $systemPrompt; public function __construct(RequestStack $requestStack) { $this->chatManager = new ChatManager($requestStack); // Initialize the OpenAI client $apiKey = $_ENV['OPENAI_API_KEY'] ?? getenv('OPENAI_API_KEY'); $baseUrl = $_ENV['OPENAI_BASE_URL'] ?? getenv('OPENAI_BASE_URL'); $baseUrl = rtrim($baseUrl, '/'); if (!str_ends_with($baseUrl, '/v1')) { $baseUrl .= '/v1'; } $this->openaiClient = \OpenAI::factory() ->withApiKey($apiKey) ->withBaseUri($baseUrl) ->make(); $this->systemPrompt = $this->loadSystemPrompt(__DIR__ . '/../../data/system_prompt.txt'); } private function loadSystemPrompt(string $filePath): string { try { if (!file_exists($filePath)) { throw new Exception("File not found."); } $content = file_get_contents($filePath); if ($content === false) { throw new Exception("Error reading file."); } return $content; } catch (Exception $e) { echo "Error loading system prompt: " . $e->getMessage() . PHP_EOL; return "You are a helpful assistant."; } }}
In this setup, we instantiate ChatManager to manage chat data, initialize the OpenAI client, and load the systemPrompt using the loadSystemPrompt method.
Note: In a full Symfony application, RequestStack is provided automatically during an HTTP request (and it will contain the current Request, including the session). In standalone scripts (like the example below), we must bootstrap a Request + Session manually.
Creating a new chat session is a fundamental task of the ChatService. The createChat method is responsible for generating a unique chat ID and initializing a chat session using the ChatManager.
PHP
public function createChat(string $userId): string { $chatId = uniqid(); $this->chatManager->createChat($userId, $chatId, $this->systemPrompt); return $chatId;}
In this method, we generate a unique chatId using PHP's uniqid() function. We then call the createChat method of ChatManager, passing the userId, chatId, and systemPrompt. This initializes a new chat session, which is ready to receive messages.
The processMessage method is where the magic happens. It processes user messages, interacts with the OpenAI client to generate AI responses, and updates the chat history. Below, we outline the steps involved in this process, followed by the corresponding code implementation:
Retrieve the chat using getChat, and raise an error if the chat is not found.
Add the user's message to the chat history.
Send the conversation, including the system prompt and all messages, to the OpenAI client to generate a response.
Add the AI's response to the chat history and return it to the user.
Handle any errors with the AI client gracefully.
PHP
public function processMessage(string $userId, string $chatId, string $message): string { $chat = $this->chatManager->getChat($userId, $chatId); if (!$chat) { throw new \ValueError("Chat not found"); } // Add user message $this->chatManager->addMessage($userId, $chatId, "user", $message); try { // Get AI response $conversation = $this->chatManager->getConversation($userId, $chatId); $response = $this->openaiClient->chat()->create([ 'model' => 'gpt-4', 'messages' => $conversation, 'temperature' => 0.7, 'max_tokens' => 500 ]); $aiMessage = trim($response->choices[0]->message->content); // Add AI response to chat history $this->chatManager->addMessage($userId, $chatId, "assistant", $aiMessage); return $aiMessage; } catch (Exception $e) { throw new \RuntimeException("Error getting AI response: " . $e->getMessage()); }}
In the context of a customer service agent, we configure our model with specific parameters to optimize its performance. The temperature is set to 0.7, which balances creativity and coherence in the AI's responses, ensuring they are both engaging and relevant. The max_tokens is set to 500, allowing the model to provide detailed and informative answers without overwhelming the user, thus maintaining a smooth and effective customer service experience.
Because ChatManager reads/writes chat state via the session (accessed through RequestStack), a standalone script must create:
a Session (we’ll use MockArraySessionStorage for an in-memory session),
a Request and attach the session to it,
and push that request into the RequestStack.
PHP
<?phprequire 'vendor/autoload.php';use App\Services\ChatService;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\RequestStack;use Symfony\Component\HttpFoundation\Session\Session;use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;try { // 1) Bootstrap a session + request (needed because ChatManager uses RequestStack -> session) $session = new Session(new MockArraySessionStorage()); $session->start(); $request = Request::create('/'); $request->setSession($session); $requestStack = new RequestStack(); $requestStack->push($request); // 2) Create the service $chatService = new ChatService($requestStack); $userId = "user123"; $chatId = $chatService->createChat($userId); echo "Chat session created with ID: $chatId" . PHP_EOL; $userMessage = "Hello, how are you?"; $aiResponse = $chatService->processMessage($userId, $chatId, $userMessage); echo "AI Response: $aiResponse" . PHP_EOL;} catch (Exception $e) { echo "Error: " . $e->getMessage() . PHP_EOL;}
Example output (your chat ID and response will vary):
text
Chat session created with ID: 65a17870c3f9aAI Response: Hello! I'm here to help with any questions or concerns you might have regarding our IT services. How can I assist you today?
This output illustrates a successful interaction where a new chat session is created, and the AI responds to the user's greeting with a helpful message. The AI's response is tailored to assist with IT services, showcasing the system's ability to provide relevant and context-aware assistance.