Stream 接入案例:React
useStream 适合单次流式生成场景。每次调用 generate() 都会重置 parts,不维护多轮消息历史。
tsx
import { useState } from 'react';
import { useStream } from '@tencent/ssv-ai-sdk-react';
import { AGUIPlugin } from '@tencent/ssv-ai-sdk-plugin-agui';
export function StreamGenerator() {
const [input, setInput] = useState('');
const {
parts,
status,
assistantStatus,
error,
generate,
stop,
} = useStream({
api: {
streamEndpoint: {
url: 'https://your-api.com/stream',
},
},
mode: 'stream',
plugins: [new AGUIPlugin()],
});
const handleGenerate = async () => {
if (!input.trim() || status === 'loading') return;
const ts = Date.now();
await generate({
input,
metadata: {
threadId: `thread-${ts}`,
runId: `run-${ts}`,
},
});
setInput('');
};
return (
<div>
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="输入内容..."
/>
<div>状态:{assistantStatus}</div>
{error && <div className="error">{error.message}</div>}
{status === 'loading' ? (
<button onClick={stop}>停止</button>
) : (
<button onClick={handleGenerate} disabled={!input.trim()}>生成</button>
)}
<div className="result">
{parts.map((part, index) => {
if (part.type === 'reasoning') {
return <div key={index} className="reasoning">{part.reason}</div>;
}
if (part.type === 'text') {
return <p key={index}>{part.text}</p>;
}
if (part.type === 'tool_call') {
return (
<div key={part.id} className="tool-call">
工具:{part.name},状态:{part.status}
{part.result && <pre>{JSON.stringify(part.result, null, 2)}</pre>}
</div>
);
}
return null;
})}
</div>
</div>
);
}
返回值速查
ts
const {
parts, // Part[],本次生成的时序内容段
status, // 'idle' | 'loading' | 'success' | 'failed' | 'stopped'
assistantStatus, // 'idle' | 'loading' | 'reasoning' | 'answering' | 'tool_calling'
error,
generate,
stop,
setOptions,
on,
off,
} = useStream(options);
适用场景
- 摘要、翻译、代码生成等单次任务
- 需要展示
reasoning/text/tool_call时序内容 - 不需要维护多轮历史,不需要注册前端工具
@ssv-lab