ollflow
v0.0.6
Published
```javascript const { WorkflowEngine, ollama,tools, toolImplementations } = require('ollflow');
Downloads
277
Readme
使用示例
const { WorkflowEngine, ollama,tools, toolImplementations } = require('ollflow');
const engine = new WorkflowEngine({
"name": "模拟法庭开庭工作流",
"steps": [
{
"id": "step1",
"action": "useTools",
"params": {
"prompt": "创建一个案件文件,描述一个简单的民事纠纷案件。包括案件编号、原告、被告、案件简述。",
"tools": tools
},
"next": "step2"
},
{
"id": "step2",
"action": "useTools",
"params": {
"prompt": "阅读案件文件,并创建一个开庭通知,包括开庭时间、地点、参与人员等信息。",
"tools": tools
},
"next": "step3"
},
{
"id": "step3",
"action": "useTools",
"params": {
"prompt": "模拟开庭过程,创建一个庭审记录文件,记录法官、原告、被告的陈述。",
"tools": tools
},
"next": "step4"
},
{
"id": "step4",
"action": "useTools",
"params": {
"prompt": "模拟证据展示环节,在庭审记录中添加双方提交的证据信息。",
"tools": tools
},
"next": "step5"
},
{
"id": "step5",
"action": "useTools",
"params": {
"prompt": "模拟辩论环节,在庭审记录中添加双方律师的辩论内容。",
"tools": tools
},
"next": "step6"
},
{
"id": "step6",
"action": "useTools",
"params": {
"prompt": "法官总结案情,并在一个新的判决书文件中写出判决结果和理由。",
"tools": tools
},
"next": "step7"
},
{
"id": "step7",
"action": "useTools",
"params": {
"prompt": "创建一个案件归档文件,总结整个案件的处理过程和结果。",
"tools": tools
},
"next": "step8"
},
{
"id": "step8",
"action": "useTools",
"params": {
"prompt": "列出所有创建的文件,并提供一个简短的案件处理总结。",
"tools": tools
},
"next": null
}
]
});
// 注册工具实现
Object.keys(toolImplementations).forEach(toolName => {
engine.registerAction(toolName, async (params) => {
const result = await toolImplementations[toolName](params);
console.log(`Tool ${toolName} result:`, result);
return result;
});
});
// 注册 useTools 动作
engine.registerAction("useTools", async (step, context) => {
const result = await ollama.useTools(step, JSON.stringify(context));
console.log("useTools result:", result);
return result;
});
// 运行工作流
engine.run().then(() => {
console.log("模拟法庭开庭工作流完成");
}).catch(error => {
console.error("工作流执行出错:", error);
});
agent 使用示例
ollama的工具方法并不好用,还是使用 json 示例输出有效果。
import { promises as fs } from 'fs';
import path from 'path';
import { Agent } from 'ollflows';
// 创建编程 Agent 实例
const agentOptions = {
name: 'programmingAgent',
};
const agent = new Agent(agentOptions);
function processResponse(responseText) {
// 首先尝试直接解析 JSON
try {
return JSON.parse(responseText);
} catch (error) {
// JSON 解析失败,继续后续处理
}
// 尝试匹配 markdown 代码块
const codeBlockPattern = /```(?:\w*)\n([\s\S]*?)\n```/;
const match = responseText.match(codeBlockPattern);
if (match) {
// 提取代码块内容并处理
const codeContent = match[1]
.split('\n')
.map(line => line.trim()) // 去除每行的首尾空格
.join('') // 合并所有行
.replace(/\s/g, ''); // 去除所有空白字符
// 尝试将处理后的内容解析为 JSON
try {
return JSON.parse(codeContent);
} catch (error) {
// JSON 解析失败,继续后续处理
}
}
// 如果所有尝试都失败,返回原始数据
return responseText;
}
function extractFirstCodeBlock(markdownText) {
// 匹配代码块的正则表达式,支持可选的语言标识
const codeBlockPattern = /```(?:\w*)\n([\s\S]*?)\n```/;
const match = markdownText.match(codeBlockPattern);
// 如果找到代码块,返回其内容;否则返回空字符串
return match ? match[1] : '';
}
async function readFileContent(filePath) {
try {
// 获取当前工作目录
const currentDir = process.cwd();
const fullPath = path.join(currentDir, filePath);
// 检查文件是否存在
try {
await fs.access(fullPath);
} catch (error) {
console.error(`File '${filePath}' not found in ${currentDir}`, error);
return null;
}
// 读取文件内容
const content = await fs.readFile(fullPath, 'utf-8');
return content;
} catch (error) {
console.error('Error reading file:', error);
return null;
}
}
async function findFilesInDirectory(directoryName) {
try {
// 获取当前工作目录
const currentDir = process.cwd();
console.log("当前运行目录", currentDir)
const targetDir = path.join(currentDir, directoryName);
const results = [];
// 检查目录是否存在
try {
await fs.access(targetDir);
} catch (error) {
console.error(`Directory '${directoryName}' not found in ${currentDir}`,error);
return results;
}
// 递归遍历目录的辅助函数
async function traverseDirectory(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// 如果是目录,递归遍历
await traverseDirectory(fullPath);
} else {
// 如果是文件,添加到结果数组
const relativePath = path.relative(targetDir, fullPath);
results.push({
file: relativePath
});
}
}
}
// 开始遍历
await traverseDirectory(targetDir);
return results;
} catch (error) {
console.error('Error while finding files:', error);
return [];
}
}
const fileslist = await findFilesInDirectory('temp');
console.log(fileslist);
async function main(fileslist) {
// 循环遍历文件列表读取内容
for (const file of fileslist) {
try {
// 构建完整的文件路径
const filePath = path.join('temp', file.file);
// 读取文件内容
const content = await fs.readFile(filePath, 'utf8');
console.log(`添加向量数据库文件 ${file.file}`);
await agent.addToMemory(content);
console.log('-------------------');
} catch (error) {
console.error(`读取文件 ${file.file} 时出错:`, error);
}
}
await agent.addToMemory('next.js最新版本是v15');
await agent.addToMemory('next.js最新版本是v15');
const response = await agent.action({
type: 'text',
task: "生成一个 Next.js 14 使用app router,使用 sqlite 数据库,支持注册登录发布博客文章并管理的项目的文件结构。",
prompt: `补充完善 Next.js 项目中页面和路由文件结构。输出格式为 JSON 数组,每个对象包含 file 和 description 两个字段,分别表示文件的绝对路径和文件的功能和作用,项目使用Tailwindcss和shadcn。以下为已经存在的文件${JSON.stringify(fileslist)},已经存在的文件除非需要修改负责不需要重新列出;
示例输出:
[
{ "file": "/app/page.tsx", "description": "网站首页文件" },
{ "file": "/app/api/login/route.ts", "description": "关于登录有关的API接口" },
{ "file": "/components/Header.tsx", "description": "头部组件文件" }
]
`
});
async function code(item) {
return agent.action({
type: 'text',
task: `开发以下文件的代码:${item.file},功能说明${item.description}`,
prompt: `你是一个专业的Next.js开发工程师,专注于根据用户的具体要求生成特定文件的代码。你的任务是提供精确、高质量且符合最佳实践的Next.js代码,仅针对指定的文件进行编写。确保代码专注于用户请求的文件,不包含任何额外内容。考虑代码的性能、可维护性以及与项目其他部分的交互。输出应仅包含代码并添加中文注释,确保代码可以直接集成到项目中使用。项目中使用Tailwindcss和shadcn。`,
input:`${item.description}`
})
}
const list = processResponse(response);
//开始循环
// 确保 list 是数组
if (Array.isArray(list)) {
// 遍历文件列表
for (const item of list) {
try {
const res = await code(item);
//
// 使用 fs.promises 的方法
await fs.mkdir('temp', { recursive: true });
// 构建完整的文件路径
const filePath = path.join('temp', item.file);
// 使用 fs.promises 创建目录
await fs.mkdir(path.dirname(filePath), { recursive: true });
// 使用 fs.promises 写入文件
await fs.writeFile(filePath, extractFirstCodeBlock(res), 'utf8');
console.log(`文件 ${item.file} 处理完成`);
} catch (error) {
console.error(`处理文件 ${item.file} 时出错:`, error);
}
}
//
} else {
console.error('响应格式错误: 预期是数组但收到', typeof list);
}
}
main(fileslist)