From 2932c3381554c4f135e7b2948bba1d91578c518e Mon Sep 17 00:00:00 2001 From: Victor Forissier Date: Mon, 2 Sep 2024 15:26:27 +0200 Subject: [PATCH] docs: backup from Readme --- docs/v0.2.3/Auth/login.md | 40 ++++ .../anonymous-not-intended-for-production.md | 25 ++ .../login/custom-authentification-system.md | 38 +++ docs/v0.2.3/Auth/login/firebase.md | 49 ++++ .../v0.2.3/Auth/login/login-with-providers.md | 51 ++++ docs/v0.2.3/Auth/logout.md | 16 ++ .../v0.2.3/Auth/react-stripe-subscriptions.md | 125 ++++++++++ docs/v0.2.3/Auth/user.md | 23 ++ docs/v0.2.3/Client Libraries/javascript.md | 56 +++++ .../Client Libraries/react-use-polyfact.md | 11 + .../useagent-react-hook-1.md | 215 +++++++++++++++++ .../react-use-polyfact/usechat.md | 128 ++++++++++ .../react-use-polyfact/usepolyfire.md | 66 ++++++ docs/v0.2.3/Data/dataloaders.md | 91 ++++++++ docs/v0.2.3/Data/embeddings.md | 97 ++++++++ docs/v0.2.3/Data/kv-store.md | 33 +++ docs/v0.2.3/Get Started/basic-usage.md | 132 +++++++++++ docs/v0.2.3/Get Started/developer-console.md | 26 +++ docs/v0.2.3/Get Started/introduction.md | 58 +++++ docs/v0.2.3/Get Started/models-list.md | 31 +++ .../Get Started/new-project-rate-limit.md | 137 +++++++++++ docs/v0.2.3/Models/chatgpt-clone.md | 220 ++++++++++++++++++ docs/v0.2.3/Models/chats.md | 8 + docs/v0.2.3/Models/chats/getmessages.md | 29 +++ docs/v0.2.3/Models/chats/new-chat.md | 103 ++++++++ docs/v0.2.3/Models/chats/sendmessage.md | 57 +++++ docs/v0.2.3/Models/generate-image.md | 46 ++++ docs/v0.2.3/Models/generate-with-types.md | 38 +++ docs/v0.2.3/Models/generate.md | 8 + docs/v0.2.3/Models/generate/generate-1.md | 56 +++++ docs/v0.2.3/Models/generate/infos.md | 89 +++++++ docs/v0.2.3/Models/generate/stream.md | 32 +++ docs/v0.2.3/Models/generate/web.md | 138 +++++++++++ docs/v0.2.3/Models/other-chat-overvire.md | 135 +++++++++++ docs/v0.2.3/Models/text-generation.md | 73 ++++++ docs/v0.2.3/Models/text-to-speech.md | 80 +++++++ docs/v0.2.3/Models/transcribe.md | 40 ++++ docs/v0.2.3/Prompt/system-prompts-alias.md | 44 ++++ .../React Components/auto-complete-input.md | 28 +++ .../auto-complete-textarea.md | 26 +++ docs/v0.2.3/React Components/chat.md | 72 ++++++ docs/v0.2.3/React Components/chat/chat-1.md | 99 ++++++++ docs/v0.2.3/React Components/chat/prompt.md | 73 ++++++ docs/v0.2.3/React Components/chat/root.md | 50 ++++ docs/v0.2.3/React Components/chat/sidebar.md | 191 +++++++++++++++ docs/v0.2.3/React Components/chat/test.md | 30 +++ .../React Components/chat/usechatcontext.md | 211 +++++++++++++++++ docs/v0.2.3/React Components/imagegenerate.md | 37 +++ docs/v0.2.3/React Components/loginui.md | 49 ++++ docs/v0.2.3/React Components/payments.md | 141 +++++++++++ .../v0.2.3/React Components/text-generated.md | 41 ++++ .../v0.2.3/React Components/text-summarize.md | 41 ++++ docs/v0.2.3/React Components/text-summary.md | 43 ++++ 53 files changed, 3776 insertions(+) create mode 100644 docs/v0.2.3/Auth/login.md create mode 100644 docs/v0.2.3/Auth/login/anonymous-not-intended-for-production.md create mode 100644 docs/v0.2.3/Auth/login/custom-authentification-system.md create mode 100644 docs/v0.2.3/Auth/login/firebase.md create mode 100644 docs/v0.2.3/Auth/login/login-with-providers.md create mode 100644 docs/v0.2.3/Auth/logout.md create mode 100644 docs/v0.2.3/Auth/react-stripe-subscriptions.md create mode 100644 docs/v0.2.3/Auth/user.md create mode 100644 docs/v0.2.3/Client Libraries/javascript.md create mode 100644 docs/v0.2.3/Client Libraries/react-use-polyfact.md create mode 100644 docs/v0.2.3/Client Libraries/react-use-polyfact/useagent-react-hook-1.md create mode 100644 docs/v0.2.3/Client Libraries/react-use-polyfact/usechat.md create mode 100644 docs/v0.2.3/Client Libraries/react-use-polyfact/usepolyfire.md create mode 100644 docs/v0.2.3/Data/dataloaders.md create mode 100644 docs/v0.2.3/Data/embeddings.md create mode 100644 docs/v0.2.3/Data/kv-store.md create mode 100644 docs/v0.2.3/Get Started/basic-usage.md create mode 100644 docs/v0.2.3/Get Started/developer-console.md create mode 100644 docs/v0.2.3/Get Started/introduction.md create mode 100644 docs/v0.2.3/Get Started/models-list.md create mode 100644 docs/v0.2.3/Get Started/new-project-rate-limit.md create mode 100644 docs/v0.2.3/Models/chatgpt-clone.md create mode 100644 docs/v0.2.3/Models/chats.md create mode 100644 docs/v0.2.3/Models/chats/getmessages.md create mode 100644 docs/v0.2.3/Models/chats/new-chat.md create mode 100644 docs/v0.2.3/Models/chats/sendmessage.md create mode 100644 docs/v0.2.3/Models/generate-image.md create mode 100644 docs/v0.2.3/Models/generate-with-types.md create mode 100644 docs/v0.2.3/Models/generate.md create mode 100644 docs/v0.2.3/Models/generate/generate-1.md create mode 100644 docs/v0.2.3/Models/generate/infos.md create mode 100644 docs/v0.2.3/Models/generate/stream.md create mode 100644 docs/v0.2.3/Models/generate/web.md create mode 100644 docs/v0.2.3/Models/other-chat-overvire.md create mode 100644 docs/v0.2.3/Models/text-generation.md create mode 100644 docs/v0.2.3/Models/text-to-speech.md create mode 100644 docs/v0.2.3/Models/transcribe.md create mode 100644 docs/v0.2.3/Prompt/system-prompts-alias.md create mode 100644 docs/v0.2.3/React Components/auto-complete-input.md create mode 100644 docs/v0.2.3/React Components/auto-complete-textarea.md create mode 100644 docs/v0.2.3/React Components/chat.md create mode 100644 docs/v0.2.3/React Components/chat/chat-1.md create mode 100644 docs/v0.2.3/React Components/chat/prompt.md create mode 100644 docs/v0.2.3/React Components/chat/root.md create mode 100644 docs/v0.2.3/React Components/chat/sidebar.md create mode 100644 docs/v0.2.3/React Components/chat/test.md create mode 100644 docs/v0.2.3/React Components/chat/usechatcontext.md create mode 100644 docs/v0.2.3/React Components/imagegenerate.md create mode 100644 docs/v0.2.3/React Components/loginui.md create mode 100644 docs/v0.2.3/React Components/payments.md create mode 100644 docs/v0.2.3/React Components/text-generated.md create mode 100644 docs/v0.2.3/React Components/text-summarize.md create mode 100644 docs/v0.2.3/React Components/text-summary.md diff --git a/docs/v0.2.3/Auth/login.md b/docs/v0.2.3/Auth/login.md new file mode 100644 index 0000000..8247e2e --- /dev/null +++ b/docs/v0.2.3/Auth/login.md @@ -0,0 +1,40 @@ +--- +title: "login" +slug: "login" +excerpt: "Login users with Polyfire Auth" +hidden: false +createdAt: "Wed Sep 27 2023 07:29:51 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:49 GMT+0000 (Coordinated Universal Time)" +--- +> πŸ“˜ Auth is required +> +> All the components and functions in the SDK require you to connect your users to Polyfire Auth. +> +> Because all calls to the Polyfire API use LLMs (and therefore cost money) or access user data, the client needs some kind of secured authentification. +> +> You don't need to authenticate your users entirely through Polyfire (e.g. we can authenticate your Firebase or Supabase user tokens). If you need a custom auth provider integrated, [tell us on Discord](https://discord.polyfire.com). + +Login users client-side to create unique user sessions. + +- Works with providers "Google" and "GitHub" but also "Firebase" (see below). +- Must be called to use _models_ and _data_ modules client-side. + +```typescript +export declare function login(input: LoginFunctionInput, projectOptions: { + project: string; + endpoint: string; +}): Promise; +``` + +## Types + +```typescript +type SimpleProvider = "github" | "google"; +type LoginWithFirebaseInput = { + token: string; + provider: "firebase"; +}; +type LoginFunctionInput = SimpleProvider | { + provider: SimpleProvider; +} | LoginWithFirebaseInput; +``` diff --git a/docs/v0.2.3/Auth/login/anonymous-not-intended-for-production.md b/docs/v0.2.3/Auth/login/anonymous-not-intended-for-production.md new file mode 100644 index 0000000..e121fce --- /dev/null +++ b/docs/v0.2.3/Auth/login/anonymous-not-intended-for-production.md @@ -0,0 +1,25 @@ +--- +title: "Anonymous (Not intended for Production)" +slug: "anonymous-not-intended-for-production" +excerpt: "" +hidden: false +createdAt: "Mon Oct 16 2023 12:05:20 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:49 GMT+0000 (Coordinated Universal Time)" +--- +To simplify your onboarding with polyfire, we added an "anonymous" login method. + +It must first be activated in the dashboard in your project settings. + +**After that, logging in should be automatic.** + +You can also try to call it manually (after a logout for example) with: + +```js Javascript +login({ provider: "anonymous" }); +``` + +If you want to simulate multiple users, the login function also provides you with the ability to add an email to differentiate them like this: + +```js Javascript +login({ provider: "anonymous", email: "user@example.com" }); +``` diff --git a/docs/v0.2.3/Auth/login/custom-authentification-system.md b/docs/v0.2.3/Auth/login/custom-authentification-system.md new file mode 100644 index 0000000..c2d195f --- /dev/null +++ b/docs/v0.2.3/Auth/login/custom-authentification-system.md @@ -0,0 +1,38 @@ +--- +title: "Custom Authentification System" +slug: "custom-authentification-system" +excerpt: "" +hidden: false +createdAt: "Mon Oct 16 2023 11:41:24 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:49 GMT+0000 (Coordinated Universal Time)" +--- +If you are already using a custom authentification system and want to link Polyfire to your authentification system, you can use the "custom" provider. + +You will need to sign a Json Web Token using the RSA/RS256 algorithm and input your public key in the PEM format in the dashboard in the "Custom Auth Public Key" field of your project's settings. + +Your JWT must contains these fields: + +- `iss`: Your project alias +- `aud`: must be:`polyfire_custom_auth_api` +- `sub`: The id of the user you want to identify. It can be any string as long as it is unique to the user. + +For example. Assuming the public key is already added in the dashboard "Custom Auth Public Key" field, somewhere in server-side code: + +```js Javascript + +const token = jwt.sign( + { + iss: projectAlias, + aud: "polyfire_custom_auth_api", // Don't change this string + sub: userID, + }, + privateKey, // Leaking this key would allow to connect as any user. Make sure it's never sent client-side. + { algorithm: "RS256" } +); +``` + +The generated token can then be used client-side in the login function like this: + +```js Javascript +login({ provider: "custom", token: theTokenGeneratedBefore }) +``` diff --git a/docs/v0.2.3/Auth/login/firebase.md b/docs/v0.2.3/Auth/login/firebase.md new file mode 100644 index 0000000..dc07d7d --- /dev/null +++ b/docs/v0.2.3/Auth/login/firebase.md @@ -0,0 +1,49 @@ +--- +title: "Firebase" +slug: "firebase" +excerpt: "" +hidden: false +createdAt: "Mon Oct 16 2023 11:40:36 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:49 GMT+0000 (Coordinated Universal Time)" +--- +## Add your Firebase Project ID to your project + +Before being able to use firebase as a login method you first need to link your Firebase project to your polyfire project. + +You can find your Firebase Project ID in your project settings in the firebase console . Choose your project, click on the gear icon in the top left corner and click on "Project Settings". Your Project ID will be displayed among other infos. + +To link it to your Polyfire project, go on and choose your project. When you are in the project detail page, click on the Edit button and add your Firebase Project ID before saving. + +## Setup the Firebase login + +If you didn't do it already, follow this tutorial to setup the login with firebase: + +## Link your Firebase User Session to Polyfire + +You can set the provider to firebase and send a firebase token to the login function parameter. To get a firebase token, you can use the `getIdToken()` method of the firebase user object. + +For example: + +```js Javascript +const userCredentials = await signInWithEmailAndPassword( + auth, + "john.doe@example.com", + "correct_horse_battery_staple" +); + +const user = userCredentials.user; + +const firebaseToken = await user.getIdToken(); + +const polyfire = PolyfireClientBuilder({ project: "your_project_alias" }) +await polyfire.auth.login({ provider: "firebase", token: firebaseToken }) + +// You can now use the Polyfire Client: +const helloWorldHaiku = await polyfire.generate("Write me a hello world haiku"); + +console.log(helloWorldHaiku); +``` + +> πŸ“˜ With the usePolyfire React Hook +> +> Using the usePolyfire React Hook it would work the same except that you would be importing the _auth_ module from usePolyfire instead of creating a client object like higher up. diff --git a/docs/v0.2.3/Auth/login/login-with-providers.md b/docs/v0.2.3/Auth/login/login-with-providers.md new file mode 100644 index 0000000..3a5a8b3 --- /dev/null +++ b/docs/v0.2.3/Auth/login/login-with-providers.md @@ -0,0 +1,51 @@ +--- +title: "OAuth Providers" +slug: "login-with-providers" +excerpt: "" +hidden: false +createdAt: "Wed Sep 27 2023 07:17:47 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:41:44 GMT+0000 (Coordinated Universal Time)" +--- +For Polyfire to work client-side, **you need to setup unique user sessions**. That way, each user of your app will have a custom, rate-limited, API token and can use your app according to the restrictions you give them. + +To do that you can use our login functions, from the _auth_ module. + +```jsx +import React from 'react'; +import { usePolyfire } from 'polyfire-js/hooks'; + +function App() { + const { auth } = usePolyfire(); + const { login, status } = auth; + + if (status == 'loading') { + return ( +
Loading...
+ ) + } else if (status == 'authenticated') { + return ( +
We already logged in!
+ ) + } else if (status == 'unauthenticated') { + return ( + + ) + } else { + return
+ } +} + +export default App; +``` + +# Linking pre-existing auth system + +If you have Firebase Auth setup. Pass in your JWT as shown [in that tutorial](doc:signin-firebase). If you want integrations to other auth providers:[message us on our Discord](https://www.polyfire.com/discord). + +You can also connect your own auth system [by doing a custom auth.](doc:custom-authentification-system) + +# Providers Available + +The sign in providers available are GitHub, Google, Microsoft (Azure) and Firebase (passing your Firebase JWT). + +[Reach out on Discord if you want more.](discord.polyfire.com) diff --git a/docs/v0.2.3/Auth/logout.md b/docs/v0.2.3/Auth/logout.md new file mode 100644 index 0000000..d7f01a9 --- /dev/null +++ b/docs/v0.2.3/Auth/logout.md @@ -0,0 +1,16 @@ +--- +title: "logout" +slug: "logout" +excerpt: "" +hidden: false +createdAt: "Wed Sep 27 2023 07:32:37 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:48 GMT+0000 (Coordinated Universal Time)" +--- +Ends user session and cleans cache. + +- Doesn't return anything. +- Will require user to re-authenticate user to use API modules. (models, data, etc). + +```typescript +export declare function logout(): Promise; +``` diff --git a/docs/v0.2.3/Auth/react-stripe-subscriptions.md b/docs/v0.2.3/Auth/react-stripe-subscriptions.md new file mode 100644 index 0000000..1626ea0 --- /dev/null +++ b/docs/v0.2.3/Auth/react-stripe-subscriptions.md @@ -0,0 +1,125 @@ +--- +title: "Stripe Integration" +slug: "react-stripe-subscriptions" +excerpt: "" +hidden: false +createdAt: "Mon Sep 11 2023 09:26:19 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Wed Nov 29 2023 15:37:38 GMT+0000 (Coordinated Universal Time)" +--- +# 1. Initialize the Stripe webhook + +- You first need a Polyfire project. You can [create one here](https://beta.polyfire.com/project/new). +- Go to _Auth > Payments_ on your Polyfire dashboard. +- Copy the webhook URL for one of the next steps. + +# 2. Configure User Rate Limits + +- **Free User Rate Limit** : + Set a dollar threshold for free app usage under `Free User Rate Limit`. +- **Premium User Rate Limit **: + Assign a higher dollar limit for premium users in the `Premium User Rate Limit`. +- **Developer Rate Limit Testing**: + To test rate limits, toggle `Dev has rate limit?` to 'On' in development. + Adjust or disable this in production. + Now save your settings by clicking on the "Save" button. + +# 2. Add the webhook on the Stripe dashboard + +- Add the generated webhook [here on Stripe](https://dashboard.stripe.com/webhooks) . +- Configure the webhook to be sent on all events (You can also select manually theses events: _customer.created, customer.updated, checkout.session.completed, customer.subscription.created, customer.subscription.updated and customer.subscription.deleted_) + +# 3. Create a payment link + +- Create a new Stripe payment link [here](https://dashboard.stripe.com/payment-links/create) on your Stripe dashboard. +- In the product field, select Add new product, give it the name, image, description and price you want. Set the payment to Recurring and select Monthly in billing period. +- In the After payment tab, choose Don't show confirmation page and set the address of your app. + _NOTE: for localhost, use , you will need this address instead of http\://localhost in your tests to stay connected after the payment._ +- Create the link and copy it. + +# 4. Add the paywall to your app + +For this part, I am going to use the chat we made in this tutorial: [Making ChatGPT](doc:chatgpt-clone) + +We create a component that will be displayed instead of the chat if this user didn't pay yet. Don't forget to replace `` by your payment link. + +Polyfire uses the userID as the identifier to know which user paid a subscription, this is why we use the client_reference_id query parameter. + +```jsx +function Paywall({ userId }: { userId: string }) { + return ( + + ); +} + +``` + +We can then modify the App component to get the userId and add the paywall when the rate limit has been reached - which should be right away in this case since the rate limit is 0. + +```jsx +function App() { + const polyfire = usePolyfire(); + + const { login, status, user } = polyfire.auth; + const { getAuthID, usage } = user; + + const { Chat } = polyfire.utils; + + + const [chat, setChat] = useState(); + const [paywall, setPaywall] = useState(false); + const [userId, setUserId] = useState(); + const [messages, setMessages] = useState< + { is_user_message: boolean; content: string }[] + >([]); + + useEffect(() => { + if (status === "authenticated") { + const updateUsage = async () => { + const userId = await getAuthID(); + setUserId(userId); + + const userUsage = await usage(); + if (userUsage.rateLimit === undefined || userUsage.rateLimit === null) { + setPaywall(false); + } else { + setPaywall(userUsage.rateLimit <= userUsage.usage); + } + + setChat(new Chat()); + }; + + updateUsage(); + } + }, [status]); + + if (status === "unauthenticated") { + return ( + + ); + } + + if (chat && !paywall) { + return ( + { + await chat.sendMessage(message); + setMessages((await chat.getMessages()).reverse()); + }} + /> + ); + } + + if (paywall && userId && status !== "loading") { + return ; + } + + return
Loading...
; +} +``` diff --git a/docs/v0.2.3/Auth/user.md b/docs/v0.2.3/Auth/user.md new file mode 100644 index 0000000..95b1186 --- /dev/null +++ b/docs/v0.2.3/Auth/user.md @@ -0,0 +1,23 @@ +--- +title: "user" +slug: "user" +excerpt: "" +hidden: false +createdAt: "Wed Sep 27 2023 07:39:48 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:33:49 GMT+0000 (Coordinated Universal Time)" +--- +User object with Auth and Token IDs. + +- Give you access to a unique userID +- Useful to mesure rateLimit and user's usage if you want to trigger a paywall / payment flow. + +```typescript +export type UserClient = { + usage: () => Promise<{ + usage: number; + rateLimit?: number; + }>; + getAuthID: () => Promise; + getToken: () => Promise; +}; +``` diff --git a/docs/v0.2.3/Client Libraries/javascript.md b/docs/v0.2.3/Client Libraries/javascript.md new file mode 100644 index 0000000..b0ba99e --- /dev/null +++ b/docs/v0.2.3/Client Libraries/javascript.md @@ -0,0 +1,56 @@ +--- +title: "Javascript" +slug: "javascript" +excerpt: "" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 12 2023 08:49:03 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 01:23:26 GMT+0000 (Coordinated Universal Time)" +--- +> **_NOTE:_** +> +> _If you're using React, we recommend to use the [usePolyfire hook](doc:usepolyfire)_ + +## With NPM + +First install the Polyfire SDK: + +```Text Bash +npm install polyfire-js +``` + +Import the `PolyfireClientBuilder` object + +```javascript +import PolyfireClientBuilder from "polyfire-js"; +``` + +## Without NPM + +You can initialize Polyfire by importing the browser minified script: + +```html + +``` + +The `PolyfireClientBuilder` object is added as a global variable in the window object + +## Using the _polyfire_ Object + +You can check if the user is already connected by using the `polyfire.auth.init()` function + +If they aren't we'll have to use the `polyfire.auth.login(provider: string)` method to connect them first + +```js Javascript +const polyfire = PolyfireClientBuilder({ project: "your_project_alias" }) + +const isAuthenticated = await polyfire.auth.init(); +if (!isAuthenticated) { + await polyfire.auth.login("github") +} + +const helloWorld = await polyfire.models.generate("Write me a hello world haiku"); +console.log(helloWorld); +``` diff --git a/docs/v0.2.3/Client Libraries/react-use-polyfact.md b/docs/v0.2.3/Client Libraries/react-use-polyfact.md new file mode 100644 index 0000000..c2b009d --- /dev/null +++ b/docs/v0.2.3/Client Libraries/react-use-polyfact.md @@ -0,0 +1,11 @@ +--- +title: "React" +slug: "react-use-polyfact" +excerpt: "" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Mon Sep 11 2023 09:04:43 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Wed Oct 18 2023 20:57:45 GMT+0000 (Coordinated Universal Time)" +--- diff --git a/docs/v0.2.3/Client Libraries/react-use-polyfact/useagent-react-hook-1.md b/docs/v0.2.3/Client Libraries/react-use-polyfact/useagent-react-hook-1.md new file mode 100644 index 0000000..6aaaed6 --- /dev/null +++ b/docs/v0.2.3/Client Libraries/react-use-polyfact/useagent-react-hook-1.md @@ -0,0 +1,215 @@ +--- +title: "useAgent" +slug: "useagent-react-hook-1" +excerpt: "The `useAgent` hook is a Agent AI tool for simulating the cognitive steps someone might take when answering a question." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 12 2023 13:59:46 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Mon Oct 23 2023 11:12:28 GMT+0000 (Coordinated Universal Time)" +--- +## Importing the Hook + +To use the `useAgent` hook, first, ensure that it's imported into your React component. + +```javascript +import { useAgent } from 'polyfire-js/hooks; +``` + +## Actions + +To enable the agent to perform specific tasks, you need to define the `actions` that the agent will use. Each action is represented as an object with a `name`, `description`, `callback`, and `example`, all are required. + +The action type is: + +```ts Typescript +{ + name: string, // Action name + description: string, // Description of what the action does + callback: (param: string) => Promise, // This is the function that'll be executed for this action + example: { + question: string, + process: [ + { + thought: string, + action: string, + observation: string, + } + ] + } +} +``` + +### Writing the Examples + +Each action will need to have some examples of how it is used. This is necessary for the LLM to understand what the action actually does. + +For example, a basic search function that allows the Agent to search on the web could have these examples: + +```json JSON +[ + { + question: + 'Musician and satirist Allie Goertz wrote a song about the "The Simpsons" character Milhouse, who Matt Groening named after who?', + process: [ + { + thought: + 'The question simplifies to "The Simpsons" character Milhouse is named after who. I only need to search Milhouse and find who it is named after.', + action: "Search[Milhouse]", + observation: + "Milhouse Mussolini Van Houten is a recurring character in the Fox animated television series The Simpsons voiced by Pamela Hayden and created by Matt Groening.", + }, + { + thought: + 'The paragraph does not tell who Milhouse is named after, maybe I can look up "The Simpsons Milhouse named after".', + action: "Search[The Simpsons Milhouse named after]", + observation: + "Milhouse was named after U.S. president Richard Nixon, whose middle name was Milhous.", + }, + { + thought: + "Milhouse was named after U.S. president Richard Nixon, so the answer is Richard Nixon.", + action: "Finish[Richard Nixon]", + observation: "", + }, + ], + } +] +``` + +## UseAgent + +Now that we have the actions defined, we can call useAgent with the action list. The second parameter is a `GenerationOptions` as defined in [generate](ref:generate) + +> **NOTE:** +> +> In our tests, the agents were not working correctly if we didn't use GPT-4. Using GPT-3.5 will make them hallucinate or forget actions as well as getting stuck in endless loops. +> +> You can still test it with other models but you've been warned. + +```js +const { start, stop } = useAgent(actions, { + model: "gpt-4", + provider: "openai", +}); +``` + +### Start the agent + +After the agent has been initialized with all its action, you can use the `start` function to give it a task to accomplish. + +``` +function start(question: string, progress?: (step: number, result: string) => void): Promise +``` + +If you want to log/use the reasoning of the agent, you can use the progress function. + +If you want to stop the agent early you can call the function `stop()`. + +## Example Usage + +Here's how you might use the `useAgent` hook in a component: + +```javascript +import { useState } from "react"; +import { usePolyfire, useAgent, DefinitionAction } from "polyfire-js/hooks"; + +export const examples = [ + { + question: + 'Musician and satirist Allie Goertz wrote a song about the "The Simpsons" character Milhouse, who Matt Groening named after who?', + process: [ + { + thought: + 'The question simplifies to "The Simpsons" character Milhouse is named after who. I only need to search Milhouse and find who it is named after.', + action: "Search[Milhouse]", + observation: + "Milhouse Mussolini Van Houten is a recurring character in the Fox animated television series The Simpsons voiced by Pamela Hayden and created by Matt Groening.", + }, + { + thought: + 'The paragraph does not tell who Milhouse is named after, maybe I can look up "The Simpsons Milhouse named after".', + action: "Search[The Simpsons Milhouse named after]", + observation: + "Milhouse was named after U.S. president Richard Nixon, whose middle name was Milhous.", + }, + { + thought: + "Milhouse was named after U.S. president Richard Nixon, so the answer is Richard Nixon.", + action: "Finish[Richard Nixon]", + observation: "", + }, + ], + } +]; + + +export default function App() { + const { auth: { login }, models } = usePolyfire(); + + const search = async (request: string) => { + const page = await models?.generate(request, { + web: true, + }); + + return page; + }; + + + const actions: DefinitionAction[] = [ + { + name: "Search", + description: "Use this action if you have to search on the web", + callback: search, + example: examples[0], + } + ]; + + const { start, stop } = useAgent(actions, { + provider: "openai", + model: "gpt-4", + }); + + const [answer, setAnswer] = useState(null); + const [status, setStatus] = useState("idle"); // 'idle', 'processing', 'completed' + + const getAnswer = async () => { + setStatus("processing"); + + try { + const response = await start( + "How is jean-baptiste dutrou-bordier ?", + (step, result) => { + console.log(`Step: ${step}, Result: ${result}`); + } + ); + + setAnswer(response); + setStatus("completed"); + } catch (error) { + console.error("An error occurred:", error); + setStatus("idle"); + } + }; + + const loginButton = login && ( + + ); + + const agentBox = ( +
+ + {status === "processing" &&

Processing...

} + {status === "completed" && answer &&

Answer: {answer}

} + +
+ ); + + return
{login ? loginButton : agentBox}
; +} + + +``` diff --git a/docs/v0.2.3/Client Libraries/react-use-polyfact/usechat.md b/docs/v0.2.3/Client Libraries/react-use-polyfact/usechat.md new file mode 100644 index 0000000..9e831b1 --- /dev/null +++ b/docs/v0.2.3/Client Libraries/react-use-polyfact/usechat.md @@ -0,0 +1,128 @@ +--- +title: "useChat" +slug: "usechat" +excerpt: "" +hidden: false +createdAt: "Tue Sep 12 2023 08:28:54 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Dec 29 2023 15:03:38 GMT+0000 (Coordinated Universal Time)" +--- +## Importing the Hook + +```js Javascript +import { useChat } from "polyfire-js/hooks"; +``` + +## Using the useChat hook + +```ts Typescript +function useChat(): ChatInstance +``` + +`useChat` doesn't take any parameter returns a `ChatInstance` object containing all the necessary informations and functions to interact with the chat as defined below: + +```ts Typescript +type Message = { + id: string | null; // The current question/answer will be null. An id will be set to it at the end of the generation + chat_id: string; + is_user_message: boolean; + content: string; + created_at: string | null; // The current question/answer will be null. The date will be set at the end of the generation +} + +type ChatInfos = { + created_at: string; + id: string; + latest_message_content: string; + latest_message_created_at: string; + name: string | null; + system_prompt: string | null; + system_prompt_id: string | null; + user_id: string; +} + +type ChatBase = { + data: T | undefined; + error: string | undefined; + loading: boolean; +} + +type Chats = ChatBase +type ChatHistory = ChatBase +type ChatAnswer = ChatBase + +type ChatUtils = { + deleteChat: (chatId: string) => Promise; + renameChat: (chatId: string, name: string) => Promise; + resetChat: () => void; + selectChat: (chatId: string) => Promise; + sendMessage: (message: string) => Promise; +}; + +type ChatInstance = { + answer: ChatAnswer; + chat: ChatInfos | undefined; + chats: Chats; + history: ChatHistory; + utils: ChatUtils; +} +``` + +To send a new message, use the `sendMessage` function. + +```ts Typescript +function sendMessage(message: string): void; +``` + +The message will be added to messages and the answer from the LLM will be updated token by token until the answer have been fully generated. + +During the generation, loading will be set to `true`, allowing you to disable the send button. + +`answer.loading` is also set to true during the usePolyfire initialization. + +> :warning: **Using sendMessage when answer.loading is true will throw an error** + +## Example Usage + +The [How to make a clone of ChatGPT](doc:chatgpt-clone) app could be simplified with this hook: + +```js Javascript +function App() { + const { + auth: { login, status }, + } = usePolyfire(); + const { + history: { data: messages }, + utils: { onSendMessage: sendMessage }, + answer: { loading }, + } = useChat(); + + return ( + <> + {status === "unauthenticated" ? ( +
+

+ Don't forget to change the project slug in src/index.tsx +

+

+ After that you will be able to{" "} + +

+
+ ) : status === "authenticated" ? ( + + ) : ( + "Loading..." + )} + + ); +} +``` diff --git a/docs/v0.2.3/Client Libraries/react-use-polyfact/usepolyfire.md b/docs/v0.2.3/Client Libraries/react-use-polyfact/usepolyfire.md new file mode 100644 index 0000000..3358564 --- /dev/null +++ b/docs/v0.2.3/Client Libraries/react-use-polyfact/usepolyfire.md @@ -0,0 +1,66 @@ +--- +title: "usePolyfire" +slug: "usepolyfire" +excerpt: "Polyfire provides a hook to simplify the login process of your users in React." +hidden: false +createdAt: "Tue Sep 12 2023 08:46:37 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Mon Nov 27 2023 06:34:25 GMT+0000 (Coordinated Universal Time)" +--- +> **_NOTE:_** +> +> _The usePolyfire hook is a React Hook_ +> +> _If you're not using React, please follow this page instead: [Importing polyfire](doc:javascript)_ + +## Importing Polyfire + +First install the Polyfire SDK: + +```bash Bash +npm install polyfire-js +``` + +## Usage + +### PolyfireProvider + +You will need to wrap your app in the Polyfire Provider to be able to use the usePolyfire hook. Pass your project id to the PolyfireProvider + +```jsx Javascript +root.render( + + + +); +``` + +### Hook: usePolyfire + +The usePolyfire hook exports a client with all the Polyfire functions, to use most of them you will first need to login. The authentification functions are exported like this: + +```js Javascript +const { auth: { login, logout, status }, models: { generate } } = usePolyfire(); +``` + +All of the functions except the login function requires the user to be authenticated before calling them. You can check whether you're authenticated with `status`. `status` can be `authenticated`, `unauthenticated` and `loading`. + +```js Javascript +if (status === "authenticated") { + const haiku = await generate("Generate a hello world haiku"); + console.log(haiku); +} +``` + +The login function takes the login provider as a parameter. + +```jsx Javascript + +``` + +**WARNING: For now, the only login provider available are GitHub, Google [and Firebase](doc:signin-firebase), we will add more in the future** + +To logout, use the logout function + +```jsx Javascript + +``` diff --git a/docs/v0.2.3/Data/dataloaders.md b/docs/v0.2.3/Data/dataloaders.md new file mode 100644 index 0000000..caf7b6e --- /dev/null +++ b/docs/v0.2.3/Data/dataloaders.md @@ -0,0 +1,91 @@ +--- +title: "DataLoaders" +slug: "dataloaders" +excerpt: "" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 12 2023 08:33:18 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Mon Nov 06 2023 10:35:43 GMT+0000 (Coordinated Universal Time)" +--- +Data Loaders are designed to make it easy to send context to a LLM. + +The Data Loaders are built on top of memories, this means the Key Points of the [Embeddings](ref:embeddings) feature also applies to it. _TLDR; it's not made for summarizing documents, it's best use is for search._ + +## Using dataloaders + +You can send your dataloaders in the `data` field of the generationOption. + +For example, here's how you would use the `AudioLoader` dataloader: + +```js Javascript +import { AudioLoader } from "polyfire-js"; + +// In React: +const { models: { generate } } = usePolyfire(); +// In other environments: +const { models: { generate } } = polyfire; + +const audioStream = await fetch("https://storage.googleapis.com/polyfact-docs-storage/secret.mp3"); + +if (audioStream?.body) { + const answer = await generate("What is the secret ?", { + data: AudioLoader(audioStream.body), + }); + + console.log(answer); // It should give you something like "The secret is banana42" +} +``` + +We already expose 3 simple dataloaders `AudioLoader`, `TextFileLoader` and `StringLoader`: + +```ts Typescript +// TextFileLoader is used to load content from a raw text file (Buffer or Stream) +function TextFileLoader(file: FileInput, maxTokenPerChunk = 100): Loader; + +// AudioLoader is used to load content from an audio file (Buffer or Stream, the formats are the ones supported by transcribe) +function AudioLoader(file: FileInput, maxTokenPerChunk = 100): Loader; + +// StringLoader is used to load content directly from a string +function StringLoader(str: string, maxTokenPerChunk = 100): Loader; +``` + +## Implementing a new dataloader + +Under the hood, a dataloader is a function that takes a embedding collection and loads some data to it. + +The dataloader must be of the type LoaderFunction. + +```ts Typescript +type LoaderFunction = (embeddings: Embeddings, clientOptions: InputClientOptions) => Promise; +``` + +But we in most cases we can use the StringLoader to implement your own dataLoader without having to manage the Embeddings and chunking of the data ourselves. + +For example, let's imagine we want to implement a dataloader that just takes an URL and load the raw html content of the page to the context: + +```js Typescript +function URLLoader(url: string, maxTokenPerChunk = 100): LoaderFunction { + return async function loadURLContentIntoMemory(...args) { + const response = await fetch(url); + const content = await response.text(); + + await StringLoader(content, maxTokenPerChunk)(...args); + }; +} +``` + +We can now use our URLLoader by sending it to the generate function: + +```js Javascript +const answer = await generate("your_question", { + data: URLLoader("your_url_with_infos_about_your_subject") +}); +``` + +> **NOTE:** +> +> This naive implementation of URLLoader might not be optimal, especially on modern websites since it takes the raw html, there's a lot of noise. A better implementation would use . +> +> Note that we already have a special option to allow to search the web for more context. See [Web](ref:web) diff --git a/docs/v0.2.3/Data/embeddings.md b/docs/v0.2.3/Data/embeddings.md new file mode 100644 index 0000000..bf4cf24 --- /dev/null +++ b/docs/v0.2.3/Data/embeddings.md @@ -0,0 +1,97 @@ +--- +title: "Embeddings" +slug: "embeddings" +excerpt: "The embeddings are a simple way to create a long term memory and simplify the use of extracted information." +hidden: false +createdAt: "Mon Sep 11 2023 08:57:33 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Mon Mar 04 2024 07:11:34 GMT+0000 (Coordinated Universal Time)" +--- +# Overview + +1. Embeddings are a **data format using vectors** to store information in a way that can be **searched based on its semantic meaning** +2. Calling the `Embeddings()` class creates a **vector index** you can add data to +3. Large inputs are **automatically split up** in chunks of about 512 tokens and added to the index +4. When **calling a LLM** with the embeddings index ID, **Polyfire automatically queries the most similar data** in your index and inject it in the LLM call as context + +# Simple example + +```javascript +// In React +const { data: { Embeddings } } = usePolyfire(); +// In other environments: +const { data: { Embeddings } } = polyfire; + +const index = Embeddings(); +indexId = index.getId() +embeddings.add("The secret word is: banana42"); +const secret = await polyfire.generate("What's the secret?", { embeddingsId: indexId }); +console.log(secret); // Outputs: The secret word is "banana42". +``` + +# Embeddings() class + +## Class prototype + +```typescript +type EmbeddingsOptions = { + id?: string, // This cannot be set at the same time as public since it gets an existing embedding index instead of creating a new one. + public?: boolean, // Whether the content of your new embedding index should be accessible accross your project or restricted to a single user. Default is false. +} | string; + +function Embeddings(options?: EmbeddingsOptions): embeddings; +async function embeddings.getId(): Promise; +async function embeddings.add(input: string): Promise; +async function embeddings.search(input: string): Promise<{ content: string, similarity: number }[]> +``` + +## New index + +To create a new index, import the `Embedding` class from the `data` Polyfire module and instantiate it + +```typescript +import { data } = polyfireClient; +const { Embeddings } = data; + +const index = Embeddings() +``` + +## Index ID + +To get the ID of an embeddings index, call the `getId()` function + +```javascript +const id = await index.getId(); +console.log(id); // Outputs the ID of the embedding index +``` + +## Retrieve an index + +Pass an embeddings ID in options to retrieve previously created indexes + +```javascript +const existingIndex = Embeddings("yourEmbeddingsIndexId"); +// or +const existingIndex = Embeddings({ id: "yourEmbeddingsIndexId" }); +``` + +## Add data + +You can add new data to your embeddings using the `add` method + +```javascript +index.add("My house is yellow"); +``` + +## Search index + +The `search()` function looks for semantically similar data in an embeddings index + +```javascript +const [{ content }] = await index.search("My house is pink"); + +console.log(content); // My house is yellow +``` + +# getAllEmbeddings() + +This function returns all the embedding indexes that have been created. diff --git a/docs/v0.2.3/Data/kv-store.md b/docs/v0.2.3/Data/kv-store.md new file mode 100644 index 0000000..83aff00 --- /dev/null +++ b/docs/v0.2.3/Data/kv-store.md @@ -0,0 +1,33 @@ +--- +title: "KV Store" +slug: "kv-store" +excerpt: "" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 12 2023 08:31:14 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Wed Oct 18 2023 20:57:45 GMT+0000 (Coordinated Universal Time)" +--- +Polyfire exposes a simple persistent key value store for each user of each project. + +_NOTE: The kv store only stores string. If you want to store something more complex, you can use JSON.stringify_ + +## πŸ’‘ Example + +To set a value: + +```js Javascript +// In React: +const { data: { kv } } = usePolyfire(); +// In other environments: +const { data: { kv } } = polyfire; + +await kv.set("my_key", "my_value"); +``` + +The value can later be retieved with kv.get: + +```js Javascript +console.log(await kv.get("my_key")); // Should print "my_value" +``` diff --git a/docs/v0.2.3/Get Started/basic-usage.md b/docs/v0.2.3/Get Started/basic-usage.md new file mode 100644 index 0000000..bb5f70c --- /dev/null +++ b/docs/v0.2.3/Get Started/basic-usage.md @@ -0,0 +1,132 @@ +--- +title: "Basic Usage" +slug: "basic-usage" +excerpt: "This tutorial shows you how to use the Polyfire Backend SDK in your AI app." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 26 2023 06:38:49 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 02:27:03 GMT+0000 (Coordinated Universal Time)" +--- +# How does it work? + +Polyfire is a Managed Backend for AI apps. It means that your AI Backend is "abstracted" and you don't have to think about it. All you do is use some function in your Front End code to use AI models, embeddings (data vectorized by LLMs) and many other things you might need like smart prompts, data integrations, rate limits, billing integrations, etc. + +Your user flow is the following: + +1. Create a project in the [Polyfire Developer Console](https://beta.polyfire.com). If you're unsure how to do that, you can follow [this tutorial here](doc:new-project-rate-limit). +2. Initializing the Polyfire in your Front End code +3. Call Polyfire SDK functions in your code to make your AI app + +In the following guide, we will look into how to setup Polyfire client-side, and then how to use the core SDK functions to make a basic AI app. + +# Requirements + +To follow this tutorial, you need some kind of React App. Our documentation is mostly focused on React right now, even thought the underlying JavaScript code works for any JavaScript Front End library. + +To setup a basic React App with TypeScript, run the command below. + +```shell Shell +npx create-react-app --template typescript +cd +npm install polyfire-js +``` + +To run this app, you can use the command `npm start`. + +*** + +# Setting up Polyfire in my Front End + +## 1. Inject Polyfire in your app + +In your _**index.tsx**_ or at the root of your client side-code, import the Polyfire Provider and wrap your app in it. + +```jsx JSX +import ReactDOM from "react-dom/client"; +import { PolyfireProvider } from "polyfire-js/hooks"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; + +const root = ReactDOM.createRoot( + document.getElementById("root") as HTMLElement +); +root.render( + + + +); + +reportWebVitals(); +``` + +> 🚧 Replace _your_project_alias_ +> +> Make sure to remember to replace _your_project_alias_ in the provider by the Project Alias you can grab on your project page. + +## 2. Add user sessions + +For Polyfire to work client-side, you need to setup unique user sessions. That way, each user of your app will have a custom, rate-limited, API token and can use your app according to the restrictions you give them. + +To do that you can use our login functions, from the _auth_ module. + +In _**App.tsx**_ or wherever in your own app, add this authentification code: + +```jsx +import React from 'react'; +import { usePolyfire } from 'polyfire-js/hooks'; + +function App() { + const { auth } = usePolyfire(); + const { login, status } = auth; + + if (status == 'unauthenticated') + return + else if (status == 'loading') return (
Loading...
) + else if (status == 'authenticated') return (
We already logged in!
) + else return
+} + +export default App; +``` + +> If your app already has an integration with Firebase Auth, you can see how to use it [in that tutorial](doc:signin-firebase). We plan to add all the other Auth integrations, if you want us to speed up integrating the Auth system you are using, [message us on our Discord](www.polyfire.com/discord). + +## 3. Use LLMs to write a poetic "Hello World" + +Now that we have unique user sessions per user, we can make some calls to the Polyfire Backend API and run some AI models. + +We will use the basic `generate()` function imported from the _models_ Polyfire module. By default `generate()` calls the OpenAI gpt-3.5-turbo endpoint, which is the model running ChatGPT. + +Still in your **_App.tsx_** or wherever else you are in your app, modify your code so it looks like the one below: + +```jsx +import React, { useState, useEffect } from "react"; +import { usePolyfire } from "polyfire-js/hooks"; + +function App() { + const { auth, models } = usePolyfire(); + const [helloWorld, setHelloWorld] = useState(); + + const { login, status } = auth; + const { generate } = models; + + useEffect(() => { + if (status === "authenticated") { + generate("Write a hello world haiku").then(setHelloWorld); + } + }, [status]); + + if (status == "unauthenticated") + return ; + else if (status == "loading" || !helloWorld) return
Loading...
; + else if (status == "authenticated") return
{helloWorld}
; + else return
; +} + +export default App; +``` + +You can now start developing with the Polyfire Backend! :sparkles: diff --git a/docs/v0.2.3/Get Started/developer-console.md b/docs/v0.2.3/Get Started/developer-console.md new file mode 100644 index 0000000..8ea81a1 --- /dev/null +++ b/docs/v0.2.3/Get Started/developer-console.md @@ -0,0 +1,26 @@ +--- +title: "Developer Console" +slug: "developer-console" +excerpt: "The Developer Console is a key element of the Polyfire Backend API. It where you can see visually all the elements of your managed backend, including the various model usages, projects, billing, data and all the other metrics and variables you use through the API." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 26 2023 01:46:41 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 02:27:45 GMT+0000 (Coordinated Universal Time)" +--- +# Overview of the Developer Console + +The Polyfire Developer Console is at [beta.polyfire.com](https://beta.polyfire.com.) Most of the things you can do from the Console can also be done using the API, but the visual interface is much more enjoyable to keep track of you project, users, data and other API metrics. + +The Dev Console is broken down in a few sections: + +1. **Home**: where you can init your project and access your configuration variables. +2. **Auth**: where you can see the list of your users and define parameters like rate limits or payments. +3. **Models**: where you can consult the list of models we support and see logs of their usage. +4. **Data**: where you can see the embeddings you have created and stored, your key-value database and the variation data integrations of your app. +5. **Prompts**: where you can see the various prompts you have saved and are using in your app. + +# Create an account + +To create a Developer Account, simply go to the [Developer Console](https://beta.polyfire.com) and Sign Up With Github. diff --git a/docs/v0.2.3/Get Started/introduction.md b/docs/v0.2.3/Get Started/introduction.md new file mode 100644 index 0000000..42779a9 --- /dev/null +++ b/docs/v0.2.3/Get Started/introduction.md @@ -0,0 +1,58 @@ +--- +title: "Introduction" +slug: "introduction" +excerpt: "⚑ A managed backend for AI apps. Call AI models from the frontend πŸͺΆ" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Mon Sep 11 2023 08:37:03 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 02:26:18 GMT+0000 (Coordinated Universal Time)" +--- +Polyfire's goal is to make it possible to code every AI tool/Chatbot you could want in only a couple of lines of code in the frontend without the need for complex abstractions and having to deploy anything. + +[block:image] +{ + "images": [ + { + "image": [ + "https://files.readme.io/7442014-demo.gif", + "", + "" + ], + "align": "center" + } + ] +} +[/block] + + +## :new: Getting Started + +To get an overview of Polyfire follow this **[Basic Usage](doc:basic-usage)** tutorial. + +## ✨ Starter Guides + +We also made a couple of tutorials you can use to get started with Polyfire: + +- **[How to make a clone of ChatGPT](doc:chatgpt-clone)** +- **[New Project](doc:new-project-rate-limit)** +- **[Adding stripe subscriptions](doc:react-stripe-subscriptions)** +- **[Call Polyfire from React](doc:usepolyfire)**: The usePolyfire hooks lets you use Polyfire and handle authentification without having to deploy any backend +- **[Call Polyfire from other browser environments](doc:javascript)**: The Polyfire Client Object allows you to use Polyfire and handle authentification without having to deploy any backend in any environment + +## πŸ“š Useful References + +- **[Generate Simple Text](ref:generate)**: Answer to simple requests as text +- **[Create Chatbots](ref:chats)**: Easily create chatbots +- **[Transcribe](ref:transcribe)**: Transcribe audio files to text +- **[Memory](ref:embeddings)**: Easily create a long-term memory and simplify the use of large amounts of information +- **[GenerateImage](ref:generate-image)**: Generate images with Dall-E + +## πŸ“« Contact us + +We strive for feedback and want to understand everyone's needs, and you can hang out with us on [Discord](https://www.polyfire.com/discord)! + +## πŸ§‘β€πŸ’» Contributing + +Polyfire is open-source! You can contribute to the [Javascript SDK](https://github.com/polyfire-ai/polyfire-js) or the [API](https://github.com/polyfire-ai/polyfact-api-go) by opening an issue or a PR! diff --git a/docs/v0.2.3/Get Started/models-list.md b/docs/v0.2.3/Get Started/models-list.md new file mode 100644 index 0000000..c72a84b --- /dev/null +++ b/docs/v0.2.3/Get Started/models-list.md @@ -0,0 +1,31 @@ +--- +title: "Models List" +slug: "models-list" +excerpt: "List of the models available and their respective costs." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 26 2023 01:24:16 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 10 2023 10:06:56 GMT+0000 (Coordinated Universal Time)" +--- +| Model Name | Type | Input | Output | +| :--------------------------------- | :------------------------- | :------------------ | :------------------ | +| `gpt-3.5-turbo` | Text Generation | $0.0015 / 1K tokens | $0.002 / 1K tokens | +| `gpt-3.5-turbo-16k` | Text Generation | $0.0030 / 1K tokens | $0.004 / 1K tokens | +| `gpt-4` | Text Generation | $0.03 / 1K tokens | $0.06 / 1K tokens | +| `gpt-4-32k` | Text Generation | $0.06 / 1K tokens | $0.12 / 1K tokens | +| `cohere` | Text Generation | $0.015 / 1K tokens | $0.015 / 1K tokens | +| `llama-2-70b-chat`[Replicate] | Text Generation | N/A | $0.0014 / second | +| `wizard-mega-13b-awq`[Replicate] | Uncensored Text Generation | N/A | $0.000725 / second | +| `airoboros-llama-2-70b`[Replicate] | Uncensored Text Generation | N/A | $0.0014 / second | +| `replit-code-v1-3b`[Replicate] | Code Generation | N/A | $0.00115 / second | +| `dalle-2` | Image Generation | N/A | $0.02 / image | +| `text-embedding-ada-002` | Embeddings | $0.0001 / 1K tokens | N/A | +| `elevenlabs` | Text-To-Speech | $0.3 / 1K chars | N/A | +| `whisper` | Speech-To-Text | $0.0001 / second | N/A | + +- You can put your own OpenAI and Replicate keys in the [dashboard settings](https://beta.polyfire.com/settings). +- `text-embedding-ada-002` is used when creating a Memory/Embeddings or when using a DataLoader. +- Some features (Web, Memory, Embeddings, DataLoaders, etc...) will increase the number of input tokens. [the infos method](ref:infos) lets you monitor closely the LLMs token usage. +- Your total usage costs appears on [your dashboard](https://beta.polyfire.com) diff --git a/docs/v0.2.3/Get Started/new-project-rate-limit.md b/docs/v0.2.3/Get Started/new-project-rate-limit.md new file mode 100644 index 0000000..70bc8bd --- /dev/null +++ b/docs/v0.2.3/Get Started/new-project-rate-limit.md @@ -0,0 +1,137 @@ +--- +title: "New Project" +slug: "new-project-rate-limit" +excerpt: "A quick tutorial on how to create a new project & set user rate limits." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Tue Sep 26 2023 01:56:04 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 02:27:33 GMT+0000 (Coordinated Universal Time)" +--- +# Project Creation Flow + +Polyfire is what is called a managed backend, it means that we handle all the backend part of your app, so that you only have to focus on the client side part. (The Front End, which typically is React, React Native or another mobile or web library.) + +The Flow is always the same: + +1. Create a new project on the [Developer Console](https://beta.polyfire.com) +2. Install an initialize your Polyfire project on your client code +3. Make calls to your Polyfire Backend API in your client code using the various methods and interfaces of the Polyfire JavaScript SDK + +# Step by step + +## 1. Navigate to the Developer Console + +From [www.polyfire.com](http://www.polyfire.com) click on the "Start your project" button, or go directly to [beta.polyfire.com](beta.polyfire.com), to get to the dashboard. There you can sign in with your GitHub or Google account. + +[block:image] +{ + "images": [ + { + "image": [ + "https://files.readme.io/f1b2a05-Screenshot_2023-10-16_at_3.50.21_PM.png", + "", + "" + ], + "align": "center" + } + ] +} +[/block] + + +## 2. Create a new project + +From the home page, you can create a new project or use the default sandbox project that is created with each new account. + +[block:image] +{ + "images": [ + { + "image": [ + "https://files.readme.io/c61993a-Screenshot_2023-10-16_at_3.54.45_PM.png", + "", + "" + ], + "align": "center" + } + ] +} +[/block] + + +## 3. Copy the project slug or starter code + +After creating the project, you will be redirected to the Project Hone Page. + +From this page copy the project slug or the starter code (which as your project slug in it) and paste it in your client side code set init Polyfire. + +[block:image] +{ + "images": [ + { + "image": [ + "https://files.readme.io/d827377-Screenshot_2023-10-16_at_4.07.37_PM.png", + "", + "" + ], + "align": "center" + } + ] +} +[/block] + + +## 4. Initialize Polyfire in your Front End + +On your client-side code, you can setup the Polyfire SDK by injecting the Project Slug into the Polyfire Provider (if your using React) or in the init() function (Javascript). + +Example code for a React App is shown below. This is the same code than the starter code on the dashboard but without your project slug. + +```javascript + + // src/App.jsx + import React from 'react'; + import { PolyfireProvider, usePolyfire } from 'polyfire-js/hooks'; + + const App = () => { + // Wrap your main component with PolyfireProvider. This provides the necessary context. + return ( + + + + ); + }; + + // Component that interacts with the Polyfire SDK + const ExampleComponent = () => { + // Use the usePolyfire hook to access Polyfire functionalities + const { auth: { login, logout, status }, models: { generate } } = usePolyfire(); + + // Function to fetch a code sample when user is authenticated + const fetchSample = async () => { + if (status === "authenticated") { + const completion = await generate("Give me a code sample"); + console.log(completion); + } + } + + // Render buttons for authentication and fetching samples + return ( +
+ + + + +
+ ); + }; + + export default App; + +``` + +And that's it! You can call the Polyfire AI Backend through your app. + +In this starter code, there are authentication functions for your users. You need user sessions to generate unique, rate-limited, API keys for each user. We show you how to do that in more details [in that guide](doc:basic-usage), but it's basically setup in the starter code. diff --git a/docs/v0.2.3/Models/chatgpt-clone.md b/docs/v0.2.3/Models/chatgpt-clone.md new file mode 100644 index 0000000..b043694 --- /dev/null +++ b/docs/v0.2.3/Models/chatgpt-clone.md @@ -0,0 +1,220 @@ +--- +title: "Making ChatGPT" +slug: "chatgpt-clone" +excerpt: "In this tutorial, we will make a chatbot application similar to ChatGPT. We will use React as a frontend library, Tailwind as a CSS framework, and Polyfire's client SDK to access AI APIs and make the AI logic." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Mon Sep 11 2023 09:22:11 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Wed Oct 18 2023 20:57:45 GMT+0000 (Coordinated Universal Time)" +--- +> _**Note:** This tutorial uses the functions contained in the usePolyfire hook instead of the useChat directly. We thought it would be more interesting as a tutorial and you would learn more about Polyfire this way. If your goal is just to make a simple chat check the [useChat](doc:usechat) hook_ + +## Step 0: Getting started + +This tutorial assume you already have made a **React project** using polyfire as explained in the Getting Started + +## Step 1: Styling with TailwindCSS + +For styling our chat interface, we'll be using TailwindCSS. Install it: + +```bash +npm install -D tailwindcss +npx tailwindcss init +``` + +Then, set up your styles and configure Tailwind: + +**src/index.css** + +```css +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, body, #root { + width: 100%; + height: 100%; + margin: 0; +} +``` + +**tailwind.config.js** + +```json +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +} +``` + +Make sure to restart your server to apply the Tailwind styles. + +## Step 2: Designing the Chat Interface + +Time to design our chat interface: + +Create a new ChatBox.tsx file and paste that code in it. + +```jsx +function ChatBox() { + return ( +
+
+
+              

