AnkiWeb
- Rating
- 0 (👍 0 · 👎 0)
- Updated
- 2025-12-31
- Anki versions
- 2.1.1~
- Description language
- ja
AnkiWeb addon 8664763
Enables one-click AI queries during card review through a template button, auto-filling specified fields with configurable Cloudflare Workers or other APIs, requiring Edit Field During Review.
Open on AnkiWeb GitHub Ask about alternatives
stale
| Min Anki | Max Anki | Updated |
|---|---|---|
| 2.1.1 | + | 2025-12-31 |
Loading…
Automatically fills language-learning flashcard fields via AI providers, audio, and images, supporting any language pair with preview, cache, and field mapping.
Transcribes audio files attached to Anki cards via Deepgram or Whisper, offering API key configuration, fill-in and template-filter options with caching.
Looks up Turkish vocabulary from the official TDK dictionary to fill notes with definitions, examples, and pronunciations, supporting editor buttons, bulk browser filling, audio filters, and double-click tooltips.
Integrates Open Evidence medical AI into Anki's sidebar with five USMLE preset queries, auto-send, per-card chat, original AI modes, and a UI overhaul.
Exports Anki cards as images using customizable Jinja2 HTML templates and CSS, with options for resolution, cloze replacement, excluded fields, per-note templates, and ImageMagick auto-cropping.
Automatically fills Chinese note fields with translations, pinyin, audio, characters, definitions, examples, tone colors, and frequency for Anki 25.07+.
这是一个Anki插件,允许您在卡片复习时一键调用AI(通过Cloudflare Workers或其他API)并将结果自动填入指定字段(需要配合1020366288插件)。
卡片模板中添加按钮
例 <div style='font-size: 40px'><button onclick="pycmd('CF_aiGenerate')" style="padding: 10px 1px; background: #3d8b40;color:#3d4b40; font-size: 14px;float: right">——</button>
Edit Field During Review 插件的兼容性,更新解析后无需刷新卡片。安装插件与依赖插件:
[8664763] 安装。[1020366288] 安装依赖插件Edit Field During Review。获取 API Key:
配置插件:
Authorization ,如 Bearer abc123sm 。提问字段 (例如:Expression) 和 回答字段 (例如:Edit)。在卡片模板中添加按钮:
<button onclick="pycmd('CF_aiGenerate')" style="padding: 10px 1px; background: #3d8b40; font-size: 14px;">AI提问</button>
anki-ai-proxyCF worker示例.js的内容粘贴进去curl -X POST "https://anki-ai-proxy.abc123sm.workers.dev" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer abc123sm" \
-d '{
"messages": [{"role": "user", "content": "こんにちは"}],
"model": "@cf/ibm-granite/granite-4.0-h-micro"
}'
export default {
async fetch(request, env) {
// 只允许 POST
if (request.method !== "POST") {
return new Response("Method Not Allowed", { status: 405 });
}
// Bearer Token 验证
const EXPECTED_TOKEN = "Bearer abc123sm";
const auth = request.headers.get("Authorization");
if (!auth || auth !== EXPECTED_TOKEN) {
return new Response("Unauthorized", { status: 401 });
}
let body;
try {
body = await request.json();
} catch {
return new Response("Invalid JSON", { status: 400 });
}
const messages = body.messages;
if (!Array.isArray(messages)) {
return new Response("Missing messages", { status: 400 });
}
const model = body.model || "@cf/ibm-granite/granite-4.0-h-micro";
try {
// 调用AI模型
const result = await env.AI.run(model, { messages });
// 调试:打印返回结果
console.log("使用模型:", model);
console.log("AI返回结果:", JSON.stringify(result));
// 根据不同的模型返回格式,提取回复内容
let replyContent;
// ========== 模型1: @cf/ibm-granite/granite-4.0-h-micro ==========
if (model === "@cf/ibm-granite/granite-4.0-h-micro") {
// 处理IBM Granite模型的复杂嵌套格式
if (result.choices && result.choices.length > 0) {
if (result.choices[0].message && result.choices[0].message.content) {
const content = result.choices[0].message.content;
// 如果content是字符串,直接使用
if (typeof content === 'string') {
replyContent = content;
}
// 如果content是对象,尝试进一步提取
else if (typeof content === 'object' && content.choices) {
replyContent = content.choices[0]?.message?.content || JSON.stringify(content);
}
}
}
// 方法2: 如果返回的是简单response字段
else if (result.response) {
replyContent = result.response;
}
// 方法3: 其他格式,直接转换为字符串
else {
replyContent = typeof result === 'string' ? result : JSON.stringify(result);
}
}
// ========== 模型2: @cf/meta/llama-3.2-1b-instruct ==========
else if (model === "@cf/meta/llama-3.2-1b-instruct") {
// 处理Llama模型的简单格式
if (result.response) {
replyContent = result.response;
}
// 如果返回的是标准OpenAI格式
else if (result.choices && result.choices.length > 0) {
const message = result.choices[0].message;
if (message && message.content) {
replyContent = message.content;
}
}
// 其他情况
else {
replyContent = typeof result === 'string' ? result : JSON.stringify(result);
}
}
// ========== 其他模型(通用处理) ==========
else {
// 通用处理逻辑
if (result.response) {
replyContent = result.response;
} else if (result.choices && result.choices.length > 0) {
const message = result.choices[0].message;
if (message && message.content) {
replyContent = message.content;
}
} else {
replyContent = typeof result === 'string' ? result : JSON.stringify(result);
}
}
// 返回标准的OpenAI格式
return new Response(JSON.stringify({
choices: [{
message: {
role: "assistant",
content: replyContent || "AI未返回有效回复"
}
}]
}), {
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
});
} catch (error) {
console.error("AI调用失败:", error);
return new Response(JSON.stringify({
error: "AI模型调用失败",
details: error.message
}), { status: 500 });
}
},
};
{{Audio}}
<div>{{Snapshot}}</div>
<div>{{am-highlighted}}</div>
<script>
function copyReading(button) {
// 从按钮的anniu属性获取特定字段的内容
const readingText = button.getAttribute('data-copy-anniu');
// 创建临时textarea元素
const textarea = document.createElement('textarea');
textarea.value = readingText;
document.body.appendChild(textarea);
// copy
textarea.select();
document.execCommand('copy');
// delete
document.body.removeChild(textarea);
// update
const originalText = button.textContent;
button.textContent = '搞掂';
button.classList.add('copied');
}
</script>
<button class="copy-btn" onclick="copyReading(this)" data-copy-anniu="{{Expression}}">复制</button>
<div>{{am-highlighted}}</div>
<div>{{Snapshot}}</div>
<button onclick="pycmd('aiGenerate')" style="padding: 10px 1px; background: #3d8b40;color:#3d8b40; font-size: 14px;float: right">——</button><div style='font-size: 40px'><button onclick="pycmd('CF_aiGenerate')" style="padding: 10px 1px; background: #3d8b40;color:#3d4b40; font-size: 14px;float: right">——</button>{{edit:Meaning}}</div>
<div style='font-size: 25px; text-align:start'>{{edit:Edit}}</div>
.card {
font-family: arial;
font-size: 50px;
text-align: center;
color: #CDC8B1;
background-color: #25390c;##f1e5c9;
}
.card.nightMode {
font-family: arial;
font-size: 50px;
text-align: center;
color: #8B8878;
#background-color: #25390c;
}
.expression{
font-size: 40px;
}
[morph-status=unknown] { color: red; }
[morph-status=learning] { color: #1E90FF; }
[morph-status=known] { color: green; }
.copy-btn {
padding: 10px 1px;
background-color: #3d8b40;
font-size: 18px; /* 可用 !important增大字体 */
float: left;
}
.copy-btn.copied {
background-color: #666;
}
<img alt="效果预览" src="https://github.com/abc123sm/anki_CF_aitiwen/raw/main/pic/1.png" />
因为使用的字段不同,所以可以与AI提问共存(一个是 CF_aiGenerate,一个是 aiGenerate) <img alt="共存" src="https://github.com/abc123sm/anki_CF_aitiwen/raw/main/pic/3.png" />
<img alt="CF AI worker" src="https://github.com/abc123sm/anki_CF_aitiwen/raw/main/pic/4.png" />
<img alt="反代API" src="https://github.com/abc123sm/anki_CF_aitiwen/raw/main/pic/2.png" />
每天有免费0.11美元额度,反正对我来说是够够的
@cf/ibm-granite/granite-4.0-h-micro
最便宜,但有些时候给英文 $0.017
@cf/meta/llama-3.2-1b-instruct
也挺便宜,但有些时候给英文,幻觉还多 $0.027
@cf/meta/llama-3.2-3b-instruct
我目前感觉很不错的,推荐 $0.051
@cf/meta/llama-3.1-8b-instruct-fast
@cf/meta/llama-3.1-8b-instruct-fp8-fast
8b还会天天爆英文…… $0.045
@cf/meta/llama-2-7b-chat-fp16
不是,怎么meta的这么喜欢爆英文 $0.56 per M input tokens
@cf/qwen/qwen3-30b-a3b-fp8
喜欢给一堆文法解释,我是文法无用主义者,而且我prompt明明有避免使用语法术语这句话,他却无视了 $0.051
@cf/meta/llama-3.3-70b-instruct-fp8-fast
挺好用 $0.293
@cf/google/gemma-3-12b-it
挺好用 $0.345
速度好慢,结果乱给,不要用推理模型,不适合咱们场景
@cf/deepseek-ai/deepseek-r1-distill-qwen-32b
@cf/mistral/mistral-7b-instruct-v0.1
如果你遇到任何问题或有功能建议,欢迎到本项目的 GitHub Issues 页面提交。
或者 这个TG频道。