llm-extension.md 3.6 KB

llm-extension — LLM 抽象层预留

本文件回答:LLM 抽象层的接口定义、本期实现边界、未来扩展时的落点。 依赖:无

一、定位

本期不实现任何 LLM 调用。只定义抽象接口,为后续 RAG 检索、笔记静态翻译等扩展预留位置。接口先放在这里,防止业务代码把“以后要接 LLM”这件事忘掉,也防止届时改动侵入现有模块。

二、本期实现边界

  • 只定义 Go interface,放在 backend/internal/llm 包下;
  • 不实现任何 provider(不接 OpenAI、不接 DeepSeek、不接本地模型);
  • 不引入任何 LLM SDK 依赖;
  • 不定义配置项(API key、base URL、模型名等一概不出现);
  • 不写 HTTP 接口,前端无感知。

三、接口定义

接口按“能力”划分,不按“模型”划分。业务层只依赖能力接口,不依赖具体 provider。

package llm

import "context"

// Provider 是所有 LLM 能力的根接口。
// 本期不实现,仅定义。
type Provider interface {
    // Translate 将文本从源语言翻译为目标语言。
    // 同步调用,适用于短文本(单篇笔记正文以内)。
    Translate(ctx context.Context, req TranslateRequest) (TranslateResponse, error)

    // Embed 生成文本的向量表示,供 RAG 检索使用。
    // 单条文本生成一个向量。
    Embed(ctx context.Context, text string) ([]float32, error)
}

type TranslateRequest struct {
    Text           string // 待翻译文本
    SourceLanguage string // 源语言代码,如 "zh"、"en";空表示自动检测
    TargetLanguage string // 目标语言代码
}

type TranslateResponse struct {
    Text string // 翻译结果
}

说明:

  • Translate 和 Embed 是两个独立能力,未来可以由不同 provider 实现;
  • 接口只覆盖“输入文本 → 输出结果”,不涉及流式、不涉及对话、不涉及 tool use——这些不是本项目当前场景需要的;
  • Provider 是根接口,未来如需拆分(如 Translator / Embedder 两个接口),在实现第一个 provider 时再拆,现在不预先拆。

四、未来扩展的落点

以下内容本期不实现,但写在这里,标明未来改动应该落在哪,避免届时重新设计。

4.1 配置项

未来接入 provider 时,architecture.md 的配置项一节需要新增:

  • LLM_PROVIDER:provider 名(如 openai / deepseek / local);
  • LLM_API_KEY:API 密钥(如适用);
  • LLM_BASE_URL:API 地址(如适用);
  • LLM_MODEL:模型名。

4.2 触发方式

  • 翻译:同步调用。用户在笔记详情页点“翻译”,后端调 Translate,返回结果直接展示,不落库。
  • RAG 检索:异步任务。Embed 在笔记保存后异步执行,向量存储方案届时决定(pgvector 或外部存储),本期不引入。

4.3 数据出境规则

未来接入外部 LLM 时,必须明确哪些内容允许发送出去:

  • 只有 public 笔记 允许送往外部 provider;
  • private 笔记的翻译 / 嵌入只能走本地模型,或经用户显式确认后临时发送;
  • 这条规则在实现第一个 provider 时写入 conventions.md 第四节,本文件不预先写死。

五、硬性约束

  • 业务层不得直接 import 任何 LLM SDK,只能 import backend/internal/llm;
  • 抽象层不泄漏具体 provider 的 SDK 类型到业务层(如 OpenAI 的 ChatCompletionRequest 不得出现在接口签名里);
  • 本期不写任何实现代码,不建 backend/internal/llm/openai 之类的子包。
苏ICP备2026082406号
苏公网安备 待审核