@mmteam/jsllm
v0.1.14
Published
MM Team LLM library (providers + chat/session runner)
Downloads
664
Readme
@mmteam/jsllm
独立的 LLM 能力库:封装多供应商差异(OpenAI 兼容、Gemini)与会话执行(含工具循环/落盘)。
发布形态:
- 单文件运行时代码:
dist/index.cjs(CommonJS,已 bundle 所有运行时依赖) - 单文件类型声明:
dist/types.d.ts - 发布包零 dependencies(下游安装后无需额外安装 OpenAI/Gemini SDK 等依赖)
功能概览
- 统一供应商:OpenAI 兼容 / Gemini
- 统一会话:会话目录管理、消息落盘、历史恢复、usage 累计
- 流式输出:stdout 输出回答;stderr 输出诊断与 think/reasoning(若模型提供)
- 工具循环:内置
shell工具(模型触发时在工作区执行命令,并回填输出)
安装
npm i @mmteam/jsllm环境要求
- Node.js >= 20
快速开始
CommonJS(推荐)
const path = require("node:path");
const { chatInSession } = require("@mmteam/jsllm");
async function main() {
await chatInSession({
init: {
providerName: "openai",
apiType: "openai",
apiKey: process.env.OPENAI_API_KEY,
model: "gpt-4o-mini",
temperature: 0.7,
},
workspaceRoot: process.cwd(),
sessionRootDir: path.join(process.cwd(), ".magicai/chat-sessions"),
messageArg: "hello",
});
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});输入规则:
- 若提供
messageArg,使用其作为用户输入 - 否则当 stdin 非 TTY 时读取 stdin;两者都没有则报错
ESM 项目中使用(可选)
本包对外导出为 CommonJS(require)。在纯 ESM 项目中可用 createRequire 引用:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const { chatDirectText } = require("@mmteam/jsllm");API
对外仅导出 2 个函数(以及必要类型):
详细参数、类型与中文说明:请参考 node_modules/@mmteam/jsllm/dist/types.d.ts(本仓库构建产物对应 projects/jsllm/codex-zf/dist/types.d.ts)。
如何选择?
| 能力 | chatDirectText | chatInSession |
|---|---|---|
| 目标 | 单轮生成(返回文本) | 会话引擎(落盘 + 工具循环 + 流式输出) |
| 输入 | 调用方提供 messages | messageArg 或 stdin;并自动加载会话历史 |
| 输出 | Promise<string> | stdout 流式输出;会话文件落盘;stderr 输出诊断/think |
| 工具 | 不启用、不执行 | 内置 shell(模型触发时执行并回填) |
| 适用场景 | 摘要/改写/分类等一次性生成;你自管存储 | CLI/交互式场景;需要可追溯、可续写会话 |
chatDirectText(init, messages): Promise<string>
- 用途:不落盘、不启用工具的“单轮文本生成”,返回最终聚合文本
- 示例:
const { chatDirectText } = require("@mmteam/jsllm");
const text = await chatDirectText(
{
providerName: "gemini",
apiType: "gemini",
apiKey: process.env.GEMINI_API_KEY,
model: "gemini-1.5-pro",
},
[
{ role: "user", content: "Summarize: ..." },
],
);
console.log(text);chatInSession(options): Promise<void>
- 用途:执行一次“CLI 式会话主循环”(会话落盘 + 流式输出 + 工具循环)
- 重要参数:
workspaceRoot:工作区根目录(用于解析public/agents,以及工具执行 cwd)sessionRootDir:会话根目录(会在其下创建会话目录与latest软链)systemPrompt:支持内联文本或@引用文件/agent 名称(见下方说明)consoleOutput:是否写入 stdout/stderr(默认true)onEvent:实时输出回调(区分正常回复 text 与 think,并携带与落盘一致的文件名/路径)
供应商与配置
OpenAI 兼容(apiType: "openai")
init: {
providerName: "openai", // 或 dashscope / 自建网关等;qwen* 见下
apiType: "openai",
apiKey: "...",
baseUrl: "https://your-gateway.example.com", // 可选
model: "gpt-4o-mini",
temperature: 0.7,
}Gemini(apiType: "gemini")
init: {
providerName: "gemini",
apiType: "gemini",
apiKey: "...",
baseUrl: "https://generativelanguage.googleapis.com", // 可选;仅代理/国内环境需要
apiVersion: "v1beta", // 建议显式配置;预览模型推荐 v1beta
model: "gemini-1.5-pro",
}baseUrl:非必须;未配置时使用 SDK 默认地址apiVersion:建议显式配置;预览模型常用v1beta
qwen*(OpenAI 兼容扩展)
判断规则:providerName 以 qwen 前缀(不区分大小写)即视为 qwen 模式(如 qwen1、qwen-local)。
thinking 参数:
- 公共字段:
thinking.enabled、thinking.budgetTokens - qwen 私有字段:
qwen.enable_thinking、qwen.thinking_budget(优先级高于公共字段)
示例:
init: {
providerName: "qwen-local",
apiType: "openai",
apiKey: "...",
baseUrl: "http://localhost:8000/v1",
model: "qwen2.5",
thinking: { enabled: true, budgetTokens: 2048 },
qwen: { enable_thinking: true, thinking_budget: 2048 },
}会话落盘说明(chatInSession)
- 会话根目录:由
sessionRootDir指定 - 会话目录:
YYYYMMDD_HHMMSS/ latest:会话根目录下的软链,指向最近一次有效会话目录usage.json:会话累计用量(当供应商返回 usage 时会自动累加)- 消息文件:按序号落盘,支持恢复历史继续会话
.think:当模型输出 reasoning/think 时,会额外落盘同名.think文件
实时回调(chatInSession.onEvent)
你可以通过 onEvent 在应用侧接收流式输出,并区分正常回复与 think(事件中携带与落盘一致的文件名):
await chatInSession({
/* ... */,
consoleOutput: false,
onEvent(e) {
if (e.type === "assistant_text") {
// e.textSoFar:当前轮累计的“正常回复”
}
if (e.type === "assistant_think") {
// e.thinkSoFar:当前轮累计的 think/reasoning
}
},
});多轮会话(chatInSession)
chatInSession 的多轮能力通过“会话目录落盘 + 下次加载历史”实现:每次调用会读取目标会话目录的历史消息并继续追加写入。
- 默认续写上一会话(推荐):多次调用时保持相同的
sessionRootDir,且不传sessionArg,库会自动复用latest指向的会话目录。 - 固定到指定会话:传入
sessionArg: "my-session"(相对sessionRootDir的相对子目录),每次调用都使用同一个值,即可稳定续写同一会话。 - systemPrompt 建议:同一会话通常只在“第一轮”设置
systemPrompt;后续轮次不再传(或改用sessionArg固定会话),避免触发创建新会话导致上下文断裂。
systemPrompt / globalAgent(chatInSession)
systemPrompt支持两种形式:- 内联文本:直接传字符串
- 引用文件/agent:以
@开头,例如@公共智能体或@./path/to/prompt.txt
- 当引用的是名称(非绝对路径且不以
./开头)时,会在${workspaceRoot}/public/agents/下查找,并允许省略.agent.md扩展名
环境变量
MCHAT_REQUEST_TIMEOUT_MS:OpenAI 兼容请求超时(毫秒)MCHAT_DEBUG:Gemini provider debug 输出(true/1开启)
安全说明(工具)
chatInSession 内置 shell 工具:当模型触发工具调用时,会在 workspaceRoot 下通过 bash -lc 执行命令并回填输出。请仅在可信环境中使用,并确保运行账号权限可控。
开发
下述为仓库开发者使用;下游项目不需要执行 build。
npm run build