0.0.3 • Published 8 months ago

@hackdance/agents-hooks v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

@hackdance/agents-hooks

A collection of react hooks for building AI powered UI's.

These hooks are meant to be used with the @hackdance/agents-core package.

Getting Started

pnpm add @hackdance/agents-hooks

use-json-stream

Hook for receiving safe to parse json from an agent stream.

Usage

"use client"

import { useState } from "react"

import { useJsonStream } from "@/hooks/use-json-stream"
import { PromptComposer } from "@/components/prompt-composer"
import { jokeCriticScema } from "@/ai/agents/joke-critic-agent"

export default function JokeCritic() {
  const [prompt, setPrompt] = useState("")
  const [response, setResponse] = useState({})

  const { startStream, stopStream, loading } = useJsonStream({
    onReceive: data => {
      setResponse(data)
    },
    onEnd: async ({ content }) => {
      setResponse(content)
    },
    schema: jokeCriticScema
  })

  const sendMessage = async () => {
    if (!prompt.length || loading) return

    try {
      startStream({
        prompt,
        url: "/api/ai/joke-critic",
        ctx: {}
      })
    } catch (e) {
      console.error(e)
    }
  }

  const handleInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
    setPrompt(event.target.value ?? "")
  }

  return (
    <div className="h-full flex flex-col justify-between py-4 overflow-hidden">
      <div className="p-8">
        <h2>Your joke score</h2>

        <strong>Critique</strong>
        <p>{response?.critique}</p>

        <strong>Funny Factor</strong>
        <p>{response?.funnyFactor}</p>

        <strong>Novelty</strong>
        <p>{response?.novelty}</p>

        <strong>Overall Score</strong>
        <p>{response?.overallScore}</p>
      </div>

      <div className="p-8">
        <PromptComposer
          placeholder="Tell me a joke..."
          loading={loading}
          onChange={handleInput}
          onSubmit={sendMessage}
          prompt={prompt}
        />
      </div>
    </div>
  )
}

Utils

Streaming JSON parser utility for parsing json streams as it becomes available.

 const functionParamaterSchema = z.object({
   name: z.string(),
   age: z.number()
 });


const functionStream = await fetch("https://api.openai.com/completion", {
  ...options,
  body: JSON.stringify({
    ...openAiConfig,
    functions: [{
      name: "My Function",
      description: "A function that returns a person's name and age.",
      paramaters: zodToJson(functionParamaterSchema)
    }]
  })
})

const argumentsStream = OAIResponseFnArgsParser(stream)
const parser = JsonStreamParser(schema);
argumentsStream?.pipeThrough(parser)

use-chat-stream

A hook for managing a conversation with an ai agent.

Usage

"use client"

import { useState } from "react"

import { useChatStream } from "@/hooks/use-chat-stream"
import { MessageList } from "@/components/message-list"
import { PromptComposer } from "@/components/prompt-composer"

export default function Chat({ conversation, updateConversation }) {
  const [prompt, setPrompt] = useState("")
  const ChatScrollerRef = useRef<HTMLDivElement>(null)

  const scrollToEnd = ({ now = false }: { now?: boolean }) => {
    ChatScrollerRef?.current?.scrollTo({
      top: ChatScrollerRef?.current?.scrollHeight,
      behavior: now ? "auto" : "smooth"
    })
  }

  const { startStream, messages, loading } = useChatStream({
    startingMessages: conversation?.messages,
    onBeforeStart: async () => {
      scrollToEnd({})
      setPrompt("")
    },
    onEnd: ({ messagePair, messages: latestMessages }) => {
      updateConversation({ newMessages: messagePair })
    }
  })

  const sendMessage = async () => {
    if (!prompt.length || loading) return

    try {
      startStream({
        prompt,
        url: "/api/ai/chat",
        ctx: {}
      })
    } catch (e) {
      console.error(e)
    }
  }

  const handleInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
    setPrompt(event.target.value ?? "")
  }

  return (
    <div className="h-full flex flex-col justify-between py-4 overflow-hidden">
      <div className=" overflow-y-auto p-8" ref={ChatScrollerRef}>
        <MessageList messages={messages} />
      </div>

      <div className="p-8">
        <PromptComposer
          loading={loading}
          onChange={handleInput}
          onSubmit={sendMessage}
          prompt={prompt}
        />
      </div>
    </div>
  )
}
0.0.3

8 months ago

0.0.2

8 months ago

0.0.1

8 months ago