Omi Crossref App:为 Omi 对话工具打造的无认证学术文献检索集成
2026/9/16 23:04:14 网站建设 项目流程

Omi Crossref App:为 Omi 对话工具打造的无认证学术文献检索集成

【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend

本篇技术指南围绕开源仓库GitHub_Trending/fr/Friend中 plugins/omi-crossref-app 插件展开,系统讲解如何基于公共 Crossref REST API 构建一套免认证(no-auth)的 Omi chat tools 集成服务。读完本文,你将掌握该插件的三个核心工具(文献搜索、DOI 详情查询、按作者检索)的接口契约、底层调用链与部署方式,并能直接本地运行或发布到 Railway/Heroku 类平台。

插件定位:无认证的学术元数据查询服务

omi-crossref-app是 Omi 插件体系中的独立子应用,其目标是在对话场景中为 AI 提供学术论文元数据检索能力。与仓库内其他需要 OAuth 或 API Key 的插件(如 plugins/omi-google-calendar-app、plugins/omi-dropbox-app)不同,它直接使用公共的 Crossref REST API(https://api.crossref.org),不依赖任何环境变量、OAuth 流程或密钥,天然适合作为轻量 chat tool 接入。

从 README 的定位描述"A no-auth Crossref integration app for Omi chat tools"与 main.py 中 FastAPI 应用的标题Crossref Omi Integration可以确认:该插件只承担"查询、清洗、返回文本结果"这一件事,不涉及数据库、鉴权与用户态存储。

三个核心工具及其请求契约

README 声明了三个工具,其参数契约完整定义在 main.py 的/tools端点以及 models.py 的 Pydantic 模型中:

工具名功能输入参数默认值
search_crossref_works按关键词搜索学术文献query(必填)、max_results(1–10)max_results=5
get_crossref_work按 DOI 获取单篇文献详情doi(必填)
get_crossref_works_by_author按作者名列出近期文献author(必填)、max_results(1–10)max_results=5

三个输入模型SearchWorksInputGetWorkInputAuthorWorksInput均继承pydantic.BaseModel,其中max_results默认为 5。所有工具响应统一使用ChatToolResponseresult/error二选一的可选字段),这保证了 Omi 侧解析结果时接口形状一致。

1. search_crossref_works:关键词检索

对应实现位于 main.py。它先将query去除首尾空白,并校验长度至少 2 个字符;随后调用crossref_get("/works", {"query": query, "rows": limited, "sort": "relevance", "order": "desc"}),即按相关度降序向 Crossref 拉取最多limited条结果,最后逐条输出序号. 标题 (年份)DOI: xxx两行文本。

注意max_results并非直接透传:clamp_max_results(main.py)会将其钳制在max(1, min(10, value))区间内,防止越界请求。

2. get_crossref_work:按 DOI 查详情

对应实现位于 main.py。入参doi需满足两个校验:必须包含/(否则返回Invalid DOI format. Example: 10.1038/nphys1170),且不得包含..(防路径注入类异常值)。合法后将 DOI 通过urllib.parse.quote编码后请求/works/{doi},输出Title / DOI / Year / Publisher / URL五行,并在存在摘要时追加Abstract: {abstract[:1200]}(截断至 1200 字符以控制 token 消耗)。

3. get_crossref_works_by_author:按作者检索

对应实现位于 main.py。逻辑与关键词检索对称,但请求参数改为query.authorsort: "published"order: "desc",即按出版时间降序返回该作者最近的作品列表。

底层实现要点:JATS 清洗与年份提取

Crossref 的abstract字段经常携带 JATS XML 标记(如<jats:p><jats:italic>),而 chat tools 需要纯文本。clean()函数(main.py)按三层正则处理:

  1. 无条件剥离<jats:...>开闭标签(_JATS_TAG);
  2. 无条件剥离通用闭合标签(_CLOSE_TAG);
  3. 对开标签要求其前一个字符不是字母/数字/下划线(_OPEN_TAG使用负向后行断言),从而保留a<b这类数学不等式。

