feat: add support for temperature, top_p to be configurable (#2200)
Co-authored-by: twix03 <sathwikbalaa@gmail.com> Co-authored-by: RainbowBird <git@luoling.moe>
This commit is contained in:
co-authored by
twix03
RainbowBird
parent
66c6aa9b57
commit
e293b71abc
@@ -1,5 +1,5 @@
|
||||
import { createInsertSchema, createSelectSchema } from 'drizzle-valibot'
|
||||
import { array, literal, number, object, optional, pipe, string, transform, union } from 'valibot'
|
||||
import { array, literal, number, object, optional, string, union } from 'valibot'
|
||||
|
||||
import * as schema from '../../schemas/characters'
|
||||
|
||||
@@ -17,6 +17,7 @@ export const CharacterCapabilityConfigSchema = object({
|
||||
apiBaseUrl: string(),
|
||||
llm: optional(object({
|
||||
temperature: number(),
|
||||
topP: optional(number()),
|
||||
model: string(),
|
||||
})),
|
||||
tts: optional(object({
|
||||
@@ -63,11 +64,6 @@ export const InsertCharacterCoverSchema = createInsertSchema(schema.characterCov
|
||||
export const CharacterPromptSchema = createSelectSchema(schema.characterPrompts)
|
||||
export const InsertCharacterPromptSchema = createInsertSchema(schema.characterPrompts)
|
||||
|
||||
const DateSchema = pipe(
|
||||
string(),
|
||||
transform(v => new Date(v)),
|
||||
)
|
||||
|
||||
export const CreateCharacterSchema = object({
|
||||
// TODO: Replace createInsertSchema-derived request bodies with explicit HTTP DTO schemas.
|
||||
// The current shape still leaks persistence fields such as ownerId/creatorId into the API boundary.
|
||||
@@ -102,16 +98,13 @@ export const CreateCharacterSchema = object({
|
||||
|
||||
// TODO: Split update request schema from DB insert schema.
|
||||
// This route should reject server-managed fields like id/ownerId/creatorId/timestamps instead of allowing them here.
|
||||
export const UpdateCharacterSchema = createInsertSchema(schema.character, {
|
||||
id: optional(string()),
|
||||
export const UpdateCharacterSchema = object({
|
||||
version: optional(string()),
|
||||
coverUrl: optional(string()),
|
||||
avatarUrl: optional(string()),
|
||||
creatorRole: optional(string()),
|
||||
priceCredit: optional(string()),
|
||||
creatorId: optional(string()),
|
||||
ownerId: optional(string()),
|
||||
characterId: optional(string()),
|
||||
createdAt: optional(DateSchema),
|
||||
updatedAt: optional(DateSchema),
|
||||
capabilities: optional(array(createInsertSchema(schema.characterCapabilities, {
|
||||
characterId: optional(string()),
|
||||
type: CharacterCapabilityTypeSchema,
|
||||
config: CharacterCapabilityConfigSchema,
|
||||
}))),
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Database } from '../../libs/db'
|
||||
import type { EngagementMetrics } from '../../otel'
|
||||
|
||||
import { useLogger } from '@guiiai/logg'
|
||||
import { and, eq, isNull, or, sql } from 'drizzle-orm'
|
||||
import { and, eq, inArray, isNull, or, sql } from 'drizzle-orm'
|
||||
|
||||
import * as schema from '../../schemas/characters'
|
||||
import * as userCharacterSchema from '../../schemas/user-character'
|
||||
@@ -190,16 +190,60 @@ export function createCharacterService(db: Database, metrics?: EngagementMetrics
|
||||
return inserted
|
||||
},
|
||||
|
||||
async update(id: string, data: Partial<schema.NewCharacter>) {
|
||||
// TODO: Return a stable single-object response shape for HTTP callers.
|
||||
// leaking Drizzle returning() arrays across the service boundary makes route contracts drift.
|
||||
const result = await db.update(schema.character)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(and(
|
||||
eq(schema.character.id, id),
|
||||
isNull(schema.character.deletedAt),
|
||||
))
|
||||
.returning()
|
||||
async update(id: string, data: {
|
||||
version?: string
|
||||
coverUrl?: string
|
||||
characterId?: string
|
||||
capabilities?: {
|
||||
type: 'llm' | 'tts' | 'vlm' | 'asr'
|
||||
config: any
|
||||
}[]
|
||||
}) {
|
||||
const { capabilities, ...characterData } = data
|
||||
|
||||
const result = await db.transaction(async (tx) => {
|
||||
let updatedChar
|
||||
if (Object.keys(characterData).length > 0) {
|
||||
const [res] = await tx.update(schema.character)
|
||||
.set({ ...characterData, updatedAt: new Date() })
|
||||
.where(and(
|
||||
eq(schema.character.id, id),
|
||||
isNull(schema.character.deletedAt),
|
||||
))
|
||||
.returning()
|
||||
updatedChar = res
|
||||
}
|
||||
|
||||
if (capabilities) {
|
||||
const submittedTypes = capabilities.map(c => c.type)
|
||||
if (submittedTypes.length > 0) {
|
||||
await tx.delete(schema.characterCapabilities)
|
||||
.where(and(
|
||||
eq(schema.characterCapabilities.characterId, id),
|
||||
inArray(schema.characterCapabilities.type, submittedTypes),
|
||||
))
|
||||
|
||||
await tx.insert(schema.characterCapabilities).values(
|
||||
capabilities.map(c => ({ ...c, characterId: id })),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedChar) {
|
||||
return updatedChar
|
||||
}
|
||||
|
||||
const fallback = await tx.query.character.findFirst({
|
||||
where: and(
|
||||
eq(schema.character.id, id),
|
||||
isNull(schema.character.deletedAt),
|
||||
),
|
||||
})
|
||||
if (!fallback)
|
||||
throw new Error('Character not found')
|
||||
return fallback
|
||||
})
|
||||
|
||||
logger.withFields({ id }).log('Updated character')
|
||||
return result
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ interface CharacterCapabilityBaseConfig {
|
||||
export interface CharacterCapabilityConfig extends CharacterCapabilityBaseConfig {
|
||||
llm: {
|
||||
temperature: number
|
||||
topP?: number
|
||||
model: string
|
||||
}
|
||||
tts: {
|
||||
|
||||
Reference in New Issue
Block a user