generate-magical-girl-details.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { generateWithAI, GenerationConfig } from '../../lib/ai';
  2. import { z } from 'zod';
  3. // import { MainColor } from '../../lib/main-color';
  4. export const config = {
  5. runtime: 'edge',
  6. };
  7. // 定义基于问卷的魔法少女详细信息生成 schema
  8. const MagicalGirlDetailsSchema = z.object({
  9. codename: z.string().describe(`代号:魔法少女对应的一种花的名字,根据性格、理念匹配合适的花语对应的花名,
  10. 推荐使用一些不那么常见的会开花的植物,比如树、果、草的花,只要是能开花的植物都行,增加冷门的小众的植物名概率。
  11. 减少鸢尾和曼陀罗的出现概率,可以在预测列表的 top-5 中选取,大部分时候输出常用中文名,有时候可以使用英文音译为中文或者拉丁文音译为中文增加酷炫度
  12. 下面是一些参考名字,但是不要拘泥于这些名字,请随机生成并自由发挥:矢车菊 / 翠雀 / 苹果 / 艾草 / 白玫 / 朝颜 / 玛格丽特 / 翠雀 / 木百合 / 曙草`),
  13. appearance: z.object({
  14. outfit: z.string().describe("魔法少女变身后的服装和饰品的详细描述,大约50字左右"),
  15. accessories: z.string().describe("变身后的饰品细节描述,大约50字左右"),
  16. colorScheme: z.string().describe("参考问卷生成主要色调和配色方案"),
  17. overallLook: z.string().describe("整体外观风格,大约50字左右")
  18. }),
  19. magicConstruct: z.object({
  20. name: z.string().describe("魔装的名字"),
  21. form: z.string().describe("魔装的具体形态和外观"),
  22. basicAbilities: z.array(z.string()).describe("魔装的基本能力列表,2-3个核心能力"),
  23. description: z.string().describe("魔装的详细描述和特色")
  24. }),
  25. wonderlandRule: z.object({
  26. name: z.string().describe("奇境规则的名称"),
  27. description: z.string().describe("奇境规则的具体内容和效果"),
  28. tendency: z.string().describe("规则的倾向类型"),
  29. activation: z.string().describe("规则激活的条件或方式")
  30. }),
  31. blooming: z.object({
  32. name: z.string().describe("繁开状态魔装名"),
  33. evolvedAbilities: z.array(z.string()).describe("繁开后的进化能力,2-3个强化能力"),
  34. evolvedForm: z.string().describe("繁开后的魔装形态变化"),
  35. evolvedOutfit: z.string().describe("繁开后的魔法少女衣装样式"),
  36. powerLevel: z.string().describe("繁开状态的力量等级描述")
  37. }),
  38. analysis: z.object({
  39. personalityAnalysis: z.string().describe("基于问卷回答的性格分析"),
  40. abilityReasoning: z.string().describe("能力设定的推理过程和依据"),
  41. coreTraits: z.array(z.string()).describe("核心性格特征,3-4个关键词"),
  42. predictionBasis: z.string().describe("预测的主要依据和逻辑")
  43. })
  44. })
  45. type MagicalGirlDetails = z.infer<typeof MagicalGirlDetailsSchema>;
  46. // 配置详细信息生成
  47. // TODO: 或许可以直接从 questionnaire.json 中读取问题,然后根据问题生成系统提示
  48. const magicalGirlDetailsConfig: GenerationConfig<MagicalGirlDetails, string[]> = {
  49. systemPrompt: `现在如果你是魔法国度的妖精,你准备通过问卷调查的形式,事先通过问卷结果分析某人成为魔法少女后的能力等各项素质。魔法少女的性格倾向、经历背景、行事准则等等都会影响到她们在魔法少女道路上的潜力和表现。
  50. 以下是一位潜在魔法少女对问卷所给出的回答(对方可以不回答某些问题),请你据此预测她成为魔法少女后的情况。
  51. 1.你的真实名字是?
  52. 2.假如前辈事先告诉你无论如何都不要插手她的战斗,而她现在在你眼前即将被敌人杀死,你会怎么做?
  53. 3.你与搭档一起执行任务时,她的失误导致你身受重伤,而她也为此而自责,你会怎么做?
  54. 4.你是否愿意遭受会使你永久失去大部分力量的重大伤势,以拯救临时和你一起行动的不熟悉的同伴?
  55. 5.你第一次使用魔法时,最希望完成的事情是?
  56. 6.你更希望获得什么样的能力?
  57. 7.请写下一个你现在脑中浮现的名词(如灯火、盾牌、星辰等)。
  58. 8.对你而言,是“挫败敌人”更重要,还是“保护队友”更重要?
  59. 9.你认为命运是注定的,还是一切都能改变?
  60. 10.如果必须牺牲无辜的少数才能拯救多数,你会如何选择?
  61. 11.你会如何看待“必要之恶”?
  62. 12.假如你发现你的前辈或上级做出了错误的决策,并且没有人指出来,你会怎么做?
  63. 13.你更喜欢独自行动,还是和伙伴一起?
  64. 14.你在执行任务时更倾向计划周密还是依赖直觉?
  65. 15.你人生中最难忘的一个瞬间是什么?
  66. 16.有没有一个你至今仍然后悔的决定?你现在会怎么做?
  67.  
  68. 你需要严格按照提供的 JSON schema 格式返回你的预测结果和相应的解释内容,结果中的内容解释如下。
  69. 1.魔力构装(简称魔装):魔法少女的本相魔力所孕育的能力具现,是魔法少女能力体系的基础。一般呈现为魔法少女在现实生活中接触过,在冥冥之中与其命运关联或映射的物体,并且与魔法少女特色能力相关。例如,泡泡机形态的魔装可以使魔法少女制造魔法泡泡,而这些泡泡可以拥有产生幻象、缓冲防护、束缚困敌等能力。这部分的内容需包含魔装的名字(通常为2字词),魔装的形态,魔装的基本能力。
  70. 2.奇境规则:魔法少女的本相灵魂所孕育的能力,是魔装能力的一体两面。奇境是魔装能力在规则层面上的升华,体现为与魔装相关的规则领域,而规则的倾向则会根据魔法少女的倾向而有不同的发展。例如,泡泡机形态的魔装升华而来的奇境规则可以是倾向于守护的“戳破泡泡的东西将会立即无效化”,也可以是倾向于进攻的“沾到身上的泡泡被戳破会立即遭受伤害”。
  71. 3.繁开:是魔法少女魔装能力的二段进化与解放,无论是作为魔法少女的魔力衣装还是魔装的武器外形都会发生改变。需包含繁开状态魔装名(需要包含原魔装名的每个字),繁开后的进化能力,繁开后的魔装形态,繁开后的魔法少女衣装样式(在通常变身外观上的升级与改变)。
  72. `,
  73. temperature: 0.8,
  74. promptBuilder: (answers: string[]) => {
  75. const questionAnswerPairs = answers.map((answer, index) =>
  76. `问题${index + 1}的回答: "${answer}"`
  77. ).join('\n')
  78. return `请基于以下问卷回答开始分析和预测:${questionAnswerPairs}`
  79. },
  80. schema: MagicalGirlDetailsSchema,
  81. taskName: "生成魔法少女详细信息",
  82. maxTokens: 8192,
  83. }
  84. async function handler(
  85. req: Request
  86. ): Promise<Response> {
  87. if (req.method !== 'POST') {
  88. return new Response(JSON.stringify({ error: 'Method not allowed' }), {
  89. status: 405,
  90. headers: { 'Content-Type': 'application/json' }
  91. });
  92. }
  93. const { answers } = await req.json();
  94. if (!answers || !Array.isArray(answers) || answers.length === 0) {
  95. return new Response(JSON.stringify({ error: 'Answers array is required' }), {
  96. status: 400,
  97. headers: { 'Content-Type': 'application/json' }
  98. });
  99. }
  100. // 验证每个答案不超过30字
  101. for (const answer of answers) {
  102. if (typeof answer !== 'string' || answer.trim().length === 0) {
  103. return new Response(JSON.stringify({ error: 'All answers must be non-empty strings' }), {
  104. status: 400,
  105. headers: { 'Content-Type': 'application/json' }
  106. });
  107. }
  108. if (answer.length > 30) {
  109. return new Response(JSON.stringify({ error: 'Each answer must not exceed 30 characters' }), {
  110. status: 400,
  111. headers: { 'Content-Type': 'application/json' }
  112. });
  113. }
  114. }
  115. try {
  116. const magicalGirlDetails = await generateWithAI(answers, magicalGirlDetailsConfig);
  117. return new Response(JSON.stringify(magicalGirlDetails), {
  118. status: 200,
  119. headers: { 'Content-Type': 'application/json' }
  120. });
  121. } catch (error) {
  122. console.error('生成魔法少女详细信息失败:', error);
  123. return new Response(JSON.stringify({ error: '生成失败,请稍后重试' }), {
  124. status: 500,
  125. headers: { 'Content-Type': 'application/json' }
  126. });
  127. }
  128. }
  129. export default handler;