2024 注意:即使之前能正常工作,现在日志记录器的绑定不再有效 - 我们还不太清楚原因
一个用于提示/LLM应用工程的最小可行日志记录器。
使用你的IDE作为日志UI - 一个快速、简单、可扩展、零依赖的Node.js日志工具。
.tsv
文件以导入电子表格。电子表格就是你进行提示工程所需的全部工具!简短视频演示:https://www.loom.com/share/ae818b7d058343c1ad6caf8deee2e430
.logs
文件夹清除日志(可自定义).tsv
文件以导入电子表格(如Google Sheets、Excel、Quadratic)非目标:
安装:
npm install @smol-ai/logger
使用:
import { SmolLogger } from '@smol-ai/logger'; const logger = new SmolLogger({ logToConsole: true, logToStore: true }) // 易于关闭 const log = logger.log // 可选的便捷别名,减少冗长 log('日志名称(必填)', payload) // 基本用法
默认情况下,所有日志都会发送到控制台和文件系统,因此你可以在IDE中轻松导航:
<img width="1462" alt="图片" src="https://github.com/smol-ai/logger/assets/6764957/348a3f49-1022-4763-9b63-cf0e3080b85a">日志看起来是这样的!
<img width="1470" alt="图片" src="https://github.com/smol-ai/logger/assets/6764957/a862f61d-9459-42d2-bab7-572231c5c8e8">log
函数是一个单一参数的"恒等函数" - 返回payload,因此你可以就地修改。
mySingleArityFunction({foo, bar, baz}) // 哦不,我需要记录bar和baz mySingleArityFunction({foo, ...log({bar, baz})) // 搞定! mySingleArityFunction(log({foo, bar, baz})) // 为什么不全部记录呢 myBadMultiArityFunction(foo, bar, baz) // 哦不,我需要记录bar myBadMultiArityFunction(foo, log(bar), baz) // 搞定! myBadMultiArityFunction(...log({foo, bar, baz}).values()) // 为什么不全部记录呢
我们默认使用单一参数以鼓励JS生态系统中的这种做法。
要清 除你的日志 - 删除.logs
文件夹!就这么简单!下次运行日志时它会重新生成。
对于生产环境的日志记录,可以覆盖Smol Logger的存储目标。我们喜欢Logflare!
<img height="300" alt="图片" src="https://github.com/smol-ai/logger/assets/6764957/69b546ec-23d7-4099-9432-5fd37ca1436e">// 可选:保留默认的本地文件存储以便重用 const localStore = logger.store // 用你自己的远程文件存储覆盖默认的本地文件存储 // { logName: string, loggedLine: string | null, payload: any, secondsSinceStart: number, secondsSinceLastLog: number } logger.store = ({ logName, loggedLine, payload, secondsSinceStart, secondsSinceLastLog }) => { fetch("https://api.logflare.app/logs/json?source=YOUR_SOURCE_ID", { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", "X-API-KEY": "YOUR_API_KEY_HERE" }, body: JSON.stringify({ message: logName, metadata: {loggedLine, payload, secondsSinceStart, secondsSinceLastLog }}) }) // 可选:同时记录到本地文件存储 localStore({ logName, loggedLine, payload, secondsSinceStart, secondsSinceLastLog }) }
如果你预期会有大量日志,应该对它们进行批处理:
// 这是目前未经测试的示例代码,如果你运行并尝试过,请发送PR const logMessages = [] function throttle(func, delay = 1000) { let timeout = null; return function(...args) { const { logName, loggedLine, payload, secondsSinceStart, secondsSinceLastLog } = args; logMessages.push(({ message: logName, metadata: {loggedLine, payload, secondsSinceStart, secondsSinceLastLog }})); if (!timeout) { timeout = setTimeout(() => { func.call(this, ...args); timeout = null; }, delay); } }; }
const sendToLogFlare = ({ logName, loggedLine, payload, secondsSinceStart, secondsSinceLastLog }) => { fetch("https://api.logflare.app/logs/json?source=YOUR_SOURCE_ID", { method: "POST", headers: { "Content-Type": "application/json; charset=utf-8", "X-API-KEY": "YOUR_API_KEY" }, body: JSON.stringify({"batch": logMessages}) }) .then(() => logMessages = []) }
log.store = throttle(sendToLogFlare, 1000)
<details>
<summary>
<strong>异步/阻塞日志记录</strong>
</summary>
在 smol logger 中,日志记录默认是同步的。
请注意,在上面的例子中,我们在同步调用内部触发了一个异步fetch。如果你的应用程序崩溃,由于它是异步运行的,有一个很小的可能性日志可能无法完成发送。如果你需要为异步调用进行阻塞,你可以使用 `asyncLog` 方法和一个异步存储:
```js
// 可选:存储本地文件存储以便重用
const oldStore = logger.store
// 用你自己的远程文件存储覆盖默认的本地文件存储
// { logName: string, loggedLine: string | null, payload: any, secondsSinceStart: number, secondsSinceLastLog: number }
logger.store = async ({ logName, loggedLine, payload, secondsSinceStart, secondsSinceLastLog }) => {
const res = await fetch("https://api.logflare.app/logs/json?source=YOUR_SOURCE_ID", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8",
"X-API-KEY": "YOUR_API_KEY_HERE"
},
body: JSON.stringify({ message: logName, metadata: {loggedLine, payload, secondsSinceStart, secondsSinceLastLog }})
}).then(res => res.json())
// 只是演示你可以在这个存储中使用await
}
// 现在你可以在异步上下文中阻塞执行
await logger.asyncLog('我的消息在这里', { foo: 'bar' })
注意:这个功能是新的且未经测试,请尝试并提供修复/反馈
</details>这会同时记录你想要监控的异步函数的输入和输出。主要用于提示工程,在这种情况下你非常关心输入与输出对在同一日志文件中的可见性。
<details> <summary> Openai SDK V3说明 </summary>import OpenAI from 'openai'; // 这是用于openai v4包的!v3说明在下面 import {SmolLogger} from '@smol-ai/logger'; const openai = new OpenAI({ apiKey: 'my api key', // 默认为 process.env["OPENAI_API_KEY"] }); const logger = new SmolLogger({logToConsole: true, logToStore: true}); // 两个参数都是可选的,只是为你列出默认值以便轻松关闭 const wrapped = logger.wrap( openai.chat.completions.create.bind(openai) // 绑定很重要,因为OpenAI内部是如何检索其配置的 async function main() { const completion = await wrapped({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: "你是一个有帮助的助手", }, { role: "user", content: "选择一个著名的流行歌手,并给我他们的3首歌", }, ], }); console.log(completion.choices); } main();
很快就会过时,所以我们把它隐藏在这里
</details>import { Configuration, OpenAIApi } from 'openai'; const openai = new OpenAIApi(new Configuration({ apiKey: process.env.OPENAI_API_KEY })); const wrapped = logger.wrap(openai.createChatCompletion.bind(openai)) // 绑定很重要,因为OpenAI内部是如何检索其配置的 const response = await wrapped({ model: process.env.OPENAI_MODEL || 'gpt-3.5-turbo', messages: [/* 等等 */ ], });
有时输出可能非常冗长(就像OpenAI chatCompletion的情况)。所以我们还允许你暴露一个简单的"日志转换器",这是一个任意函数,可以将拦截的输出修改为你喜欢的格式:
<img height="400" alt="image" src="https://github.com/smol-ai/logger/assets/6764957/0b15a508-db3b-4a52-8a8f-a94a7e0282a6"> <img height="400" alt="image" src="https://github.com/smol-ai/logger/assets/6764957/75b68625-2516-492e-8642-be316d57d5f4">// 编辑上面的代码以添加logTransformer const wrapped = logger.wrap( openai.createChatCompletion.bind(openai), // 绑定很重要,因为OpenAI内部是如何检索其配置的 { wrapLogName: 'chatGPT APIcall', // 可选 - 自定义显示在日志上的名称。默认为 "wrap(fn.name)" logTransformer: (args, result) => ({ // 可以是异步的 // ...result, // 可选 - 如果你想要完整的原始结果本身 prompt: args[0].messages, response: result.choices[0].message, // 这是v4 api;v3是 result.data.choices[0].message }) } ) const response = await wrapped({ model: process.env.OPENAI_MODEL || 'gpt-3.5-turbo', messages: [/* 等等 */ ], }); // 现在记录的响应只包含我们感兴趣的特定字段,见下面的截图
log2tsv
CLI单个JSON日志文件对于调试单次运行很有用。这是smol-logger的良好默认设置。
对于提示工程,你还需要轻松比较不同运行之间的提示与输出,并对它们进行评分/编写评估。对于这一点,没有比电子表格更灵活或更强大的界面了。因此,我们帮助你将日志导出为电子表格。
你可以运行 log2tsv
CLI,它会在你的 ./logs
文件夹中输出一个 logs.tsv
文件(我们会接受PR来自定义这个)。你可以在Google Sheets/Excel/Quadratic等中导入这个 .tsv
文件,以进行进一步的提示工程。
./node_modules/.bin/log2tsv # 在安装了 @smol-ai/logger 的目录中
你也可以将其放入npm脚本中,它就会运行:
<img width="1451" alt="image" src="https://github.com/smol-ai/logger/assets/6764957/3f6500cd-9a42-43ec-8aba-c5930fb568a1">// package.json { "scripts": { "tsv": "log2tsv" // 然后运行 npm run tsv } }
请注意,标题是从第一条日志中提取的 - 很可能不会完全匹配所有日志的主体内容,特别是当你有不规则形状的日志时。我们相信你能够自行在电子表格中重新命名它们,如果它们足够重要的话。
如果你需要,我们会接受一个PR来使其可以通过编程方式运行(而不仅仅是CLI)。
自定义的一般规则是覆盖类中暴露的任何变量和方法:
logger.logDirectory = '.smol-logs' // 更改默认文件存储目录 logger.logToConsole = false // 关闭终端日志记录 logger.logToStore = false // 关闭存储日志记录 // 更多使用想法 logger.logToStore = Math.random() < 0.05 // 只记录5%的流量 logger.logToStore = user.isVIPCustomer() // 基于功能标志记录日志 logger.logName = (name: string) => `我的自定义日志名称:${name}` // 更改日志命名! logger.LOGCOLOR = (logName: string) => "\x1b[35m" + logName + "\x1b[0m"; // 将日志颜色设置为洋红色而不是黄色
其他可以尝试的日志颜色:
\x1b[31m: 红色
\x1b[32m: 绿色
\x1b[33m: 黄色
\x1b[34m: 蓝色
\x1b[35m: 洋红色
\x1b[36m: 青色
\x1b[37m: 白色
<details>
<summary>
发挥创意!例如,你可以在单个归约函数中堆叠logName函数...
</summary>
<img height="400" alt="image" src="https://github.com/smol-ai/logger/assets/6764957/2f15bf5a-a25b-4b69-b7e5-38524beeef70">// 对于高级应用,你可以在堆栈中添加日志名称 const logStack = [logger.logName] // 将原始logName函数存储在堆栈底部 logger.logName = (name) => logStack.reduce((prev, fn) => fn(prev), name) let temp = 0 do { logStack.unshift(name => ' ' + name) // 这里记录的所有内容都缩进一级 log('logname1 here ' + temp, temp) let temp2 = 0 do { logStack.unshift(name => ' ' + name) // 这里记录的所有内容都缩进两级 log('logname2 here ' + temp2, temp2) logStack.shift() } while (temp2++ < 5) logStack.shift() } while (temp++ < 5)
</details>将来我们可能会为嵌套日志记录提供更正式的API: (这在代码中但未经测试)
const sublog = logger.newSubLog('prefix') // Logger的新实例,带有缩进日志设置 let temp = 0 do { sublog('logname1 here ' + temp, temp) // 这里记录的所有内容都缩进一级 const sublog2 = sublog.sublog() let temp2 = 0 do { sublog2('logname2 here ' + temp2, temp2) // 这里记录的所有内容都缩进两级 } while (temp2++ < 5) } while (temp++ < 5)
如果感兴趣,请开启一个issue,这里有很多设计空间
我们并不是真的追求最高速度,因为我们更关心开发中的开发者体验,但请参见 /benchmark
:
$ cd benchmark && npm install $ node bench.js > bench.txt $ grep "^bench" bench.txt benchWinston*100000: 1.690s benchBunyan*100000: 1.820s benchPino*100000: 892.089ms benchSmol*100000: 1.290s benchWinston*100000: 1.620s benchBunyan*100000: 1.712s benchPino*100000: 911.538ms benchSmol*100000: 1.284s
这 希望能证明我们比Winston/Bunyan更快,并且与Pino相比具有竞争力,同时提供更好的功能集。
这个仓库是使用 https://github.com/alexjoverm/typescript-library-starter 初始化的(必须使用 https://github.com/alexjoverm/typescript-library-starter/issues/333 进行修改)
按照控制台说明安装semantic release并运行它(对"Do you want a .travis.yml
file with semantic-release setup?"问题回答NO)。
注意:确保你已经在package.json
文件中设置了repository.url
npm install -g semantic-release-cli semantic-release-cli setup # 重要!!对"Do you want a `.travis.yml` file with semantic-release setup?"问题回答NO。它已经为你准备好了 :P
从现在开始,你需要使用npm run commit
,这是创建常规提交的便捷方式。
自动发布得益于semantic release,它会自动在github和npm上发布你的代码,并自动生成更新日志。
swyx注 - 无法使发布工作正常,一直失败。
目前:
npm run build npm version patch npm publish --access=public
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松 管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需 求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能 ,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海 量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号