AI Town is a virtual town where AI characters live, chat and socialize.
This project is a deployable starter kit for easily building and customizing your own version of AI town. Inspired by the research paper Generative Agents: Interactive Simulacra of Human Behavior.
The primary goal of this project, beyond just being a lot of fun to work on, is to provide a platform with a strong foundation that is meant to be extended. The back-end engine natively supports shared global state, transactions, and a journal of all events so should be suitable for everything from a simple project to play around with to a scalable, multi-player game. A secondary goal is to make a JS/TS framework available as most simulators in this space (including the original paper above) are written in Python.
git clone git@github.com:a16z-infra/ai-town.git
cd AI-town
npm install
npm run dev
npm run dev
will fail asking for environment variables. Enter them in the environment variables on your Convex dashboard to proceed. You can get there via npx convex dashboard
or https://dashboard.convex.dev See below on how to get the various environnment variables.
a. Set up Clerk
- Go to https://dashboard.clerk.com/ and click on âAdd Applicationâ
- Name your application and select the sign-in providers you would like to offer users
- Create Application
- Add NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
and CLERK_SECRET_KEY
to .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_***
CLERK_SECRET_KEY=sk_***
- Go to JWT Templates and create a new Convex Template. - Copy the JWKS endpoint URL for use below.
b. OpenAI API key
Visit https://platform.openai.com/account/api-keys to get your OpenAI API key if youâre using OpenAI for your language model.
c. Pinecone API keys
- Create a Pinecone index by visiting https://app.pinecone.io/ and click on âCreate Indexâ
- Give it an index name (this will be the environment variable PINECONE_INDEX_NAME
)
- Fill in Dimension as 1536
- Once the index is successfully created, click on âAPI Keysâ on the left side nav and create an API key: copy âEnvironmentâ value to PINECONE_ENVIRONMENT
variable, and âValueâ to PINECONE_API_KEY
d. Add secrets to the convex dashboard
npx convex dashboard
Go to âsettingsâ and add the following environment varables. CLERK_ISSUER_URL
should be the URL from the JWKS endpoint.
OPENAI_API_KEY sk-*******
CLERK_ISSUER_URL https://****
PINECONE_API_KEY ********
PINECONE_ENVIRONMENT us****
PINECONE_INDEX_NAME ********
To run both the front and and back end:
npm run dev
You can now visit [ [http://localhost:[PORT_NUMBER]](http://localhost:[PORT_NUMBER]/)
If](http://localhost:[PORT_NUMBER]](http://localhost:[PORT_NUMBER]/)
If) youâd rather run the frontend in a separate terminal from Convex (which syncs your backend functions as theyâre saved), you can run these two commands:
npm run dev:frontend
npm run dev:backend
See package.json for details, but dev:backend runs npx convex dev
*Note: The simulation will pause after 5 minutes if the window is idle. Loading the page will unpause it. If you want to run the world without the browser, you can comment-out the heartbeat check in convex/engine.ts
To add a new world, seed it, and start it running
Note: you can add --no-push
to run these commands without first syncing the functions. If you already have npm run dev
running, this will be faster. If you remove it, itâll push up the latest version of code before running the command.
npx convex run init:reset
To go one iteration at a time, you can create a world with
` npx convex run --no-push init:resetFrozen
npx convex run --no-push engine:tick '{"worldId":"
To freeze the back end, in case of too much activity
` npx convex run --no-push engine:freezeAll
npx convex run --no-push engine:unfreeze `
To clear all databases
Many options:
npx convex dashboard
and clear tables from there.crons.ts
to automatically clear up space from old journal and memory entries.npx convex run --no-push testing:debugClearAll
to wipe all the tables.origin/reset-town
git branch. Doing npm run dev
from there will clear your schema, stop your functions, and allow you to delete your tables in the dashboard.To delete all vectors from the Pinecone index, you can run:
npx convex run --no-push lib/pinecone:deleteAllVectors
NOTE: If you share this index between dev & prod, or between projects, it will wipe them all out. You generally donât need to be deleting vectors from Pinecone, as each query is indexed on the userId, which is unique between worlds and backend instances.
To Snoop on messages
Run the following in a side terminal
npx convex run testing:listMessages --no-push --watch
Or to watch one playerâs state:
npx convex run testing:latestPlayer --no-push --watch
See more functions in testing.ts
.
fly auth login
.
- Run npx convex deploy
to deploy your dev environment to prod environment. Make sure you copy over all secrets to Convexâs prod environmentfly launch
under project root. This will generate a fly.toml
that includes all the configurations you will needModify generated fly.toml
to include NEXT_PUBLIC_*
during build time for NextJS to access client side.
[build]
[build.args]
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL="/"
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL="/"
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_*****"
NEXT_PUBLIC_CONVEX_URL="https://*******.convex.cloud"
- Modify fly.ioâs generated Dockerfile
to include new ENV variables right above RUN npm run build
` ARG NEXT_PUBLIC_CLERK_SIGN_IN_URL ARG NEXT_PUBLIC_CLERK_SIGN_UP_URL ARG NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL ARG NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ARG NEXT_PUBLIC_CONVEX_URL
RUN npm run build `
- Run fly deploy --ha=false
to deploy the app. The âha flag makes sure fly only spins up one instance, which is included in the free plan.
- Run fly scale memory 512
to scale up the fly vm memory for this app.
- Create a new file .env.prod
locally and fill in all the production-environment secrets. Remember to update NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
and CLERK_SECRET_KEY
by copying secrets from Clerkâs production instance - cat .env.prod | fly secrets import
to upload secrets. Also remember to update CONVEX_DEPLOYMENT
and NEXT_PUBLIC_CONVEX_URL
.
NOTE: every time you change character data, you should re-run npx convex run testing:debugClearAll --no-push
and then npm run dev
to re-upload everything to Convex. This is because character data is sent to Convex on the initial load. However, beware that npx convex run testing:debugClearAll --no-push
WILL wipe all of your data, including your vector store.
Updating spritesheets: in data.ts
, you will see this code:
{
name: 'f1',
textureUrl: '/assets/32x32folk.png',
spritesheetData: f1SpritesheetData,
speed: 0.1,
},...
You should find a sprite sheet for your character, and define sprite motion / assets in the corresponding file (in the above example, f1SpritesheetData
was defined in f1.ts)
convex/maps/firstmap.ts
is where the map gets loaded. The easiest way to export a tilemap is by using Tiled â Tiled exports tilemaps as a CSV and you can convert CSV to a 2d array accepted by firstmap.tsVisit Official Website