Sep 1, 2025
0
Level 11
Need the Stream Output to be well structured
So i need the stream output to be well structured but i have tried all aspects of structure but it does not
<?php
namespace App\Livewire\Test;
use Livewire\Component;
use Prism\Prism\Prism;
class Maths extends Component
{
public string $solutionText = '';
public bool $isStreaming = false;
public function solve()
{
// Reset everything
$this->solutionText = '';
$this->isStreaming = true;
$this->dispatch('clearCanvas');
try {
$prism = new Prism();
$stream = $prism::text()
->using('openai', 'gpt-4')
->withPrompt('
Solve the quadratic equation x² + 5x + 6 = 0 step by step.
Use this exact format:
Step 1: Identify coefficients
a = 1, b = 5, c = 6
Step 2: Apply quadratic formula
x = (-b ± √(b² - 4ac)) / 2a
Step 3: Calculate discriminant
b² - 4ac = 25 - 24 = 1
Step 4: Find solutions
x = (-5 ± 1) / 2
x₁ = -2, x₂ = -3
Be clear and concise. Use proper line breaks.
')
->asStream();
$previousContent = '';
foreach ($stream as $chunk) {
if (!empty($chunk->text)) {
// DEBUG: Log what we receive
\Log::info('RAW CHUNK: ' . json_encode($chunk->text));
// Check if this chunk is a repeat of previous content
if (str_contains($previousContent, trim($chunk->text))) {
\Log::info('SKIPPING DUPLICATE CHUNK');
continue;
}
// Only send if it's truly new content
$this->dispatch('solutionUpdated', text: $chunk->text);
$previousContent .= $chunk->text;
usleep(100000);
}
}
} catch (\Exception $e) {
\Log::error('Prism Error: ' . $e->getMessage());
$this->dispatch('solutionUpdated', text: 'Error: ' . $e->getMessage());
} finally {
$this->isStreaming = false;
}
}
public function render()
{
return view('livewire.test.maths')
->extends('layouts.app')
->section('content');
}
}
<div class="p-6" x-data="simpleCanvas" x-init="init()">
<h1 class="text-xl font-bold mb-4">Quadratic Solver (Simple Streaming)</h1>
<button wire:click="solve" class="px-4 py-2 bg-blue-600 text-white rounded-lg mb-4">
Solve Equation
</button>
<canvas id="solution-canvas" width="800" height="600" style="border:1px solid #000;"></canvas>
<div class="mt-4 text-sm text-gray-600">
Debug: <span x-text="debugInfo"></span>
</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('simpleCanvas', () => ({
canvas: null,
ctx: null,
x: 10,
y: 30,
lineHeight: 25,
debugInfo: 'Ready',
init() {
this.canvas = document.getElementById('solution-canvas');
this.ctx = this.canvas.getContext('2d');
this.ctx.font = "18px 'Courier New', monospace"; // Better for math
this.ctx.fillStyle = "#000";
this.ctx.fillText("Ready to solve... Click the button!", 10, 30);
this.$wire.on('clearCanvas', () => {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.x = 10;
this.y = 30;
this.debugInfo = 'Canvas cleared';
});
this.$wire.on('solutionUpdated', (data) => {
let chunk = typeof data === 'string' ? data : data.text;
if (!chunk) return;
this.debugInfo = 'Received: ' + JSON.stringify(chunk.substring(0, 20));
console.log('CHUNK:', JSON.stringify(chunk));
// Simple approach: just add the text
this.addText(chunk);
});
},
addText(text) {
// Replace newlines with actual line breaks
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (i > 0) {
// Move to next line for each \n
this.y += this.lineHeight;
this.x = 10;
}
// Draw the line
if (line.length > 0) {
// Check if line fits, if not wrap it
const words = line.split(' ');
let currentLine = '';
for (let word of words) {
const testLine = currentLine + (currentLine ? ' ' : '') + word;
const width = this.ctx.measureText(testLine).width;
if (width > 780 && currentLine) {
// Draw current line and start new one
this.ctx.fillText(currentLine, this.x, this.y);
this.y += this.lineHeight;
this.x = 10;
currentLine = word;
} else {
currentLine = testLine;
}
}
// Draw remaining text
if (currentLine) {
this.ctx.fillText(currentLine, this.x, this.y);
this.x += this.ctx.measureText(currentLine).width;
}
}
// Check if we need to scroll
if (this.y > this.canvas.height - 50) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.x = 10;
this.y = 30;
}
}
}
}));
});
</script>
The output is just joined and not structured
i want to achieve something like this https://postimg.cc/njHTdZ2x
But i get https://postimg.cc/WhD8Y5Gd
Please or to participate in this conversation.