Create a Real-Time AI Chat Assistant using Webman, Neuron AI, and Baileian
This step‑by‑step tutorial shows how to install the Webman PHP framework, integrate the Neuron AI Agent, configure a custom Alibaba Cloud Baileian model provider, build an AssistantAgent, and expose a Server‑Sent Events controller for real‑time AI chat responses.
Overview
This guide shows how to integrate the Neuron AI Agent into a Webman application, use Alibaba Cloud Baileian (an OpenAI‑compatible large‑model service) as a custom AI provider, and expose the assistant via a Server‑Sent Events (SSE) controller that streams responses in real time.
Installation
Webman
composer create-project workerman/webman:~2.0Neuron AI Agent
composer require neuron-core/neuron-aiCustom Baileian Provider
Create BaiLianAI.php that extends NeuronAI\Providers\OpenAI\OpenAI and overrides the base URI to point to the Baileian endpoint.
<?php
/**
* @desc Alibaba Cloud Baileian large‑model service provider
*/
declare(strict_types=1);
namespace app\common\agent\provider;
use GuzzleHttp\Client;
use NeuronAI\Providers\HttpClientOptions;
use NeuronAI\Providers\OpenAI\OpenAI;
class BaiLianAI extends OpenAI {
protected string $baseUri = 'https://api.openai.com/v1';
public function __construct(
protected string $key,
protected string $model,
protected array $parameters = [],
protected bool $strict_response = false,
protected ?HttpClientOptions $httpOptions = null,
?string $baseUri = null // custom API address
) {
if ($baseUri !== null) {
$this->baseUri = $baseUri;
}
$config = [
'base_uri' => rtrim($this->baseUri, '/') . '/',
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $this->key,
],
];
if ($this->httpOptions instanceof HttpClientOptions) {
$config = $this->mergeHttpOptions($config, $this->httpOptions);
}
$this->client = new Client($config);
}
}Assistant Agent
Define AssistantAgent.php that returns a BaiLianAI instance with your API key, model, and Baileian base URI, and provides a system prompt for the AI.
<?php
declare(strict_types=1);
namespace app\common\agent;
use app\common\agent\provider\BaiLianAI;
use NeuronAI\Agent;
use NeuronAI\Providers\AIProviderInterface;
use NeuronAI\SystemPrompt;
class AssistantAgent extends Agent {
protected function provider(): AIProviderInterface {
// Replace with your own API key and model
$apiKey = 'sk-xxxxxxxxxxxxxxx';
$model = 'qwen-max';
return new BaiLianAI(
key: $apiKey,
model: $model,
baseUri: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
);
}
public function instructions(): string {
return (string) new SystemPrompt([
"You are Tongyi Qianwen, an AI assistant developed by Alibaba Cloud.",
"You excel at answering questions and providing useful advice.",
"Please reply to users in Chinese."
]);
}
}SSE Controller
Implement AssistantController.php with two actions. index() renders the chat view. chat(Request $request) reads the user message, starts a short‑interval timer, streams the AI response via AssistantAgent::make()->stream(new UserMessage($message)), and pushes each chunk to the client using Workerman\Protocols\Http\ServerSentEvents. After the stream finishes, a completed event is sent and the connection is closed.
<?php
declare(strict_types=1);
namespace app\controller;
use app\common\agent\AssistantAgent;
use support\Request;
use Webman\Http\Response;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\ServerSentEvents;
use Workerman\Timer;
use NeuronAI\Chat\Messages\UserMessage;
class AssistantController {
public function index(): Response {
return view('assistant/index', ['name' => 'webman']);
}
public function chat(Request $request): Response {
$message = $request->input('message', '介绍一下webman');
$connection = $request->connection;
$id = Timer::add(0.1, function () use ($connection, &$id, $message) {
if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) {
Timer::del($id);
return;
}
$stream = AssistantAgent::make()->stream(new UserMessage($message));
foreach ($stream as $chunk) {
$content = is_string($chunk) ? $chunk : $chunk->getContent();
if (!empty($content)) {
$connection->send(new ServerSentEvents([
'event' => 'message',
'data' => $content,
]));
}
}
$connection->send(new ServerSentEvents([
'event' => 'completed',
'data' => 'done',
]));
Timer::del($id);
$connection->close();
}, [], false);
return response('', 200, [
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
'X-Accel-Buffering' => 'no',
]);
}
}SSE Requirements
Server must send Content-Type: text/event-stream with UTF‑8 encoding.
Client should use the browser EventSource API to listen for message and completed events.
Running the Example
Start the Webman server and open http://127.0.0.1:8787/assistant/chat in a browser. The page displays a simple chat UI that receives streamed AI replies in real time.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
