This is a collection of convenience functions and components to make interacting with LLM functionality in Grafana easier.
First, add the latest version of @grafana/llm
to your dependencies in package.json:
{
"dependencies": {
"@grafana/llm": "0.11.0"
}
}
Then in your components you can use the llm
object from @grafana/llm
like so:
import React, { useState } from 'react';
import { useAsync } from 'react-use';
import { scan } from 'rxjs/operators';
import { llms } from '@grafana/llm';
import { PluginPage } from '@grafana/runtime';
import { Button, Input, Spinner } from '@grafana/ui';
const MyComponent = (): JSX.Element => {
const [input, setInput] = React.useState('');
const [message, setMessage] = React.useState('');
const [reply, setReply] = useState('');
const { loading, error } = useAsync(async () => {
const enabled = await llms.openai.enabled();
if (!enabled) {
return false;
}
if (message === '') {
return;
}
// Stream the completions. Each element is the next stream chunk.
const stream = llms.openai
.streamChatCompletions({
// model: llms.openai.Model.LARGE, // defaults to BASE, use larger model for longer context and complex tasks
messages: [
{ role: 'system', content: 'You are a cynical assistant.' },
{ role: 'user', content: message },
],
})
.pipe(
// Accumulate the stream chunks into a single string.
scan((acc, delta) => acc + delta, '')
);
// Subscribe to the stream and update the state for each returned value.
return stream.subscribe(setReply);
}, [message]);
if (error) {
// TODO: handle errors.
return null;
}
return (
<div>
<Input value={input} onChange={(e) => setInput(e.currentTarget.value)} placeholder="Enter a message" />
<br />
<Button type="submit" onClick={() => setMessage(input)}>
Submit
</Button>
<br />
<div>{loading ? <Spinner /> : reply}</div>
</div>
);
};