school-perplexity
v1.0.2
Published
教育信息查询系统 - 基于Open AI的多语言教育机构信息查询工具
Maintainers
Readme
教育信息查询系统(school_perplexity)
一个基于 Perplexity/OpenRouter 的高校教育信息查询与落库系统。系统通过大模型(perplexity/sonar 等)检索院校的院系、学位项目与课程信息,以 JSON Schema 规范结构化输出,并支持多种存储方式(飞书多维表格、Excel文件)。
功能特性
- 多语言支持:中英文输入/输出,自动简繁统一
- 结构化输出:严格的 JSON Schema 约束 AI 输出,稳健解析
- 多存储支持:支持飞书多维表格和Excel文件两种存储方式
- 存储抽象层:可配置的存储策略,易于扩展新的存储方式
- 飞书集成:自动复制模板、缓存表 ID、批量写入、失败重试
- Excel导出:支持实时写入、定时写入、手动写入三种模式
- Excel级联读取:支持从Excel文件读取学校→院系→专业→课程的完整层级数据
- 数据清洗:自动转换中文名称为简体中文,统一数据格式
- 来源字段修复:自动修复数据中的索引引用问题(如[10]),确保级联依赖关系正确
- 稳健性:OpenRouter 请求带随机延迟重试;写入存储也带重试
- 去重清洗:院系/学位名称/课程按名称或编号基础去重
- 日志观测:默认
xxd-log;developmentLog模式启用 winston 详细日志
目录结构
school_perplexity/
├─ src/
│ ├─ index.ts # 主流程(学校→院系→学位名称→学位详情→课程)
│ ├─ clients/
│ │ └─ openAiClient.ts # OpenRouter/OpenAI 调用与通用重试、去重
│ ├─ config/
│ │ ├─ openAiConfig.ts # 模型/客户端常量、默认重试配置
│ │ ├─ schoolData.ts # 学校数据清单(示例数据)
│ │ ├─ schoolQueryPrompts.ts # 查询 Prompt 生成
│ │ └─ storageConfig.ts # 存储配置管理
│ ├─ prompt/
│ │ └─ schoolQueryPrompts.ts # 查询 Prompt 生成
│ ├─ storage/
│ │ ├─ excel/
│ │ │ └─ excelStorage.ts # Excel存储实现
│ │ └─ lark/
│ │ ├─ larkBitTableOperate.ts # 飞书多维表格操作(已适配存储接口)
│ │ ├─ larkDataConvert.ts # 落库字段映射与格式化
│ │ └─ larkUtil.ts # URL 字段辅助
│ ├─ types/
│ │ ├─ education.ts # 类型与 JSON Schema 定义
│ │ └─ storage.ts # 存储层抽象接口和工厂
│ ├─ utils/
│ │ ├─ dateFormatter.ts # 日期格式化工具
│ │ ├─ deduplicate.ts # 数据去重工具
│ │ ├─ envLoader.ts # 环境变量加载工具
│ │ ├─ jsonParse.ts # 响应清洗与 JSON 安全解析
│ │ ├─ larkUtil.ts # 飞书相关工具函数
│ │ ├─ logger.ts # 日志封装(xxd-log / winston)
│ │ ├─ textUtils.ts # 文本处理工具(简繁转换等)
│ │ ├─ urlFormatter.ts # URL格式化工具
│ │ └─ winstonConfig.ts # winston 配置
│ └─ scripts/
│ ├─ readSchoolCascadeExcel.ts # Excel级联数据读取脚本(新增)
│ ├─ readSchoolCascadeLark.ts # 飞书级联数据读取脚本
│ ├─ testExcelCascadeReader.ts # Excel级联读取测试脚本(新增)
│ ├─ testExcelStorage.ts # Excel存储功能测试脚本
│ ├─ getOpenRouterKeyLimitInfo.ts # OpenRouter额度查询
│ ├─ getOpenRouterModules.ts # OpenRouter模型查询
│ └─ testPrompt.ts # Prompt测试脚本
├─ test/ # 单元测试(Jest)
├─ docs/
│ ├─ requerment.md # 需求说明
│ ├─ optimizations.md # 优化建议
│ ├─ concurrent-testing.md # 并发测试说明
│ └─ storage-usage.md # 存储使用说明
├─ school_info_output/ # Excel输出目录(新增)
├─ output/ # 旧版Excel输出目录
├─ test_output/ # 测试输出目录
├─ README.md
├─ package.json
└─ tsconfig.json快速开始
环境要求
- Node.js ≥ 18
- 已开通 OpenRouter/Perplexity API
- 选择存储方式:飞书开放平台应用 或 本地文件系统
安装依赖
npm install环境变量
在项目根目录创建 .env,填写以下变量:
# 存储类型选择
STORAGE_TYPE=lark|excel
# OpenRouter / OpenAI
OPENAI_ROUTER_API_KEY=your_openrouter_api_key
OPENAI_ROUTER_BASE_URL=https://openrouter.ai/api/v1
REQUEST_TIMEOUT=600000
API_MAX_RETRIES=3
API_RETRY_MIN_DELAY=30000
API_RETRY_MAX_DELAY=60000
# Lark 飞书存储配置(STORAGE_TYPE=lark时必需)
LARK_APPID=your_lark_app_id
LARK_APP_SECRET=your_lark_app_secret
LARK_TABLE_SPACE_ID=your_space_id
LARK_TABLE_TEMPLATE_NODE_TOKEN=your_template_node_token
LARK_TABLE_TARGET_PARENT_TOKEN=your_target_parent_token
LARK_API_MAX_RETRIES=3
LARK_API_RETRY_MIN_DELAY=3000
LARK_API_RETRY_MAX_DELAY=10000
# Excel存储配置(STORAGE_TYPE=excel时必需)
EXCEL_OUTPUT_PATH=./school_info_output
EXCEL_TEMPLATE_PATH=./template.xlsx # 可选
EXCEL_FLUSH_MODE=manual|immediate|interval # 可选,默认manual
EXCEL_FLUSH_INTERVAL_MS=60000 # interval模式下的间隔,可选存储方式说明
1. 飞书存储(默认)
- 需要提前准备飞书多维表格模板页面
- 系统自动复制模板为
AI提取院校数据-{学校中文名}格式 - 支持批量写入、失败重试、表ID缓存
2. Excel存储(新增)
- 支持三种写入模式:
manual: 仅在程序结束时写入(默认)immediate: 每次写入后立即落盘interval: 定时写入(可配置间隔)
- 每个学校生成独立的Excel文件
- 包含学校、院系、专业、课程四个工作表
运行
# 开发模式(编译 + 运行脚本)
npm run dev
# 构建
npm run build
# 生产启动
node dist/index.js
# 测试Excel存储功能
npm run test:excel
# 清洗并修复Excel数据
npm run clean:excel
# 运行Excel级联数据读取脚本
npm run dev:readExcel
# 运行飞书级联数据读取脚本
npm run dev:readLark
# 查询OpenRouter额度信息
npm run key:limits
# 查询OpenRouter可用模型
npm run dev:modules
# 测试Prompt
npm run devPrompt默认会从 src/config/schoolData.ts 的 schoolDataTest 列表读取学校,仅包含示例数据,可根据需要拓展。
关键运行指引(必读)
- 准备:配置
.env(选择存储类型并填写对应配置),飞书存储需确保模板节点存在 - 运行:
- 安装依赖:
npm i - 开发:
npm run dev - 或执行测试:
npm test
- 安装依赖:
- 产出:
- 飞书存储:自动复制模板并写入"学校/院系/专业/课程"表
- Excel存储:在配置目录生成学校数据文件
- 常见失败点:环境变量缺失、存储配置错误、飞书权限/模板token错、OpenRouter额度/限流
数据流程
- 生成 Prompt:学校→院系→学位名称→学位详情→课程
- OpenRouter 以 JSON Schema 结构化输出
- 解析清洗(移除引用/think 标签)并类型校验
- 去重清洗(院系/学位名称/课程编号)
- 写入存储(飞书:自动复制模板、缓存表ID、批量分片、重试;Excel:按配置模式写入)
- 速率控制:查询内置随机延迟重试;流程内 1s/2s 间隔
新增功能
Excel级联数据读取(v1.1.0)
核心功能
- 支持从Excel文件读取完整的学校层级数据
- 自动构建学校→院系→专业→课程的层级关系
- 支持数据清洗和格式标准化
技术特性
- 全量读取策略:一次性读取所有数据到内存,构建Map对象进行高效查找
- 智能数据清洗:自动转换中文名称为简体中文,统一数据格式
- 层级关系构建:通过专业名称映射自动关联课程与专业
- 结构化输出:生成清晰的层级数据结构,便于后续处理
使用方法
# 运行Excel级联读取测试
npx tsx src/scripts/testExcelCascadeReader.ts
# 直接使用Excel级联读取器
npx tsx src/scripts/readSchoolCascadeExcel.ts支持的数据格式
Excel文件应包含以下工作表:
学校信息表:学校基本信息院系信息表:院系信息专业信息表:专业/学位信息课程信息表:课程详细信息
输出示例
🏫 芝加哥大学
📝 University of Chicago
📊 院系数量: 4
🏢 院系1: 本科生院
📝 The College
📚 专业数量: 22
🎓 专业1: 文学士
📖 Bachelor of Arts (BA)
📋 课程数量: 5
📝 课程1: BA Core Curriculum
📝 课程2: Major Courses
...最近更新
Excel级联数据读取功能(v1.1.0)
重大功能新增
- 新增Excel级联数据读取脚本,支持从Excel文件读取完整的学校层级数据
- 实现全量读取策略,大幅提升数据读取性能
- 自动数据清洗和格式标准化
- 智能构建专业与课程的映射关系
技术架构优化
- 重构数据读取逻辑,采用Map对象进行高效查找
- 优化内存使用,支持大规模数据处理
- 增强错误处理和日志记录
- 代码清理,删除冗余代码,提升可维护性
性能提升
- 数据读取性能从O(N³)提升到O(N)
- 支持处理包含数千门课程的大型数据集
- 内存使用更加高效
存储层重构(v1.0.10)
重大架构升级
- 新增存储抽象层,支持多种存储方式
- 新增Excel存储实现,支持三种写入模式
- 重构主程序,移除硬编码存储依赖
- 支持运行时配置存储策略
Excel存储特性
- 完全实现存储接口,与飞书存储功能一致
- 支持模板文件初始化
- 实时数据写入,支持多种落盘策略
- 每个学校独立工作簿,包含四个工作表
向后兼容性
- 保持原有飞书功能不变
- 自动适配存储接口
- 配置驱动,易于切换存储方式
飞书API过滤问题修复
修复了飞书API过滤功能中的一个问题:
- 问题:飞书API返回错误
maxLen/minLen only support string or list type - 原因:过滤条件中的值类型不正确
- 解决方案:采用全量扫描本地过滤方式,提高系统稳定性
学校级联数据读取脚本增强
- 添加了进度打印功能,实时显示数据读取进度
- 使用项目统一的日志工具,保持日志格式一致性
- 更好的用户体验,可以实时了解数据读取进度
日志
- 默认使用
xxd-log - 设置
NODE_ENV=developmentLog启用 winston,输出到控制台与logs/目录
测试与质量
# 运行测试
npm test
# 测试Excel存储
npm run test:excel
# 测试Excel级联读取
npx tsx src/scripts/testExcelCascadeReader.ts
# Lint
npm run lint
# 格式化
npm run format常见问题
- 环境变量缺失:请检查
.env是否完整,尤其是存储相关配置 - 存储配置错误:确保
STORAGE_TYPE设置正确,并填写对应的配置项 - 模板字段不匹配:飞书存储依赖既有模板定义字段,请确保模板字段名称与转换器一致
- OpenRouter 限流/额度:适当调小重试次数/延迟,或减少并发
- Excel写入失败:检查输出目录权限,确保有写入权限
- Excel读取失败:确保Excel文件格式正确,包含必要的工作表和字段
进一步优化
详见文档:
docs/optimizations.md- 优化建议docs/concurrent-testing.md- 并发测试说明docs/storage-usage.md- 存储使用说明
技术架构
存储层设计
- 接口隔离原则:通过
IDataStorage接口抽象存储实现 - 工厂模式:统一创建存储实例
- 策略模式:运行时选择存储策略
数据读取架构
- 全量读取策略:一次性读取所有数据,构建高效查找结构
- Map对象优化:使用Map进行O(1)时间复杂度的数据查找
- 数据清洗管道:自动标准化数据格式,提升数据质量
代码质量
- 遵循单一职责原则
- 完整的错误处理
- 详细的日志记录
- 类型安全的TypeScript实现
- 代码清理和重构,提升可维护性
可扩展性
- 易于添加新的存储方式
- 易于扩展新的数据读取方式
- 配置驱动的架构
- 模块化的设计
