0.0.6 • Published 7 months ago

ollflow v0.0.6

Weekly downloads
-
License
ISC
Repository
-
Last release
7 months ago

使用示例

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)
0.0.6

7 months ago

0.0.5

7 months ago

0.0.4

7 months ago

0.0.3

7 months ago

0.0.2

7 months ago

0.0.1

7 months ago