同时clean()会先执行html.unescape,将&amp;还原为&。这一行为有专门的单测佐证:test_clean.py 中的四个用例分别验证了 JATS 段落标签剥离(<jats:p>Sleep quality improved <jats:italic>slightly</jats:italic>.</jats:p>Sleep quality improved slightly.)、HTML 实体反转义、不等式操作符保留(If a<b, then c>d.原样输出)以及闭合标签清理。

年份提取由extract_year()(main.py)完成:按published-printpublished-onlineissued的优先级读取date-parts[0][0],全部缺失时返回空字符串,保证输出行格式稳定。

HTTP 调用层与超时控制

所有上游请求统一走crossref_get()异步封装(main.py):每次调用创建httpx.AsyncClient(timeout=20.0),拼接CROSSREF_BASEhttps://api.crossref.org)发起 GET,异常时由上层捕获并转为ChatToolResponse(error=...)返回。20 秒超时对 Crossref 公共 API 的典型响应时间留有余量,同时避免工具调用长期挂起拖慢对话。

依赖版本钉死在 requirements.txt:fastapi==0.104.1uvicorn==0.24.0httpx==0.27.0pydantic==2.5.2,保证构建可复现。

本地运行

README 给出了最简启动方式:

pip install -r requirements.txt uvicorn main:app --reload --host 0.0.0.0 --port 8080

启动后服务提供四类端点:

  • GET /health:健康检查,返回{"status": "ok"}(main.py);
  • GET /tools:人类可读的工具清单(名称、描述、参数);
  • GET /.well-known/omi-tools.json:Omi 平台约定的工具清单端点(main.py),声明每个工具的endpointmethod: POST、参数properties/requiredauth_required: falsestatus_message(如Searching Crossref...),供 Omi 侧自动发现与挂载;
  • POST /tools/{tool_name}:三个工具的实际执行端点。

可以先用 curl 做端到端自测:

# 搜索文献 curl -X POST http://localhost:8080/tools/search_crossref_works \ -H "Content-Type: application/json" \ -d '{"query":"graph neural network", "max_results":3}' # 按 DOI 查详情 curl -X POST http://localhost:8080/tools/get_crossref_work \ -H "Content-Type: application/json" \ -d '{"doi":"10.1038/nphys1170"}' # 按作者查近期作品 curl -X POST http://localhost:8080/tools/get_crossref_works_by_author \ -H "Content-Type: application/json" \ -d '{"author":"Geoffrey Hinton", "max_results":3}'

同一仓库中的 plugins/omi-arxiv-app 遵循完全相同的架构(/health+/.well-known/omi-tools.json+POST /tools/*),可作为对照参考。

部署到 Railway / Heroku

插件为平台即服务(PaaS)部署做了两重准备:

  • Procfile:web: uvicorn main:app --host 0.0.0.0 --port ${PORT:-8080},兼容 Heroku 等按PORT环境变量注入端口的平台,本地缺省回退 8080;
  • railway.toml:Railway 部署配置,builder = "NIXPACKS"自动识别 Python 项目,startCommand同样读取$PORT,并配置healthcheckPath = "/health"healthcheckTimeout = 100restartPolicyType = "ON_FAILURE"restartPolicyMaxRetries = 10

由于服务无状态且不读写本地文件,--reload仅用于开发环境;生产部署时直接以 Procfile/railway.toml 中不带--reload的启动命令运行即可。

在 Omi 生态中的角色与适用边界

从 plugins/main.py 的聚合入口可见,Omi 插件体系把各集成作为独立 FastAPI 子应用挂载;而omi-crossref-app这类"工具型"插件则更倾向于独立部署,通过/.well-known/omi-tools.json清单被对话运行时发现,属于 Omi 的 chat tools 能力通道。

需要明确两点适用边界:其一,本插件是只读的元数据查询服务,不提供文献全文下载、引用导出或账号体系;其二,结果质量完全取决于 Crossref 公共索引的收录与字段完整度——缺失title/date-parts的记录会回退为Untitled/空年份(见cleanextract_year的防御逻辑),摘要字段仅在有值时输出且截断至 1200 字符。基于这些源码级事实,本插件最适合作为学术场景对话助手的轻量检索后端,与 plugins/omi-pubmed-app(NCBI E-utilities)、plugins/omi-arxiv-app(arXiv Atom feed)共同构成免认证学术检索工具矩阵。

【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询