feat: add neo4j and prompt and prompt-graph
This commit is contained in:
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 { v4 } from 'uuid';
|
||||
import { CustomError } from '@abearxiong/router';
|
||||
|
||||
app
|
||||
.route('prompt', 'list')
|
||||
.define(async (ctx) => {
|
||||
const prompts = await PromptNeo.all();
|
||||
const json = await prompts.toJson();
|
||||
console.log('json', json);
|
||||
ctx.body = json;
|
||||
const prompts = await Prompt.findAll({
|
||||
order: [['updatedAt', 'DESC']],
|
||||
});
|
||||
ctx.body = prompts;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route('prompt', '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(),
|
||||
const { id, title, description, presetData, key } = ctx.query.data || {};
|
||||
if (!key) {
|
||||
throw new CustomError('Prompt key is required');
|
||||
}
|
||||
const isEdit = !!id;
|
||||
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,
|
||||
key,
|
||||
description,
|
||||
prompt,
|
||||
inputVariables: JSON.stringify(inputVariables),
|
||||
localVariables: JSON.stringify(localVariables),
|
||||
};
|
||||
const _prompt = await PromptNeo.create(promptData);
|
||||
ctx.body = await _prompt.toJson();
|
||||
presetData,
|
||||
});
|
||||
await prompt.save();
|
||||
ctx.body = prompt;
|
||||
return;
|
||||
}
|
||||
|
||||
await promptNode.update({ title, description, prompt, inputVariables, localVariables });
|
||||
ctx.body = await promptNode.toJson();
|
||||
const prompt = await Prompt.findByPk(id);
|
||||
if (!prompt) {
|
||||
throw new CustomError('Prompt not found');
|
||||
}
|
||||
await prompt.update({ title, description, presetData, key });
|
||||
ctx.body = prompt;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route('prompt', 'delete')
|
||||
.define(async (ctx) => {
|
||||
const { id, title } = ctx.query;
|
||||
const promptNode = await PromptNeo.first('id', id);
|
||||
if (!promptNode) {
|
||||
ctx.body = 'prompt not found';
|
||||
return;
|
||||
const { id } = ctx.query || {};
|
||||
if (!id) {
|
||||
throw new CustomError('Prompt id is required');
|
||||
}
|
||||
await promptNode.delete();
|
||||
const prompt = await Prompt.findByPk(id);
|
||||
if (!prompt) {
|
||||
throw new CustomError('Prompt not found');
|
||||
}
|
||||
await prompt.destroy();
|
||||
ctx.body = 'delete success';
|
||||
})
|
||||
.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);
|
||||
|
||||
Reference in New Issue
Block a user