Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // -------------------------------------------------------- Generate LLM Stream Route
- import Replicate from "replicate";
- import { ReplicateStream, streamToResponse } from 'ai';
- import { NextApiRequest, NextApiResponse } from 'next';
- const replicate = new Replicate({ auth: process.env.REPLICATE_API_KEY });
- export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse
- ) {
- const { prompt } = await req.body as { prompt: string };
- const prediction = await replicate.predictions.create({
- version: "a52e56fee2269a78c9279800ec88898cecb6c8f1df22a6483132bea266648f00",
- input: {
- prompt: `You are a helpful ai that can complete chats, text and give good responses in a logical manner . Give me completion for this : ${prompt}`,
- // max_new_tokens: 256,
- },
- stream: true,
- });
- // Convert the response into a friendly text-stream
- const stream = await ReplicateStream(prediction);
- // Respond with the stream
- console.log("stream", stream) // stream ReadableStream { locked: false, state: 'readable', supportsBYOB: false }
- return streamToResponse(stream, res);
- }
- // -------------------------------------------------------- UI Compoennt
- 'use client'
- import React from 'react'
- import { type Content, EditorContent, useEditor } from '@tiptap/react'
- import StarterKit from '@tiptap/starter-kit'
- import Text from '@tiptap/extension-text'
- import TipTapMenuBar from './TipTapMenuBar'
- import { useDebounce } from '../../lib/useDebounce'
- import { useCompletion } from 'ai/react'
- export const runtime = 'experimental-edge';
- const TipTapEditor = () => {
- const [editorState, setEditorState] = React.useState('')
- const { complete , completion , stop } = useCompletion({
- api : 'api/replicateAPI/generateLLMStream',
- onResponse: res => {
- // trigger something when the response starts streaming in
- // e.g. if the user is rate limited, you can show a toast
- if (res.status === 429) {
- console.log('You are being rate limited. Please try again later.', res);
- }
- },
- onFinish: () => {
- // do something with the completion result
- console.log('Successfully generated completion!');
- },
- })
- const customText = Text.extend({
- addKeyboardShortcuts() {
- return {
- 'Shift-a': () => {
- const prompt = this.editor.getText().split(' ').slice(-30).join(' ')
- console.log(prompt)
- complete(prompt)
- return true;
- },
- }
- }
- })
- const editor = useEditor({
- autofocus: true,
- extensions: [StarterKit, customText],
- content: editorState,
- onUpdate: ({ editor }) => {
- setEditorState(editor.getHTML())
- },
- })
- const debouncedEditorState = useDebounce(editorState, 500)
- const lastCompletion = React.useRef("")
- React.useEffect(() => {
- console.log('completion', completion)
- if (!completion || !editor) return;
- const diff = completion.slice(lastCompletion.current.length);
- lastCompletion.current = completion;
- editor.commands.insertContent(diff);
- }, [completion, editor]);
- React.useEffect(() => {
- console.log('debouncedEditorState', debouncedEditorState)
- }, [debouncedEditorState])
- return (
- <>
- <div className=''>
- { editor && <TipTapMenuBar editor={editor}/>}
- </div>
- <div className='p-4 prose dark:prose-invert'>
- <EditorContent editor={editor} />
- </div>
- <div onClick={stop}>Button</div>
- <div>
- {completion}
- </div>
- </>
- )
- }
- export default TipTapEditor
Advertisement
Add Comment
Please, Sign In to add comment