feat: add neo4j and prompt and prompt-graph
This commit is contained in:
parent
25c055b490
commit
229ad7caed
@ -1 +1 @@
|
|||||||
Subproject commit d1e2306233fde79b510dec614a95f867d686243d
|
Subproject commit f1346b3cef6684707bcd4faec20231e535904486
|
@ -2,14 +2,14 @@ import { App } from '@abearxiong/router';
|
|||||||
import { useConfig } from '@abearxiong/use-config';
|
import { useConfig } from '@abearxiong/use-config';
|
||||||
import { dynamicImport } from './lib/dynamic-import.ts';
|
import { dynamicImport } from './lib/dynamic-import.ts';
|
||||||
import { redisPublisher, redisSubscriber, redis } from './modules/redis.ts';
|
import { redisPublisher, redisSubscriber, redis } from './modules/redis.ts';
|
||||||
import { neode } from './modules/neo4j.ts';
|
import { neode, getSession } from './modules/neo4j.ts';
|
||||||
import { minioClient } from './modules/minio.ts';
|
import { minioClient } from './modules/minio.ts';
|
||||||
import { sequelize } from './modules/sequelize.ts';
|
import { sequelize } from './modules/sequelize.ts';
|
||||||
useConfig();
|
useConfig();
|
||||||
export const emit = (channel: string, message?: any) => {
|
export const emit = (channel: string, message?: any) => {
|
||||||
redisPublisher.publish(channel, JSON.stringify(message));
|
redisPublisher.publish(channel, JSON.stringify(message));
|
||||||
};
|
};
|
||||||
export { neode, redis, minioClient, sequelize };
|
export { neode, getSession, redis, minioClient, sequelize };
|
||||||
|
|
||||||
export const app = new App<{ import: any; emit: typeof emit }>({
|
export const app = new App<{ import: any; emit: typeof emit }>({
|
||||||
serverOptions: {
|
serverOptions: {
|
||||||
|
@ -90,7 +90,7 @@ RouterCodeModel.init(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize,
|
sequelize,
|
||||||
tableName: 'cf_router_code',
|
tableName: 'cf_router_code', // container flow router code
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
RouterCodeModel.sync({ alter: true, logging: false }).catch((e) => {
|
RouterCodeModel.sync({ alter: true, logging: false }).catch((e) => {
|
||||||
|
83
src/models/prompt-graph.ts
Normal file
83
src/models/prompt-graph.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { neode } from '@/app.ts';
|
||||||
|
import { getSession } from '@/modules/neo4j.ts';
|
||||||
|
import Neode from 'neode';
|
||||||
|
|
||||||
|
export const PromptNeo = neode.model('Prompt', {
|
||||||
|
id: {
|
||||||
|
type: 'uuid',
|
||||||
|
primary: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
description: 'string',
|
||||||
|
// profile: { type: 'object', optional: true }, // 用于存储 JSON 对象
|
||||||
|
prompt: 'string',
|
||||||
|
// inputVariables: { type: 'array', item },
|
||||||
|
// tags: { type: 'array', items: 'string', optional: true } // 定义字符串数组
|
||||||
|
inputVariables: { type: 'string', default: JSON.stringify([]) },
|
||||||
|
localVariables: { type: 'string', default: JSON.stringify([]) },
|
||||||
|
|
||||||
|
// 定义可单向或双向的关系
|
||||||
|
relatedPrompts: {
|
||||||
|
type: 'relationship',
|
||||||
|
relationship: 'RELATED_TO',
|
||||||
|
target: 'Prompt', // 指向自身
|
||||||
|
direction: 'out', // 默认是单向的
|
||||||
|
properties: {
|
||||||
|
created_at: 'datetime',
|
||||||
|
bidirectional: 'boolean', // 用来标记该关系是否为双向
|
||||||
|
},
|
||||||
|
eager: true, // 自动加载相关的 Prompts
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export async function createRelationship(promptA: Neode.Node<unknown>, promptB: Neode.Node<unknown>, isBidirectional = false) {
|
||||||
|
// 创建单向关系
|
||||||
|
await promptA.relateTo(promptB, 'RELATED_TO', { created_at: new Date(), bidirectional: isBidirectional });
|
||||||
|
|
||||||
|
// 如果是双向关系,创建反向关系
|
||||||
|
if (isBidirectional) {
|
||||||
|
await promptB.relateTo(promptA, 'RELATED_TO', { created_at: new Date(), bidirectional: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function createRelationship2(promptId1, promptId2, isBidirectional = false) {
|
||||||
|
const query = `
|
||||||
|
MATCH (p1:Prompt {id: $id1}), (p2:Prompt {id: $id2})
|
||||||
|
CREATE (p1)-[r:RELATED_TO {created_at: $createdAt, bidirectional: $bidirectional}]->(p2)
|
||||||
|
RETURN r
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await getSession().run(query, {
|
||||||
|
id1: promptId1,
|
||||||
|
id2: promptId2,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
|
bidirectional: isBidirectional,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.records[0].get('r');
|
||||||
|
}
|
||||||
|
export async function createPrompt(promptData) {
|
||||||
|
const session = getSession();
|
||||||
|
const query = `
|
||||||
|
CREATE (p:Prompt {
|
||||||
|
id: $id,
|
||||||
|
title: $title,
|
||||||
|
description: $description,
|
||||||
|
prompt: $prompt,
|
||||||
|
inputVariables: $inputVariables,
|
||||||
|
localVariables: $localVariables
|
||||||
|
})
|
||||||
|
RETURN p
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await session.run(query, {
|
||||||
|
id: promptData.id,
|
||||||
|
title: promptData.title,
|
||||||
|
description: promptData.description,
|
||||||
|
prompt: promptData.prompt,
|
||||||
|
inputVariables: JSON.stringify(promptData.inputVariables || []),
|
||||||
|
localVariables: JSON.stringify(promptData.localVariables || []),
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.records[0].get('p');
|
||||||
|
}
|
@ -1,18 +1,65 @@
|
|||||||
import { neode } from '@/app.ts';
|
import { sequelize } from '../modules/sequelize.ts';
|
||||||
|
import { DataTypes, Model } from 'sequelize';
|
||||||
|
import { Variable } from '@kevisual/ai-graph';
|
||||||
|
|
||||||
export const PromptNeo = neode.model('Prompt', {
|
/**
|
||||||
id: {
|
* 预设数据,定义了请求的内容和验证器
|
||||||
type: 'uuid',
|
*/
|
||||||
primary: true,
|
export type PresetData = {
|
||||||
|
// 参数
|
||||||
|
validator: {
|
||||||
|
[key: string]: any; // 请求的内容的验证器
|
||||||
|
};
|
||||||
|
data: {
|
||||||
|
prompt?: string; // 提前预设值
|
||||||
|
inputs: Variable & { operate?: string }[]; // 请求内容的变量和内容
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export class Prompt extends Model {
|
||||||
|
declare id: string;
|
||||||
|
declare title: string;
|
||||||
|
declare description: string;
|
||||||
|
declare presetData: PresetData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Prompt.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
primaryKey: true,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
presetData: {
|
||||||
|
type: DataTypes.JSON,
|
||||||
|
},
|
||||||
|
key: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
// inputVariables: {
|
||||||
|
// type: DataTypes.JSON,
|
||||||
|
// defaultValue: [],
|
||||||
|
// },
|
||||||
|
// localVariables: {
|
||||||
|
// type: DataTypes.JSON,
|
||||||
|
// defaultValue: [],
|
||||||
|
// },
|
||||||
},
|
},
|
||||||
title: {
|
{
|
||||||
type: 'string',
|
sequelize, // 传入 Sequelize 实例
|
||||||
|
modelName: 'prompt', // 模型名称
|
||||||
},
|
},
|
||||||
description: 'string',
|
);
|
||||||
// profile: { type: 'object', optional: true }, // 用于存储 JSON 对象
|
|
||||||
prompt: 'string',
|
Prompt.sync({ alter: true, force: false, logging: false }).catch((e) => {
|
||||||
// inputVariables: { type: 'array', item },
|
console.error('Prompt sync error', e);
|
||||||
// tags: { type: 'array', items: 'string', optional: true } // 定义字符串数组
|
|
||||||
inputVariables: { type: 'string', default: JSON.stringify([]) },
|
|
||||||
localVariables: { type: 'string', default: JSON.stringify([]) },
|
|
||||||
});
|
});
|
||||||
|
@ -1,17 +1,26 @@
|
|||||||
import Neode from 'neode';
|
import Neode from 'neode';
|
||||||
import { useConfig } from '@abearxiong/use-config';
|
import { useConfig } from '@abearxiong/use-config';
|
||||||
|
import neo4j from 'neo4j-driver';
|
||||||
|
|
||||||
type NeodeConfig = {
|
type NeodeConfig = {
|
||||||
uri: string;
|
uri: string;
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
};
|
};
|
||||||
const { neo4j } = useConfig<{ neo4j: NeodeConfig }>('neo4j');
|
const { neo4j: neo4jConfig } = useConfig<{ neo4j: NeodeConfig }>('neo4j');
|
||||||
|
|
||||||
const { uri, username, password } = neo4j;
|
const { uri, username, password } = neo4jConfig;
|
||||||
// 设置连接配置
|
// 设置连接配置
|
||||||
// const neode = new Neode('bolt://localhost:7687', 'neo4j', 'your_password');
|
// const neode = new Neode('bolt://localhost:7687', 'neo4j', 'your_password');
|
||||||
export const neode = new Neode(uri, username, password);
|
export const neode = new Neode(uri, username, password);
|
||||||
|
// 创建与 Neo4j 数据库的连接
|
||||||
|
export const neoDriver = neo4j.driver(
|
||||||
|
uri, // 数据库地址
|
||||||
|
neo4j.auth.basic(username, password), // 用户名和密码
|
||||||
|
);
|
||||||
|
export const getSession = () => {
|
||||||
|
return neoDriver.session();
|
||||||
|
};
|
||||||
|
|
||||||
const testConnect = async () => {
|
const testConnect = async () => {
|
||||||
// 连接成功
|
// 连接成功
|
||||||
|
@ -3,7 +3,7 @@ import { Ollama, Message, ChatRequest } from 'ollama';
|
|||||||
|
|
||||||
const config = useConfig<{ ollama: Ollama['config'] & { model: string } }>();
|
const config = useConfig<{ ollama: Ollama['config'] & { model: string } }>();
|
||||||
|
|
||||||
const { host } = config.ollama;
|
const { host, model } = config.ollama;
|
||||||
|
|
||||||
export const ollama = new Ollama({ host });
|
export const ollama = new Ollama({ host });
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export const chat = (messages: ChatMessage[], chatOpts?: ChatOpts) => {
|
|||||||
const { options, stream, ...rest } = chatOpts || {};
|
const { options, stream, ...rest } = chatOpts || {};
|
||||||
return ollama.chat({
|
return ollama.chat({
|
||||||
messages,
|
messages,
|
||||||
model: config.model,
|
model: model,
|
||||||
options: {
|
options: {
|
||||||
temperature: 0,
|
temperature: 0,
|
||||||
...chatOpts?.options,
|
...chatOpts?.options,
|
||||||
|
69
src/routes/prompt-graph/ai.ts
Normal file
69
src/routes/prompt-graph/ai.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { app } from '@/app.ts';
|
||||||
|
import { Prompt } from '@/models/prompt.ts';
|
||||||
|
import { chat } from '@/modules/ollama.ts';
|
||||||
|
import { CustomError } from '@abearxiong/router';
|
||||||
|
import { PromptTemplate } from '@kevisual/ai-graph';
|
||||||
|
|
||||||
|
app
|
||||||
|
.route('ai', 'run', { nextRoute: { id: 'runOllama' } })
|
||||||
|
.define({
|
||||||
|
validator: {
|
||||||
|
key: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
message: 'Prompt key is required',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
// ctx.currentRoute?.verify(ctx, true);
|
||||||
|
|
||||||
|
const { key, inputs = [] } = ctx.query.data || {};
|
||||||
|
if (!key) {
|
||||||
|
throw new CustomError('Prompt key is required');
|
||||||
|
}
|
||||||
|
const prompt = await Prompt.findOne({ where: { key } });
|
||||||
|
if (!prompt) {
|
||||||
|
throw new CustomError('Prompt not found');
|
||||||
|
}
|
||||||
|
const { presetData } = prompt;
|
||||||
|
const { data, validator } = presetData || {};
|
||||||
|
// const { inputs = [] } = data;
|
||||||
|
// TODO: 获取validator和inputs的内容
|
||||||
|
const promptTemplate = new PromptTemplate({
|
||||||
|
prompt: data.prompt,
|
||||||
|
inputVariables: inputs.map((item) => {
|
||||||
|
return {
|
||||||
|
key: item.key,
|
||||||
|
value: item.value,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
localVariables: [],
|
||||||
|
});
|
||||||
|
const result = await promptTemplate.getTemplate();
|
||||||
|
ctx.state = {
|
||||||
|
prompt: result,
|
||||||
|
};
|
||||||
|
ctx.body = result;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route('ai', 'runOllama', {
|
||||||
|
id: 'runOllama',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const prompt = ctx.state.prompt;
|
||||||
|
if (!prompt) {
|
||||||
|
throw new CustomError('Prompt not found');
|
||||||
|
}
|
||||||
|
console.log('prompt', typeof prompt, prompt);
|
||||||
|
const res = await chat([
|
||||||
|
{
|
||||||
|
role: 'user',
|
||||||
|
content: prompt,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
ctx.body = res;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
73
src/routes/prompt-graph/d3/get-graph.ts
Normal file
73
src/routes/prompt-graph/d3/get-graph.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { getSession } from '@/app.ts';
|
||||||
|
export async function fetchData() {
|
||||||
|
const session = getSession();
|
||||||
|
try {
|
||||||
|
const query = `MATCH (n)
|
||||||
|
OPTIONAL MATCH (n)-[r]->(m)
|
||||||
|
RETURN n, r, m`;
|
||||||
|
const queryConnect = 'MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 25';
|
||||||
|
const result = await session.run(query);
|
||||||
|
|
||||||
|
const graphData = { nodes: [], links: [] };
|
||||||
|
const nodeMap = new Map();
|
||||||
|
// n和n的关系用 relatedPrompts 进行关联
|
||||||
|
result.records.forEach((record) => {
|
||||||
|
const node = record.get('n');
|
||||||
|
const relation = record.get('r');
|
||||||
|
const target = record.get('m');
|
||||||
|
if (!nodeMap.has(node.identity)) {
|
||||||
|
nodeMap.set(node.identity, {
|
||||||
|
id: node.identity.toString(),
|
||||||
|
label: node.labels[0],
|
||||||
|
properties: node.properties,
|
||||||
|
});
|
||||||
|
graphData.nodes.push(nodeMap.get(node.identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relation && !nodeMap.has(relation.identity)) {
|
||||||
|
nodeMap.set(relation.identity, {
|
||||||
|
id: relation.identity.toString(),
|
||||||
|
label: relation.type,
|
||||||
|
properties: relation.properties,
|
||||||
|
});
|
||||||
|
graphData.nodes.push(nodeMap.get(relation.identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target && !nodeMap.has(target.identity)) {
|
||||||
|
nodeMap.set(target.identity, {
|
||||||
|
id: target.identity.toString(),
|
||||||
|
label: target.labels[0],
|
||||||
|
properties: target.properties,
|
||||||
|
});
|
||||||
|
graphData.nodes.push(nodeMap.get(target.identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relation) {
|
||||||
|
graphData.links.push({
|
||||||
|
source: node.identity.toString(),
|
||||||
|
target: relation.identity.toString(),
|
||||||
|
type: relation.type,
|
||||||
|
properties: relation.properties,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
graphData.links.push({
|
||||||
|
source: node.identity.toString(),
|
||||||
|
target: target.identity.toString(),
|
||||||
|
type: 'RELATED_TO',
|
||||||
|
properties: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return graphData;
|
||||||
|
} finally {
|
||||||
|
await session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchData().then((graphData) => {
|
||||||
|
// console.log(graphData); // 用于验证获取的数据
|
||||||
|
// drawGraph(graphData); // 调用 D3 绘制函数
|
||||||
|
// });
|
@ -1 +1,3 @@
|
|||||||
import './list.ts'
|
import './list-graph.ts';
|
||||||
|
import './list.ts';
|
||||||
|
import './ai.ts';
|
||||||
|
97
src/routes/prompt-graph/list-graph.ts
Normal file
97
src/routes/prompt-graph/list-graph.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { PromptNeo, createRelationship, createRelationship2 } from '@/models/prompt-graph.ts';
|
||||||
|
import { app } from '@/app.ts';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
import { fetchData } from './d3/get-graph.ts';
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'list')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const prompts = await PromptNeo.all();
|
||||||
|
const json = await prompts.toJson();
|
||||||
|
// console.log('json', json);
|
||||||
|
ctx.body = json;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'update')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { id, title, description, prompt, inputVariables, localVariables } = ctx.query;
|
||||||
|
const promptNode = await PromptNeo.first('id', id);
|
||||||
|
|
||||||
|
if (!promptNode) {
|
||||||
|
const promptData = {
|
||||||
|
id: v4(),
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
prompt,
|
||||||
|
inputVariables: JSON.stringify(inputVariables),
|
||||||
|
localVariables: JSON.stringify(localVariables),
|
||||||
|
};
|
||||||
|
const _prompt = await PromptNeo.create(promptData);
|
||||||
|
ctx.body = await _prompt.toJson();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await promptNode.update({ title, description, prompt, inputVariables, localVariables });
|
||||||
|
ctx.body = await promptNode.toJson();
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'delete')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const { id, title } = ctx.query;
|
||||||
|
const promptNode = await PromptNeo.first('id', id);
|
||||||
|
if (!promptNode) {
|
||||||
|
ctx.body = 'prompt not found';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await promptNode.delete();
|
||||||
|
ctx.body = 'delete success';
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'deleteAll')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const prompts = await PromptNeo.all();
|
||||||
|
for (const prompt of prompts) {
|
||||||
|
await prompt.delete();
|
||||||
|
}
|
||||||
|
ctx.body = 'delete all success';
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'createDemo')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const promptData = {
|
||||||
|
id: v4(),
|
||||||
|
title: 'test-' + v4(),
|
||||||
|
description: '这是测试保存prompt的数据',
|
||||||
|
prompt: '这是测试保存prompt的数据',
|
||||||
|
inputVariables: JSON.stringify([{ key: 'test', value: 'test' }]),
|
||||||
|
localVariables: JSON.stringify([{ key: 'test', value: 'test' }]),
|
||||||
|
};
|
||||||
|
const f = await PromptNeo.first('id', 'f5288cdb-bfca-4a65-b629-cae590ede719');
|
||||||
|
if (!f) {
|
||||||
|
ctx.body = 'not found f';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const prompt = await PromptNeo.create({ ...promptData });
|
||||||
|
// await prompt.relateTo(f, 'RELATED_TO', { createdAt: new Date().toISOString() });
|
||||||
|
// f.relateTo(prompt, 'RELATED_TO', { createdAt: new Date().toISOString() });
|
||||||
|
// await createRelationship(f, prompt);
|
||||||
|
const fj = await f.toJson() as any;
|
||||||
|
const pj = await prompt.toJson() as any;
|
||||||
|
|
||||||
|
await createRelationship2(fj.id, pj.id);
|
||||||
|
ctx.body = await prompt.toJson();
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route('prompt-graph', 'getD3')
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const value = await fetchData();
|
||||||
|
ctx.body = value;
|
||||||
|
})
|
||||||
|
.addTo(app);
|
@ -1,76 +1,63 @@
|
|||||||
import { PromptNeo } from '@/models/prompt.ts';
|
import { Prompt } from '@/models/prompt.ts';
|
||||||
|
|
||||||
import { app } from '@/app.ts';
|
import { app } from '@/app.ts';
|
||||||
import { v4 } from 'uuid';
|
import { CustomError } from '@abearxiong/router';
|
||||||
|
|
||||||
app
|
app
|
||||||
.route('prompt', 'list')
|
.route('prompt', 'list')
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const prompts = await PromptNeo.all();
|
const prompts = await Prompt.findAll({
|
||||||
const json = await prompts.toJson();
|
order: [['updatedAt', 'DESC']],
|
||||||
console.log('json', json);
|
});
|
||||||
ctx.body = json;
|
ctx.body = prompts;
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|
||||||
app
|
app
|
||||||
.route('prompt', 'update')
|
.route('prompt', 'update')
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { id, title, description, prompt, inputVariables, localVariables } = ctx.query;
|
const { id, title, description, presetData, key } = ctx.query.data || {};
|
||||||
const promptNode = await PromptNeo.first('id', id);
|
if (!key) {
|
||||||
|
throw new CustomError('Prompt key is required');
|
||||||
if (!promptNode) {
|
}
|
||||||
const promptData = {
|
const isEdit = !!id;
|
||||||
id: v4(),
|
const promptKey = await Prompt.findOne({ where: { key } });
|
||||||
|
if (promptKey && promptKey.id !== id) {
|
||||||
|
throw new CustomError(`Prompt key is already exist, use by ${promptKey.id}`);
|
||||||
|
}
|
||||||
|
if (!isEdit) {
|
||||||
|
const prompt = new Prompt({
|
||||||
title,
|
title,
|
||||||
|
key,
|
||||||
description,
|
description,
|
||||||
prompt,
|
presetData,
|
||||||
inputVariables: JSON.stringify(inputVariables),
|
});
|
||||||
localVariables: JSON.stringify(localVariables),
|
await prompt.save();
|
||||||
};
|
ctx.body = prompt;
|
||||||
const _prompt = await PromptNeo.create(promptData);
|
|
||||||
ctx.body = await _prompt.toJson();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await promptNode.update({ title, description, prompt, inputVariables, localVariables });
|
const prompt = await Prompt.findByPk(id);
|
||||||
ctx.body = await promptNode.toJson();
|
if (!prompt) {
|
||||||
|
throw new CustomError('Prompt not found');
|
||||||
|
}
|
||||||
|
await prompt.update({ title, description, presetData, key });
|
||||||
|
ctx.body = prompt;
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|
||||||
app
|
app
|
||||||
.route('prompt', 'delete')
|
.route('prompt', 'delete')
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { id, title } = ctx.query;
|
const { id } = ctx.query || {};
|
||||||
const promptNode = await PromptNeo.first('id', id);
|
if (!id) {
|
||||||
if (!promptNode) {
|
throw new CustomError('Prompt id is required');
|
||||||
ctx.body = 'prompt not found';
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
await promptNode.delete();
|
const prompt = await Prompt.findByPk(id);
|
||||||
|
if (!prompt) {
|
||||||
|
throw new CustomError('Prompt not found');
|
||||||
|
}
|
||||||
|
await prompt.destroy();
|
||||||
ctx.body = 'delete success';
|
ctx.body = 'delete success';
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
app
|
|
||||||
.route('prompt', 'deleteAll')
|
|
||||||
.define(async (ctx) => {
|
|
||||||
const prompts = await PromptNeo.all();
|
|
||||||
for (const prompt of prompts) {
|
|
||||||
await prompt.delete();
|
|
||||||
}
|
|
||||||
ctx.body = 'delete all success';
|
|
||||||
})
|
|
||||||
.addTo(app);
|
|
||||||
app
|
|
||||||
.route('prompt', 'createDemo')
|
|
||||||
.define(async (ctx) => {
|
|
||||||
const promptData = {
|
|
||||||
id: v4(),
|
|
||||||
title: 'test',
|
|
||||||
description: '这是测试保存prompt的数据',
|
|
||||||
prompt: '这是测试保存prompt的数据',
|
|
||||||
inputVariables: JSON.stringify([{ key: 'test', value: 'test' }]),
|
|
||||||
localVariables: JSON.stringify([{ key: 'test', value: 'test' }]),
|
|
||||||
};
|
|
||||||
const prompt = await PromptNeo.create(promptData);
|
|
||||||
ctx.body = await prompt.toJson();
|
|
||||||
})
|
|
||||||
.addTo(app);
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user