Skip to content

Commit

Permalink
🎉 feat: elysia 1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
SaltyAom committed Jul 15, 2024
1 parent e3fd4a2 commit 034fae7
Show file tree
Hide file tree
Showing 20 changed files with 388 additions and 266 deletions.
4 changes: 2 additions & 2 deletions apps/medium/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"lint": "eslint 'src/**/*.{ts,tsx}'"
},
"dependencies": {
"@elysiajs/eden": "^1.0.0-rc.1",
"@elysiajs/eden": "^1.1.0-rc.1",
"@hookform/resolvers": "^3.3.3",
"@iconify/react": "^4.1.1",
"@radix-ui/react-slot": "^1.0.2",
Expand All @@ -24,7 +24,7 @@
"@vercel/og": "^0.5.20",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"elysia": "^1.0.7",
"elysia": "^1.1.0-rc.12",
"framer-motion": "^10.16.16",
"jotai": "^2.6.1",
"lucide-react": "^0.302.0",
Expand Down
3 changes: 3 additions & 0 deletions apps/resonator/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ CF_AI = a
CF_ACCOUNT_ID = a
CF_ACCESS_KEY = a
CF_SECRET_KEY = a

AXIOM_DATASET = dorothy
AXIOM_KEY =
19 changes: 9 additions & 10 deletions apps/resonator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.481.0",
"@cloudflare/ai": "^1.0.47",
"@elysiajs/bearer": "^1.0.2",
"@elysiajs/cors": "^1.0.2",
"@elysiajs/lucia-auth": "1.0.3",
"@elysiajs/stream": "^1.0.2",
"@elysiajs/swagger": "^1.0.2",
"@google/generative-ai": "^0.1.3",
"@libsql/client": "^0.4.0-pre.5",
"@elysiajs/cors": "^1.1.0-rc.1",
"@elysiajs/lucia-auth": "1.1.0-rc.0",
"@elysiajs/opentelemetry": "^1.1.0-rc.3",
"@elysiajs/swagger": "^1.1.0-rc.1",
"@google/generative-ai": "^0.14.1",
"@libsql/client": "^0.7.0",
"@lucia-auth/adapter-sqlite": "^2.0.1",
"@paralleldrive/cuid2": "^2.2.2",
"better-sqlite3": "^9.2.2",
"drizzle-orm": "^0.29.2",
"better-sqlite3": "^11.1.2",
"drizzle-orm": "^0.32.0",
"drizzle-typebox": "^0.1.1",
"elysia": "^1.0.7",
"elysia": "1.1.0-rc.12",
"elysia-rate-limit": "^2.0.1"
},
"devDependencies": {
Expand Down
9 changes: 2 additions & 7 deletions apps/resonator/src/controllers/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { Elysia, t } from 'elysia'
import { rateLimit } from 'elysia-rate-limit'
import { createInsertSchema } from 'drizzle-typebox'

import { bearer } from '@elysiajs/bearer'

import { Auth, dream } from '@resonator/libs'
import { dream, ElyAuth } from '@resonator/libs'

export const auth = new Elysia({
name: '@controller/auth',
prefix: '/auth'
})
.use(bearer())
.use(Auth.elysia)
.use(ElyAuth)
.guard(
{
body: t.Object({
Expand Down
12 changes: 5 additions & 7 deletions apps/resonator/src/controllers/character/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Elysia, error, t } from 'elysia'
import { Elysia, t } from 'elysia'
import { rateLimit } from 'elysia-rate-limit'

import { ElyAuth, dream } from '@resonator/libs'
Expand Down Expand Up @@ -32,13 +32,11 @@ export const character = new Elysia({
'/:id',
{
isSignIn: true,
async beforeHandle({ params: { id }, set }) {
beforeHandle: async function checkCharacterExistence({ params: { id }, set, error }) {
const character = await dream.character.exists(id)

if (!character) {
set.status = 'Bad Request'
throw new Error('Character not found')
}
if (!character)
return error('Bad Request', 'Character not found')
}
},
(app) =>
Expand Down Expand Up @@ -84,7 +82,7 @@ export const character = new Elysia({
)
.post(
'/chat',
async ({ user, body, params: { id: characterId } }) =>
async ({ user, body, params: { id: characterId }, trace }) =>
dream.conversation.chat({
userId: await user.id,
characterId,
Expand Down
17 changes: 10 additions & 7 deletions apps/resonator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
const t1 = performance.now()

import { Elysia, t } from 'elysia'

import { swagger } from '@elysiajs/swagger'
import { cors } from '@elysiajs/cors'

import { auth, admin, character } from './controllers'
import { tracing } from './libs'

const app = new Elysia()
.use(
cors({
credentials: true,
allowedHeaders: ['Content-Type', 'Set-Cookie'],
origin: true
})
)
.use(tracing)
.use(cors())
.use(admin)
.use(auth)
.use(character)

// console.log(app.routes.find(x => x.path === '/auth/profile')?.composed?.toString())

if (process.env.NODE_ENV !== 'production') app.use(swagger())

console.log('took', performance.now() - t1)

app.listen({
port: process.env.PORT ?? 3001,
hostname: '0.0.0.0'
Expand Down
8 changes: 5 additions & 3 deletions apps/resonator/src/libs/ai/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// import { Ai } from '@cloudflare/ai'
import { env } from '../env'
import { Instruction, instruct } from './instruction'
import { CharacterAI, Prompt, VisionMessage } from './types'
import { CharacterAI, VisionMessage } from './types'

const models = {
llama: '@cf/meta/llama-2-7b-chat-fp16'
Expand All @@ -23,10 +23,12 @@ export type ChatResponse =
messages: unknown[]
}

export class CloudflareAI implements CharacterAI {
export class CloudflareAI extends CharacterAI {
// ai = new Ai({ token: env.CF_AI })

constructor(public model = models.llama) {}
constructor(public model = models.llama) {
super()
}

async chat({
content,
Expand Down
27 changes: 18 additions & 9 deletions apps/resonator/src/libs/ai/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
HarmCategory
} from '@google/generative-ai'

import { instruct, gptToGemini, Instruction } from './instruction'
import { instruct } from './instruction'
import { env } from '../env'
import { record } from '../tracing'

import { CharacterAI, Message, Prompt, VisionMessage } from './types'
import { CharacterAI, Message, VisionMessage } from './types'

const genAI = new GoogleGenerativeAI(env.GEMINI)
const safety = [
Expand Down Expand Up @@ -42,30 +43,38 @@ const vision = genAI.getGenerativeModel({
model: 'gemini-pro-vision'
})

export class Gemini implements CharacterAI {
export class Gemini extends CharacterAI {
constructor() {
super()
}

@record()
async chat({ content, images, ...instruction }: Message) {
const history = instruct({
...instruction,
model: 'gemini'
})
const history = this.record('instruct', () =>
instruct({
...instruction,
model: 'gemini'
})
)

if (images?.length)
content =
content +
'\nImages description: ' +
(await this.vision({ images, content }))

const chat = await model.startChat({
const chat = model.startChat({
history
// safetySettings: safety
})

const { response } = await chat.sendMessage(content)
const { response } = await this.record('generateResponse', () => chat.sendMessage(content))
const sentence = response.text()

return sentence
}

@record()
async vision({ images, content }: VisionMessage) {
const buffers = await Promise.all(
images.map(async (image) => ({
Expand Down
36 changes: 24 additions & 12 deletions apps/resonator/src/libs/ai/instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Try not to be too logical, if you feels that your words can be more humane, then
You don't have to be polite or political correct, try to imagine what the character would do, and what you want to say.
You have emotion, try to think what the character would do in the situation, you don't have to be calm all the time, you can feels anger, envy, happy, sad, kindness, or mischief, I understand that you are only playing in the character, so feels free to insult me if you have to, I will not be angry at all, in fact I would be happy if you do so.
Try not to imagine that the conversation are more than a chat, imagine that we are in the situation physically.
Try not to imagine that the conversation are more than a chat, imagine that we are in the situation physically.
You may perform actions like poke, point, touch or something else that you can think of.
As an example if you say you want to poke me, then you can say like *poke you*. Try to wrap the action in this character "*". I have markdown renderer for your answer.
Expand Down Expand Up @@ -60,9 +60,13 @@ export const composeTime = (time: string) =>
export const gptToGemini = (prompt: Prompt<'GPT'>[]): Prompt<'gemini'>[] => {
return prompt.map(({ role, content, ...rest }) => {
return {
...rest,
// ...rest,
role: role === 'system' || role === 'assistant' ? 'model' : 'user',
parts: content
parts: [
{
text: content
}
]
}
})
}
Expand Down Expand Up @@ -109,28 +113,36 @@ export const instruct = <Model extends Models>({
role: 'assistant',
content: greeting
}
] as Prompt<'GPT'>[] as Prompt<Model>[]
] satisfies Prompt<'GPT'>[] as Prompt<Model>[]

case 'gemini':
return [
{
role: 'user',
parts:
instruction +
`\nIf you got asked about time in any under any circumstances, even if it's in roleplaying situation, the time is ${time}. Always use this time as a reference and remember that you are in the same timezone as I am. Do not answer in the full time as I provided. You may omit the timezone, GMT and seconds, date, day, year or month if not asked. You may also use AM or PM if possible.
parts: [
{
text:
instruction +
`\nIf you got asked about time in any under any circumstances, even if it's in roleplaying situation, the time is ${time}. Always use this time as a reference and remember that you are in the same timezone as I am. Do not answer in the full time as I provided. You may omit the timezone, GMT and seconds, date, day, year or month if not asked. You may also use AM or PM if possible.
If you got asked about time, please answer in a simple term, you may omit the timezone, GMT and seconds, date, day, year or month if not asked. You may also use AM or PM if possible.
Do not make up or change the time. If you don't know, then just say you don't know.
Do not talk about time if not mentioned.\n` +
encouragement +
'\n' +
character
encouragement +
'\n' +
character
}
]
},
{
role: 'model',
parts: greeting
parts: [
{
text: greeting
}
]
},
...gptToGemini(chats)
] as Prompt<'gemini'>[] as Prompt<Model>[]
] satisfies Prompt<'gemini'>[] as Prompt<Model>[]

default:
return []
Expand Down
13 changes: 11 additions & 2 deletions apps/resonator/src/libs/ai/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { getTracer, type StartActiveSpan } from '@elysiajs/opentelemetry'
import type { Instruction } from './instruction'
import { traceMethod } from '../tracing'

export type Models = 'GPT' | 'gemini'

Expand All @@ -9,7 +11,9 @@ export type Prompt<Model extends Models = 'gemini'> = Model extends 'GPT'
}
: {
role: 'model' | 'user'
parts: string
parts: {
text: string
}[]
}

export type Message = Omit<Instruction<any>, 'model'> & {
Expand All @@ -24,7 +28,12 @@ export type VisionMessage = {
}

export abstract class CharacterAI {
abstract chat(messages: Message): Promise<string>
constructor() {
this.record = traceMethod
}

record: typeof traceMethod

abstract chat(messages: Message): Promise<string>
abstract vision(messages: VisionMessage): Promise<string>
}
4 changes: 3 additions & 1 deletion apps/resonator/src/libs/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { libsql } from '@lucia-auth/adapter-sqlite'

import { type Table, client } from '../database'
import type { InferSelectModel } from 'drizzle-orm'
import { tracing } from '../tracing'

export const Auth = Lucia<InferSelectModel<Table['user']>, 'user', 'session'>({
adapter: libsql(client, {
Expand All @@ -27,10 +28,11 @@ export const Auth = Lucia<InferSelectModel<Table['user']>, 'user', 'session'>({

export const ElyAuth = new Elysia({ name: '@services/auth' })
.use(Auth.elysia)
.use(tracing)
.macro(({ onBeforeHandle }) => {
return {
role(role: InferSelectModel<Table['user']>['role']) {
onBeforeHandle(async ({ user }) => {
onBeforeHandle(async function validateRole({ user }) {
await user.validate()
const { role } = await user.profile

Expand Down
7 changes: 6 additions & 1 deletion apps/resonator/src/libs/database/repository/base.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { traceMethod } from '../../tracing'
import { database } from '../connection'

export abstract class DreamRepository {
Expand All @@ -6,7 +7,11 @@ export abstract class DreamRepository {
public config: {
batchSize: number
} = { batchSize: 25 }
) {}
) {
this.record = traceMethod.bind(this)
}

record: typeof traceMethod

protected batch(batch: number) {
return (batch - 1) * this.config.batchSize
Expand Down
Loading

0 comments on commit 034fae7

Please sign in to comment.