AI: Hello World!

+
+
+
+
+
Human:
+ +
+ +
+
+ ); +} + +export default ChatBox +``` + +Now, we want to import that ChatBot interface into our main App. +Change your App.tsx so that it looks like the code below: + +```jsx +function App() { + const { auth: { login, status } } = usePolyfire(); + + return ( +
+ {status === "unauthenticated" ? ( + + ) : status === "authenticated" ? ( + + ) : ( + "Loading..." + )} +
+ ); +} +``` + +Your interface should look like the screenshot below. +Non dynamic chat + +But we can't yet tap messages; we need to add the JavaScript logic in the ChatBox component to do that. +This is done below: + +```jsx +function ChatBox({ messages }: { messages: { is_user_message: boolean, content: string }[] }) { + return ( +
+
+
+                {messages.map(elem => (
{elem.is_user_message ? "Human:" : "AI:"} {elem.content}
))} +
+
+
+
+
Human:
+ +
+ +
+
+ ); +} + +export default ChatBox +``` + +This should give you an error; don't worry about it, and go directly to the next step. + +Next, we enhance our ChatBox by introducing the callback property onMessage to handle user message submissions. For this, we need to import the FormEvent type from React. Update your ChatBox.tsx: + +```jsx +import { useState, FormEvent } from "react"; + +function ChatBox({ messages, onMessage }: { messages: { is_user_message: boolean, content: string }[], onMessage: (message: string) => Promise | void }) { + const [loading, setLoading] = useState(false); + async function handleSubmit(e: FormEvent) { + e.preventDefault(); + + setLoading(true); + const message = (e.target as any).message.value; + if (message) { + (e.target as any).message.value = ""; + await onMessage(message); + } + setLoading(false); + } + + return ( +
+
+
+                {messages.map(elem => (

{elem.is_user_message ? "Human:" : "AI:"} {elem.content}

))} +
+
+
+
+
Human:
+ +
+ "} type="submit" disabled={loading} /> +
+
+ ); +} + +export default ChatBox +``` + +## Step 3: Implementing the Chat Logic + +To make that preceding Chat Logic work, we need to update our App.tsx, and work with the Polyfire API to generate chat messages. + +We will make a chat and display a chat history of the conversation. +Let's update our App component so it looks something like this: + +```jsx +function App() { + const { auth: { login, status }, utils: { Chat } } = usePolyfire(); + const [chat, setChat] = useState(); + const [messages, setMessages] = useState<{ is_user_message: boolean, content: string }[]>([]); + + useEffect(() => { + if (status === "authenticated") { + setChat(new Chat()); + } + }, [status]); + + return ( + <>{ + status === "unauthenticated" ? () + : chat ? { + await chat.sendMessage(message); + setMessages((await chat.getMessages()).reverse()); + }} /> + : "Loading..." + } + ); +} + +``` + +Try typing a question! You should get an answer from GPT-3.5, the default PolyFire AI model. +Your interface should look something like the one below. +final app. + +And there you have it! You've successfully created a simple chat application similar to ChatGPT using React and Polyfire. Enjoy chatting! diff --git a/docs/v0.2.3/Models/chats.md b/docs/v0.2.3/Models/chats.md new file mode 100644 index 0000000..ea81b9c --- /dev/null +++ b/docs/v0.2.3/Models/chats.md @@ -0,0 +1,8 @@ +--- +title: "Chat" +slug: "chats" +excerpt: "" +hidden: false +createdAt: "Mon Sep 11 2023 08:54:18 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- diff --git a/docs/v0.2.3/Models/chats/getmessages.md b/docs/v0.2.3/Models/chats/getmessages.md new file mode 100644 index 0000000..f38dd9d --- /dev/null +++ b/docs/v0.2.3/Models/chats/getmessages.md @@ -0,0 +1,29 @@ +--- +title: "getMessages" +slug: "getmessages" +excerpt: "" +hidden: false +createdAt: "Wed Sep 27 2023 06:31:52 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +Get the history of the previous chat messages. + +- Returns an array of Messages sorted from the most recent ones to the oldest. + +```js javascript +const history = await chat.getMessages(); + +const lastAnswer = history[0]; + +console.log(lastAnswer.content); // Neil, Buzz and Richard. +``` + +```ts typescript +type Message = { + id: string; // A unique id for the message + chat_id: string; // A unique id for the chat + is_user_message: boolean; // Whether the message was sent by the user or the chatbot. + content: string; // The content of the message + created_at: string; // An ISO date for the time when the message was sent +} +``` diff --git a/docs/v0.2.3/Models/chats/new-chat.md b/docs/v0.2.3/Models/chats/new-chat.md new file mode 100644 index 0000000..8eb4592 --- /dev/null +++ b/docs/v0.2.3/Models/chats/new-chat.md @@ -0,0 +1,103 @@ +--- +title: "new Chat()" +slug: "new-chat" +excerpt: "This feature allows you to create a chatbot with the minimal amount of code" +hidden: false +createdAt: "Fri Nov 03 2023 02:48:16 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:43:07 GMT+0000 (Coordinated Universal Time)" +--- +## Create a simple chatbot + +To initialize a new chat: + +```js javascript +// In React +const { utils: { Chat } } = usePolyfire(); +// In other environments +const { utils: { Chat } } = polyfire; + +const chat = new Chat(); +``` + +## Chat context + +You can add context to your chatbot by the `systemPrompt` parameter. Pass a string containing your context when initiating the chat object. + +```js javascript +const systemPrompt = `Ask a random physics question. If the Human answers correctly, ask another question...`; +const chat = new Chat({ systemPrompt }); +``` + +## Chat options + +```ts typescript +type ChatOptions = { + provider?: "openai" | "cohere" | "llama"; // The default value is "openai" + systemPrompt?: string; // The system prompt as seen above + systemPromptId?: string // The Id of a custom prompt + autoMemory?: boolean; +}; +``` + +### Provider + +You can change the model provider using the provider option. + +For example, to create a chatbot using cohere: + +```js javascript +const chat = new Chat({ provider: "cohere" }); +``` + +### AutoMemory + +The autoMemory option allows to send every message of the chat to a new memory and use it in every message. + +This adds a long-term memory to the chatbot. + +```js javascript +const chat = new Chat(); + +await chat.sendMessage("The secret word is banana42"); + +... Send a lot of messages here + +await chat.sendMessage("What is the secret word?"); // The chatbot should still answer with banana42 +``` + +### systemPromptId + +The systemPromptId option allows you to add the ID of a custom prompt that you've created using the[ prompt features](ref:prompt-store) or by directly using a prompt shared by another developer. + +### systemPromptId + +The `systemPromptId` option in the `ChatOptions` type allows you to specify a custom prompt that you've created for your app. This can be either the ID of the prompt or its alias. When using the Polyfire dashboard, the alias of the prompt is typically provided, which you can directly use here. + +#### Usage Example + +```typescript +import { Chat, usePolyfire } from 'polyfire-js'; +import { ChatOptions } from "polyfire-js/generate"; + + +// Example: Initializing a Chat with a custom system prompt ID (or alias) +const App = () => { + // In React + const { utils: { Chat } } = usePolyfire(); + // In other environments + // const { utils: { Chat } } = polyfire; + + // Assuming 'physics-quiz-alias' is the alias of the custom prompt that you have created. + const customSystemPromptId = 'physics-quiz-alias'; + + const chatOptions: ChatOptions = { + systemPromptId: customSystemPromptId + }; + + const chat = new Chat(chatOptions); + + // Further chat implementation... +}; + +export default App; +``` diff --git a/docs/v0.2.3/Models/chats/sendmessage.md b/docs/v0.2.3/Models/chats/sendmessage.md new file mode 100644 index 0000000..5ecc109 --- /dev/null +++ b/docs/v0.2.3/Models/chats/sendmessage.md @@ -0,0 +1,57 @@ +--- +title: "sendMessage" +slug: "sendmessage" +excerpt: "" +hidden: false +createdAt: "Wed Sep 27 2023 06:08:16 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:43:07 GMT+0000 (Coordinated Universal Time)" +--- +The `sendMessage` method in the `Chat` class is used to send a message to a chat conversation. This method automatically adapts to provide either a stream of responses or a single, complete response based on how it is called. + +### Key Features + +#### Context-Aware + +- **Conversational Memory**: Every message sent and the corresponding response from the language model are stored, ensuring a continuous and coherent conversation flow by keeping track of all previous exchanges. + +#### Flexible Response Handling + +- **Streaming Mode**: Direct calls to `sendMessage` return a stream for real-time, incremental responses. Useful for lengthy or real-time interactions. Requires event listeners like `on('data', callback)`. +- **Complete Mode**: Using `sendMessage` with `async/await` or `.then` returns a promise for a single, full response, suitable for standard request-response scenarios. + +### Usage Examples + +#### Non-Streaming Response + +To receive a complete response after the message processing is finished, use `sendMessage` with `async/await` or `.then`. This will return a promise that resolves to a string containing the full response. + +```ts +const chat = new Chat(); + +// Example using async/await +async function getCompleteResponse() { + const answerString = await chat.sendMessage("Who was the first man to walk on the moon?"); + console.log("Non-Streaming Response:", answerString); +} + +// Example using .then +chat.sendMessage("Who was the first man to walk on the moon?") + .then(answerString => { + console.log("Non-Streaming Response:", answerString); + }); +``` + +#### Streaming Response + +For a real-time, incremental response, simply call `sendMessage` without `async/await` or `.then`. This will return a stream of responses as they become available. + +```ts +const chat = new Chat(); + +// Sending a message for streaming response +const responseStream = chat.sendMessage("Who was the first man to walk on the moon?"); + +responseStream.on('data', (data) => { + console.log("Streaming Part of Response:", data); +}); +``` diff --git a/docs/v0.2.3/Models/generate-image.md b/docs/v0.2.3/Models/generate-image.md new file mode 100644 index 0000000..185e8e6 --- /dev/null +++ b/docs/v0.2.3/Models/generate-image.md @@ -0,0 +1,46 @@ +--- +title: "generateImage" +slug: "generate-image" +excerpt: "This features allows you to generate images easily from a prompt using dall-e" +hidden: false +createdAt: "Mon Sep 11 2023 09:01:05 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +## Function: generateImage + +**Prototype:** + +```ts typescript +async function generateImage(prompt: string, options: GenerationOptions = {}): Promise<{ url: string }> +``` + +### πŸ’‘ Examples + +The simplest way to use it: + +```js javascript +// In React: +const { models: { generateImage } } = usePolyfire(); +// In other environments: +const { models: { generateImage } } = polyfire; + +const { url } = await generateImage("Pikachu"); // By default generateImage uses Dall-E to generate its images + +console.log(url); +``` + +[block:image] +{ + "images": [ + { + "image": [ + "https://hqyxaayiizqwlknddokk.supabase.co/storage/v1/object/public/generated_images/d70de08e-636e-4c78-b72e-a924b9d61464.png", + null, + "Cursed pikachu" + ], + "align": "center", + "caption": "A cursed Pikachu" + } + ] +} +[/block] diff --git a/docs/v0.2.3/Models/generate-with-types.md b/docs/v0.2.3/Models/generate-with-types.md new file mode 100644 index 0000000..62fa67f --- /dev/null +++ b/docs/v0.2.3/Models/generate-with-types.md @@ -0,0 +1,38 @@ +--- +title: "generateWithType" +slug: "generate-with-types" +excerpt: "" +hidden: false +createdAt: "Mon Sep 11 2023 14:58:13 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:43:06 GMT+0000 (Coordinated Universal Time)" +--- +> **WARNING:** Probabilistic functions +> Theses functions cannot be guaranteed to work every time. Complex inputs can sometimes confuse the LLMs and lead them to throw an Error. + +To define the schema we expose a modified version of `io-ts` that adds a way to describe your types. + +For the example here, we want to describe a function given in input and extract its name, the name of its arguments and its return type. + +```js javascript +import { t } from "polyfire"; + +// In React: const { models: { generateWithType } } = usePolyfire(); +// In other environments: const { models: { generateWithType } } = polyfire; + +const functionDescriptionType = t.type({ + functionName: t.string, + description: t.string.description("A 50 word description of what the function does"), + args: t.array(t.string).description("The name of the arguments"), + returnType: t.string +}); + +const { functionName, description, args, returnType } = await generateWithType( + "function add(a, b, c) { return a + b + c }", + functionDescriptionType, +); + +console.log(functionName) // add +console.log(description) // Adds three numbers together. +console.log(args) // ["a", "b", "c"] +console.log(returnType) // number +``` diff --git a/docs/v0.2.3/Models/generate.md b/docs/v0.2.3/Models/generate.md new file mode 100644 index 0000000..3a19162 --- /dev/null +++ b/docs/v0.2.3/Models/generate.md @@ -0,0 +1,8 @@ +--- +title: "generate" +slug: "generate" +excerpt: "" +hidden: false +createdAt: "Mon Sep 11 2023 14:48:07 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- diff --git a/docs/v0.2.3/Models/generate/generate-1.md b/docs/v0.2.3/Models/generate/generate-1.md new file mode 100644 index 0000000..229d171 --- /dev/null +++ b/docs/v0.2.3/Models/generate/generate-1.md @@ -0,0 +1,56 @@ +--- +title: "generate()" +slug: "generate-1" +excerpt: "This function is the simplest way to use LLM Text Generation." +hidden: false +createdAt: "Fri Nov 03 2023 02:45:48 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:43:07 GMT+0000 (Coordinated Universal Time)" +--- +**Prototype:** + +```ts typescript +// In React: const { models: { generate } } = usePolyfire(); +// In other environments: const { models: { generate } } = polyfire; + +async function generate(task: string, options?: GenerationOptions): Generation // Generation implements Promise +``` + +## πŸ’‘ Examples + +The simplest way to use it: + +```js javascript +const answer = await polyfire.generate("Who was the first man to walk on the moon?"); +``` + +You can also send some options as a second argument to the generate function. + +```ts typescript +type GenerationOptions = { + model?: "gpt-3.5-turbo" | "gpt-3.5-turbo-16k" | "gpt-4" | "gpt-4-32k" | "cohere" | "llama-2-70b-chat" | "replit-code-v1-3b" | "wizard-mega-13b-awq"; // The default value is gpt-3.5-turbo + stop?: string[]; // A list of word where the generation should stop + temperature?: number; // The text generation temperature (setting this to 0.0 will make the generation deterministic) + memoryId?: string; // The id of a memory to improve the context given to the LLM see the memory section of the wiki to learn more. + chatId?: string; // The id of a existing chat. It is not recommended to use this directly,prefer to use the chat feature, see the chat section to learn more. + language?: string; // The language the result should be written in +} +``` + +For example, to generate with cohere: + +```javascript +const answer = await polyfire.generate("What color is the sky?", { model: "gpt-4" }); +``` + +## Generate Chains + +You can easily construct chains of generates by call the generate method of the Generation result class + +```javascript +const answer = await generate("Who was Neil Armstrong ?") + .generate("Who was the US president at the time ?") + .generate("Who was his wife ?"); + +console.log(answer); +// Answer: The wife of Richard Nixon, the President of the United States at the time of Neil Armstrong's moonwalk, was Pat Nixon. +``` diff --git a/docs/v0.2.3/Models/generate/infos.md b/docs/v0.2.3/Models/generate/infos.md new file mode 100644 index 0000000..2f36ca0 --- /dev/null +++ b/docs/v0.2.3/Models/generate/infos.md @@ -0,0 +1,89 @@ +--- +title: "infos" +slug: "infos" +excerpt: "" +hidden: false +createdAt: "Tue Sep 12 2023 09:00:17 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +The `infos`method, when used with Polyfire`generate` function, lets you see more details about how the text is created. + +### Infos Option + +Use the `infos` method to get a report showing token use (what goes in and comes out) and the resources the model uses when creating text with the `web`, `memory` or `data` options. This is helpful for seeing how the model works, its costs, and figuring out where the created content comes from. + +To use the `infos` feature, call the `infos` method of the result of the `generate` function: + +```typescript +generate("your_task_here").infos(); +``` + +When turned on, the `generate` function gives back a `GenerationResult` that includes: + +``` +type GenerationResult = { + result: string; // The generated content + tokenUsage: { // Token usage for input and output + input: number; + output: number; + }; + ressources?: Ressource[]; // Resources or embeddings used during generation +}; + +``` + +### TokenUsage + +A part of `GenerationResult`, `TokenUsage` shows clearly the tokens used in a specific text creation task: + +```typescript +type TokenUsage = { + input: number; // Tokens consumed for the input task. + output: number; // Tokens generated as output. +}; +``` + +This feature is especially valuable for understanding model computation costs and ensuring you're not overshooting token limitations. + +### Ressource + +`Ressource` arrays encapsulate and present the various resources from `web`, `memory` or `data` that the model relied upon during generation: + +```typescript +type Ressource = { + similarity: number; // Similarity score between resource and generated content. + id: string; // Unique identifier of the resource. + content: string; // Actual content of the resource. +}; +``` + +This data can be leveraged to trace back the origins of generated content. + +πŸ’‘ **Example** + +```typescript +// In React: +const { models: { generate } } = usePolyfire(); +// In other environments: +const { models: { generate } } = polyfire; + +// Define task, options, and client configurations +const task = "Explain the concept of quantum entanglement."; + +const generationOptions: GenerationWithInfosOptions = { + provider: "openai", + model: "gpt-3.5-turbo", + memoryId: "your_memory_id", +}; + +try { + const result = await generate(task, generationOptions).infos(); + console.log("Generated Output:", result.result); + console.log("Token Usage:", result.tokenUsage); + console.log("Resources Used:", result.ressources); + +} catch (error) { + console.error("Generation faced an inconsistency:", error); +} + +``` diff --git a/docs/v0.2.3/Models/generate/stream.md b/docs/v0.2.3/Models/generate/stream.md new file mode 100644 index 0000000..2b03a4b --- /dev/null +++ b/docs/v0.2.3/Models/generate/stream.md @@ -0,0 +1,32 @@ +--- +title: "stream" +slug: "stream" +excerpt: "" +hidden: false +createdAt: "Mon Sep 11 2023 14:53:10 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +The result of a generation can also be used as a stream + +**Prototype:** + +```ts typescript +function generate( + task: string, + options: GenerationOption, +): Generation; // Generation implements the Readable interface from https://www.npmjs.com/package/readable-stream +``` + +The stream should send the result token by token instead of waiting for the whole answer. + +_NOTE: Cohere doesn't support streams yet and will return the entire answer in one chunk_ + +### πŸ’‘ Example + +The result can be piped to a writable stream with the `pipe` method or individuals chunks can be retrieved using the `.on` method as seen in the [stream api](https://nodejs.org/api/stream.html#readable-streams) + +```js javascript +const resultStream = polyfire.generate("Who was the first man to walk on the moon?", { stream: true }); + +resultStream.on("data", console.log); // In this should start printing the result word by word +``` diff --git a/docs/v0.2.3/Models/generate/web.md b/docs/v0.2.3/Models/generate/web.md new file mode 100644 index 0000000..20e9711 --- /dev/null +++ b/docs/v0.2.3/Models/generate/web.md @@ -0,0 +1,138 @@ +--- +title: "web" +slug: "web" +excerpt: "Connect your model to the web" +hidden: false +createdAt: "Tue Sep 12 2023 09:00:10 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +The `generate` function, provisioned by Polyfire, is architectured to streamline the process of task-based text generation. This document provides a granular exploration of the `web` option, elucidating both its functionality and implementation. + +*** + +### Web Option + +The Web option offers a seamless integration of any LLM supported by Polyfire with internet resources. + +To leverage this capability, set the `web` attribute to `true` when invoking the `generate` function: + +```typescript +generate("your_task_here", { web: true }); +``` + +Upon activation, the LLM can autonomously issue requests to web domains, distill pertinent data, and craft responses that align meticulously with your prescribed task. + +For scenarios demanding specific website referencing, URLs can be embedded directly into the task with the `read:` prefix: + +```typescript +generate("summarize this website read:https://example.com/" , { web: true }) +``` + +Moreover, to juxtapose or amalgamate data from multiple domains, simply append multiple links in a similar fashion: + +```typescript +generate("Compare this website read:https://example.com/milk-is-good with this one read:https://example.com/milk-is-bad") +``` + +Upon invoking the `web` option, the `options` parameter conforms to the `GenerationWithWebOptions` type, which inherently extends the attributes of `GenerationSimpleOptions`: + +```typescript +type GenerationWithWebOptions = { + provider?: "openai" | "cohere" | "llama" | ""; + model?: string; + stop?: string[]; + temperature?: number; + infos?: boolean; + language?: Language; +} & { web: true }; +``` + +> **WARNING:** So the web attribute is incompatible with the Chat, Memory, and SystemPrompt options. + +### πŸ’‘ Example + +```typescript +import { GenerationWithWebOptions } from 'polyfire-js'; + +// In React: +const { models: { generate } } = usePolyfire(); +// In other environments: +const { models: { generate } } = polyfire; + +// Define task, options, and client configurations +const task = "What is the weather like in Paris today?"; + +const generationOptions: GenerationWithWebOptions = { + provider: "openai", + model: "gpt-3.5-turbo", + Web: true +}; + +try { + const result = await generate(task, generationOptions); + console.log("Generated Output:", result); + +} catch (error) { + console.error("Generation encountered an anomaly:", error); +} +``` + +## Potential Errors and Troubleshooting: + +### 1. `error_website_exceeds_limit`: + +**Description:** This error is raised when the content from a single website has a token count that exceeds the model's context size. + +**Troubleshooting Steps:** + +- Double-check the website content. Large websites or those with extensive data might cause this issue. +- Opt to use a summary or an abridged version of the website if possible. +- Ensure that you are using the appropriate model that can handle the content size. + +### 2. `error_websites_content_exceeds`: + +**Description:** This error is raised when the accumulated content from multiple websites exceeds the model's context size. + +**Troubleshooting Steps:** + +- Limit the number of websites you are fetching content from. +- Prioritize and select only the most relevant websites. +- Consider using a different LLM that can handle larger content or splitting the content processing into multiple tasks. + +### 3. `error_no_content_found`: + +**Description:** This error indicates that no content was retrieved from the provided websites. + +**Troubleshooting Steps:** + +- Ensure that the provided URLs are correct and accessible. +- Make sure that the websites aren't blocking or limiting your content fetching requests. +- Verify that the websites have readable content and are not primarily image-based or media-based without accompanying text. + +### 4. `error_fetch_webpage`: + +**Description:** An issue occurred when trying to fetch a webpage. + +**Troubleshooting Steps:** + +- Ensure you have a stable internet connection. +- Verify that the target website is up and accessible. +- Make sure that you are not making too many rapid requests which might cause rate limiting. + +### 5. `error_parse_content`: + +**Description:** This error is raised when there's an issue parsing the content of a fetched webpage. + +**Troubleshooting Steps:** + +- Ensure that the website's content is structured in a way that's readable by the parsing method. +- Verify if the website uses unconventional structures or layouts that might be causing the parser to fail. + +### 6. `error_visit_base_url`: + +**Description:** This error indicates a problem occurred when trying to visit the base URL during scraping. + +**Troubleshooting Steps:** + +- Confirm that the base URL is correct and reachable. +- Ensure that the base URL allows for scraping and does not have restrictions like CAPTCHAs or bot blockers. diff --git a/docs/v0.2.3/Models/other-chat-overvire.md b/docs/v0.2.3/Models/other-chat-overvire.md new file mode 100644 index 0000000..0f16907 --- /dev/null +++ b/docs/v0.2.3/Models/other-chat-overvire.md @@ -0,0 +1,135 @@ +--- +title: "Chat Examples" +slug: "other-chat-overvire" +excerpt: "" +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Wed Sep 27 2023 06:10:11 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 01:18:53 GMT+0000 (Coordinated Universal Time)" +--- +## Create a simple chatbot + +To initialize a new chat: + +```js javascript +// In React +const { utils: { Chat } } = usePolyfire(); +// In other environments +const { utils: { Chat } } = polyfire; + +const chat = new Chat(); +``` + +To send your first message to the chatbot: + +```js javascript +const first = await chat.sendMessage("Who was the first man to walk on the moon?"); + +console.log(first); // Neil Armstrong. +``` + +Your chatbot will return the answer and remember the previous messages. + +```js javascript +const second = await chat.sendMessage("Who was the second one?"); + +console.log(second); // Buzz Aldrin. + +const president = await chat.sendMessage("Who was the US President at the time?"); + +console.log(second); // Richard Nixon. + +const firstNames = await chat.sendMessage("What were the first names of these three?"); + +console.log(firstNames); // Neil, Buzz and Richard. +``` + +## Streams + +As for the [stream with generate](ref:stream) function, you can choose to get streams instead of promises by adding `stream` option to `sendMessage` method. + +```js javascript +const resultStream = chat.sendMessage("Who was the first man to walk on the moon?", {stream: true}) + +resultStream.on("data", (d) => console.log(d)); // The answer should start to be printed on the console word by word + +await new Promise((res) => stream.on("end", resultStream)); // This is just to wait the end of the stream, this is not required +``` + +## Chat context + +You can add context to your chatbot by the `systemPrompt` parameter. Pass a string containing your context when initiating the chat object. + +```js javascript +const systemPrompt = `Ask a random physics question. If the Human answers correctly, ask another question...`; +const chat = new Chat({ systemPrompt }); +``` + +## Get the message history + +You can use the `getMessages` method to get the previous messages + +It will return an array of Messages sorted from the most recent ones to the oldest: + +```ts typescript +type Message = { + id: string; // A unique id for the message + chat_id: string; // A unique id for the chat + is_user_message: boolean; // Whether the message was send by the user or the chatbot. + content: string; // The content of the message + created_at: string; // An ISO date for the time when the message was sent +} +``` + +For example, after having run our example above: + +```js javascript +const history = await chat.getMessages(); + +const lastAnswer = history[0]; + +console.log(lastAnswer.content); // Neil, Buzz and Richard. +``` + +## Chat options + +```ts typescript +type ChatOptions = { + provider?: "openai" | "cohere" | "llama"; // The default value is "openai" + systemPrompt?: string; // The system prompt as seen above + systemPromptId? string // The Id of a custom prompt + autoMemory?: boolean; +}; +``` + +### Provider + +You can change the model provider using the provider option. + +For example, to create a chatbot using cohere: + +```js javascript +const chat = new Chat({ provider: "cohere" }); +``` + +### AutoMemory + +The autoMemory option allows to send every message of the chat to a new memory and use it in every message. + +This adds a long-term memory to the chatbot. + +```js javascript +const chat = new Chat({ autoMemory: true }); + +await chat.sendMessage("The secret word is banana42"); + +... Send a lot of messages here + +await chat.sendMessage("What is the secret word?"); // The chatbot should still answer with banana42 +``` + +### systemPromptId + +The systemPromptId option allows you to add the ID of a custom prompt that you've created using the[ prompt features](ref:prompt-store) or by directly using a prompt shared by another developer. diff --git a/docs/v0.2.3/Models/text-generation.md b/docs/v0.2.3/Models/text-generation.md new file mode 100644 index 0000000..cdbc7b0 --- /dev/null +++ b/docs/v0.2.3/Models/text-generation.md @@ -0,0 +1,73 @@ +--- +title: "Text Generation" +slug: "text-generation" +excerpt: "Examples of text generation functions." +hidden: false +metadata: + image: [] + robots: "index" +createdAt: "Fri Nov 03 2023 01:00:22 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 02:14:19 GMT+0000 (Coordinated Universal Time)" +--- +# Generate Text + +The basic LLM function is called `generate()`. It is imported from the _models_ Polyfire module. By default `generate()` calls the OpenAI gpt-3.5-turbo endpoint, which is the model running ChatGPT. + +An example of a simple AI-generated greeting in a React app: + +```jsx +function GreetingBox({ userName }) { + const [greeting, setGreeting] = useState(); + const { models } = usePolyfire(); + + useEffect(() => { + models + .generate(`Write a fun and simple greeting for ${userName}`) + .then(setGreeting); + }, []); + + return
{greeting}
; +} +``` + +# Customizing the Model + +You can change the the model the `generate()` function calls by including the options object. The complete list of available models and their names can be found [here](doc:models-list) or on the Dashboard. + +The same example but using GPT-4: + +```jsx JSX +function GreetingBox({ userName }) { + const [greeting, setGreeting] = useState(); + const { models } = usePolyfire(); + + useEffect(() => { + models + .generate(`Write a fun and simple greeting for ${userName}`, { model: "gpt-4" }) + .then(setGreeting); + }, []); + + return
{greeting}
; +} +``` + +# Uncensored Generation + +To generate uncensored text, call the model `wizard-mega-13b-awq`. It can be very handy if you are trying to build, let's say, an AI girlfriend. + +```jsx +function DirtyAnswer({ userMessage, girlfriendPrompt }) { + const [dirtyTalk, setDirtyTalk] = useState(); + const { models } = usePolyfire(); + + useEffect(() => { + const prompt = `${girlfriendPrompt}. Write a dirty answer to this message: ${userMessage}.` + + models + .generate(prompt, { model: "wizard-mega-13b-awq" }) + .then(setDirtyTalk); + }, []); + + return
{dirtyTalk}
; +} +``` diff --git a/docs/v0.2.3/Models/text-to-speech.md b/docs/v0.2.3/Models/text-to-speech.md new file mode 100644 index 0000000..867bc24 --- /dev/null +++ b/docs/v0.2.3/Models/text-to-speech.md @@ -0,0 +1,80 @@ +--- +title: "Text to speech" +slug: "text-to-speech" +excerpt: "Generate realistic audio files from written text" +hidden: false +createdAt: "Thu Oct 26 2023 13:08:03 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Thu Oct 26 2023 13:35:00 GMT+0000 (Coordinated Universal Time)" +--- +## Function: tts + +**Prototype:** + +```ts typescript +async function tts(text: string, options?: TTSOptions): Promise + +type TTSOptions = { voice?: string }; // See below the list of all possible voices + +function AudioTTS.getMp3Buffer(): Buffer // Get the speech as an Mp3 file buffer +async function AudioTTS.getAudioBuffer(): Promise // Get the speech as a standard [AudioBuffer](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer) +async function AudioTTS.play(): Promise // Play the speech audio +``` + +### πŸ’‘ Example + +```js javascript +// In React: +const { models: { tts } } = usePolyfire(); +// In other environments: +const { models: { tts } } = polyfire; + +const audio = await tts("According to all known laws of aviations, there is no way that a bee should be able to fly."); + +await audio.play(); +``` + +*** + +## Available voices list: + +| name | gender | description | provider | +| :-------- | :----- | :------------- | :--------- | +| rachel | female | calm | elevenlabs | +| clyde | male | war veteran | elevenlabs | +| domi | female | strong | elevenlabs | +| dave | male | conversational | elevenlabs | +| fin | male | sailor | elevenlabs | +| bella | female | soft | elevenlabs | +| antoni | male | well-rounded | elevenlabs | +| thomas | male | calm | elevenlabs | +| charlie | male | casual | elevenlabs | +| emily | female | calm | elevenlabs | +| elli | female | emotional | elevenlabs | +| callum | male | hoarse | elevenlabs | +| patrick | male | shouty | elevenlabs | +| harry | male | anxious | elevenlabs | +| liam | male | | elevenlabs | +| dorothy | female | pleasant | elevenlabs | +| josh | male | deep | elevenlabs | +| arnold | male | crisp | elevenlabs | +| charlotte | female | seductive | elevenlabs | +| matilda | female | warm | elevenlabs | +| matthew | male | | elevenlabs | +| james | male | calm | elevenlabs | +| joseph | male | | elevenlabs | +| jeremy | male | excited | elevenlabs | +| michael | male | | elevenlabs | +| ethan | male | | elevenlabs | +| gigi | female | childlish | elevenlabs | +| freya | female | | elevenlabs | +| grace | female | | elevenlabs | +| daniel | male | deep | elevenlabs | +| serena | female | pleasant | elevenlabs | +| adam | male | deep | elevenlabs | +| nicole | female | whisper | elevenlabs | +| jessie | male | raspy | elevenlabs | +| ryan | male | soldier | elevenlabs | +| sam | male | raspy | elevenlabs | +| glinda | female | witch | elevenlabs | +| giovanni | male | foreigner | elevenlabs | +| mimi | female | childish | elevenlabs | diff --git a/docs/v0.2.3/Models/transcribe.md b/docs/v0.2.3/Models/transcribe.md new file mode 100644 index 0000000..e8d3e85 --- /dev/null +++ b/docs/v0.2.3/Models/transcribe.md @@ -0,0 +1,40 @@ +--- +title: "Speech to text" +slug: "transcribe" +excerpt: "Transcribe audio files to texts easily using the transcribe function" +hidden: false +createdAt: "Mon Sep 11 2023 08:56:11 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:44:07 GMT+0000 (Coordinated Universal Time)" +--- +## Function: transcribe + +**Prototype:** + +```ts typescript +async function transcribe(file: Uint8Array | Buffer | Readable): Promise +``` + +### πŸ’‘ Example + +```js javascript +// Get your file from an upload/fetch. + +// In React: +const { models: { transcribe } } = usePolyfire(); +// In other environments: +const { models: { transcribe } } = polyfire; + +const transcription = await transcribe(file); + +console.log(transcription); +``` + +Should return (only if you have send the audio version on the bee-movie of course) + +``` +According to all known laws of aviation, there is no way that a bee should be able to fly. Its wings are too small to get its fat little body off the ground. The bee, of course, flies anyway because bees don't care about what humans think is impossible. +``` + +The supported file formats are `mp3`, `mp4`, `mpeg`, `mpga`, `m4a`, `wav` and `webm` + +The maximum file size is 25MB diff --git a/docs/v0.2.3/Prompt/system-prompts-alias.md b/docs/v0.2.3/Prompt/system-prompts-alias.md new file mode 100644 index 0000000..0c49c88 --- /dev/null +++ b/docs/v0.2.3/Prompt/system-prompts-alias.md @@ -0,0 +1,44 @@ +--- +title: "System Prompts" +slug: "system-prompts-alias" +excerpt: "" +hidden: false +metadata: + title: "System Prompts Alias" + description: "In this guide, we'll help you use aliases for system prompts to simplify your code" + image: [] + robots: "index" +createdAt: "Thu Nov 02 2023 10:39:07 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Nov 03 2023 16:12:07 GMT+0000 (Coordinated Universal Time)" +--- +In the Polyfire-JS SDK, the `generate` function or `Chat` class allows the use of the `systemPrompt` option where your prompts are typically hardcoded. An alternative is the `systemPromptId` option which utilizes a UUID. However, remembering and managing these UUIDs can be a hassle.So you can use an alias generated from your prompt name. They provide a recognizable and easy-to-use name for your system prompts, tidying up your code and enhancing clarity. + +## Setting Up Prompts + +1. **Access System Prompts**: Enter your dashboard, choose your project, and navigate to the system prompts management area. + +2. **Create a New Prompt**: + - Select `Prompts > Saved`. + - Press the `New` button. + - Input the name and prompt content, then save your new prompt. + - If a prompt already exists, locate it in `Prompts > Saved`. + +3. **Select a Prompt**: Identify the prompt you wish to use and copy its alias for use in your code. + +_Note_: Your prompt's name should be distinctive as it forms the basis of the alias and should be easy to remember. + +## Use Alias in Your Code + +After setting up your custom prompt, you can use the alias with the `systemPromptId` in your code when engaging with polyfire-js SDK. Here's how: + +```javascript +generate("Write a hello world haiku", {systemPromptId: "my_prompt_alias"}) + .then(response => { + console.log(response); + }) + .catch(error => { + console.error(error); + }); +``` + +In the snippet above, "my_prompt_alias" stands in for the system prompt's alias. The Polyfire API will use this alias to identify and execute the appropriate system prompt. diff --git a/docs/v0.2.3/React Components/auto-complete-input.md b/docs/v0.2.3/React Components/auto-complete-input.md new file mode 100644 index 0000000..0f597f2 --- /dev/null +++ b/docs/v0.2.3/React Components/auto-complete-input.md @@ -0,0 +1,28 @@ +--- +title: "AutoCompleteInput" +slug: "auto-complete-input" +excerpt: "Input component with auto-complete suggestions" +hidden: false +createdAt: "Mon Jan 08 2024 15:18:11 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:42:00 GMT+0000 (Coordinated Universal Time)" +--- +# Description + +A regular input component with an auto-complete placeholder. When a user types some text, the component waits for a 1 second break, and then sends a query to GPT-3.5 to suggest the next couple of words. The users can accept the suggestion with the Tab key. + +# Props + +- `completionColor`: Specifies the color of the auto-complete text. +- `containerStyle`: Defines the styling for the component's container. +- `containerClassName`: CSS class name for the component's container +- Extends all the props of a classic `` component + +# Example + +```typescript + +``` diff --git a/docs/v0.2.3/React Components/auto-complete-textarea.md b/docs/v0.2.3/React Components/auto-complete-textarea.md new file mode 100644 index 0000000..fb71691 --- /dev/null +++ b/docs/v0.2.3/React Components/auto-complete-textarea.md @@ -0,0 +1,26 @@ +--- +title: "AutoCompleteTextArea" +slug: "auto-complete-textarea" +excerpt: "Textarea component with auto-complete suggestions" +hidden: false +createdAt: "Mon Jan 08 2024 15:17:59 GMT+0000 (Coordinated Universal Time)" +updatedAt: "Fri Mar 01 2024 06:42:00 GMT+0000 (Coordinated Universal Time)" +--- +# Description + +This component is a regular Textarea component. But after the user has stopped typing for 1 second, it calls GTP-3.5 to ask for a suggestion on the next couple of words. The user can accept the suggestion with the Tab key. + +It's like [AutoCompleteInput](ref:auto-complete-input) but for a Textarea. + +# Props + +- Extends all the props of a standard `