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.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
Create a Real-Time AI Chat Assistant using Webman, Neuron AI, and Baileian

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.0

Neuron AI Agent

composer require neuron-core/neuron-ai

Custom 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.

PHPAI assistantAlibaba CloudSSEWebmanNeuron AI
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.