Spaces:
Running
Running
feat: Lynote Notes open-source demo space (landing page + ready Gradio app)
Browse files- README.md +85 -5
- app.py +77 -0
- index.html +154 -18
- requirements.txt +2 -0
README.md
CHANGED
|
@@ -1,10 +1,90 @@
|
|
| 1 |
---
|
| 2 |
title: Lynote Notes
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
-
pinned:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Lynote Notes
|
| 3 |
+
emoji: π
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: static
|
| 7 |
+
pinned: true
|
| 8 |
+
license: mit
|
| 9 |
+
short_description: "Source-grounded AI notes with citations (open source)."
|
| 10 |
+
tags:
|
| 11 |
+
- ai-notes
|
| 12 |
+
- note-taker
|
| 13 |
+
- source-grounded
|
| 14 |
+
- citations
|
| 15 |
+
- rag
|
| 16 |
+
- local-first
|
| 17 |
+
- bilingual
|
| 18 |
+
- open-source
|
| 19 |
+
- python
|
| 20 |
+
- cli
|
| 21 |
---
|
| 22 |
|
| 23 |
+
# π Lynote Notes
|
| 24 |
+
|
| 25 |
+
**Source-grounded, bilingual, local-first AI note taker.** Turn documents, web pages, recordings, videos and YouTube links into structured notes where every bullet cites the exact source chunk it came from β so you can verify, edit and reuse notes instead of trusting a black box.
|
| 26 |
+
|
| 27 |
+
**Open source (MIT):** [github.com/lynote-ai/lynote-notes](https://github.com/lynote-ai/lynote-notes)
|
| 28 |
+
|
| 29 |
+
## The problem
|
| 30 |
+
|
| 31 |
+
AI note tools usually give you a summary you cannot check. If a note says "BM25 is used for retrieval", you should be able to click through to the sentence that said it. Lynote Notes makes traceability the default contract: notes are generated from your sources, and every claim links back to a chunk β including a timestamp for audio and video.
|
| 32 |
+
|
| 33 |
+
## Quickstart
|
| 34 |
+
|
| 35 |
+
```bash
|
| 36 |
+
git clone https://github.com/lynote-ai/lynote-notes.git
|
| 37 |
+
cd lynote-notes
|
| 38 |
+
pip install -e .
|
| 39 |
+
|
| 40 |
+
lynote-notes add lecture.md
|
| 41 |
+
lynote-notes add https://example.com/post
|
| 42 |
+
lynote-notes note --title "Weekly reading"
|
| 43 |
+
lynote-notes ask "What did we decide about pricing?"
|
| 44 |
+
lynote-notes export --note note_xxx --format anki --out cards.tsv
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
Optional extras add more source types:
|
| 48 |
+
|
| 49 |
+
```bash
|
| 50 |
+
pip install -e ".[pdf]" # PDF (pypdf)
|
| 51 |
+
pip install -e ".[docx]" # Word documents
|
| 52 |
+
pip install -e ".[media]" # audio/video transcription (faster-whisper)
|
| 53 |
+
pip install -e ".[youtube]" # YouTube captions (yt-dlp)
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
## Methodology
|
| 57 |
+
|
| 58 |
+
Five small stages, one traceable pipeline:
|
| 59 |
+
|
| 60 |
+
1. **Ingest** β text/Markdown, web pages, PDF, DOCX, YouTube captions, audio and video (optional backends behind extras, imported lazily).
|
| 61 |
+
2. **Chunk** β paragraph-aware splitting with overlap; media keeps start/end timestamps.
|
| 62 |
+
3. **Note** β a provider drafts sections from chunks (offline extractive by default, or any OpenAI-compatible LLM with automatic fallback). Providers only return chunk ids; the core resolves them into citations and drops ids that do not exist, so hallucinated citations cannot leak into a note.
|
| 63 |
+
4. **Ask** β dependency-free BM25-lite retrieval (CJK unigrams + bigrams, numeric tokens) finds the evidence; answers cite the chunks they came from.
|
| 64 |
+
5. **Export** β Markdown for reading, Anki TSV for memorising.
|
| 65 |
+
|
| 66 |
+
## Status and quality
|
| 67 |
+
|
| 68 |
+
- 58 offline tests, 92% line coverage, CI on Python 3.9 / 3.11 / 3.12
|
| 69 |
+
- Zero third-party dependencies in the core install
|
| 70 |
+
- Bilingual: English and Chinese out of the box
|
| 71 |
+
|
| 72 |
+
## Limitations
|
| 73 |
+
|
| 74 |
+
- The default provider is extractive β it selects and organises sentences from your sources rather than rewriting them. Use an LLM provider for more fluent notes.
|
| 75 |
+
- Retrieval is lexical (BM25): paraphrased questions can miss relevant passages; embeddings are on the roadmap.
|
| 76 |
+
- Transcription quality depends on the ASR model and audio quality.
|
| 77 |
+
- No live meeting capture by design: export the recording and upload it.
|
| 78 |
+
- Notes can still miss context or nuance β always check important facts, numbers and quotes against the cited source.
|
| 79 |
+
|
| 80 |
+
## More free Lynote tools
|
| 81 |
+
|
| 82 |
+
- [π Free AI Note Taker](https://huggingface.co/spaces/Lynote/free-ai-notes) β hosted product page (lynote.ai/ai-notes)
|
| 83 |
+
- [βοΈ Free AI Humanizer](https://huggingface.co/spaces/Lynote/free-ai-humanizer) β rewrite AI text into natural human prose
|
| 84 |
+
- [π Free AI Detector](https://huggingface.co/spaces/Lynote/free-ai-detector) β sentence-level AI text detection
|
| 85 |
+
- [πΌοΈ Free AI Image Detector](https://huggingface.co/spaces/Lynote/free-ai-image-detector) β check if an image was AI-generated
|
| 86 |
+
- [π§ humanize-text-model](https://huggingface.co/Lynote/humanize-text-model) β MIT-licensed bilingual T5 model
|
| 87 |
+
|
| 88 |
+
## License
|
| 89 |
+
|
| 90 |
+
MIT. See the [repository](https://github.com/lynote-ai/lynote-notes) for source and license notices.
|
app.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Interactive Lynote Notes demo (kept ready for PRO hosting).
|
| 2 |
+
|
| 3 |
+
Paste text, get a cited note, then ask questions grounded in the same text.
|
| 4 |
+
The demo uses the library's offline extractive provider, so it needs no model
|
| 5 |
+
and no API key β only Gradio and the lynote-notes package.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import tempfile
|
| 9 |
+
|
| 10 |
+
import gradio as gr
|
| 11 |
+
|
| 12 |
+
from lynote_notes import Workspace
|
| 13 |
+
|
| 14 |
+
MAX_CHARS = 5_000
|
| 15 |
+
UTM = (
|
| 16 |
+
"https://lynote.ai/ai-notes?utm_source=huggingface"
|
| 17 |
+
"&utm_medium=space&utm_campaign=hf_launch&utm_content=oss_notes"
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _workspace(text: str) -> Workspace:
|
| 22 |
+
ws = Workspace(tempfile.mkdtemp())
|
| 23 |
+
ws.add_text(text, "Pasted text")
|
| 24 |
+
return ws
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def make_note(text: str, title: str):
|
| 28 |
+
text = (text or "").strip()
|
| 29 |
+
if len(text) < 80:
|
| 30 |
+
return "Add at least 80 characters of source text."
|
| 31 |
+
if len(text) > MAX_CHARS:
|
| 32 |
+
return f"Input is limited to {MAX_CHARS:,} characters in this demo."
|
| 33 |
+
ws = _workspace(text)
|
| 34 |
+
note = ws.make_note(title or "Your note")
|
| 35 |
+
return ws.export_note(note, "md")
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def ask_question(text: str, question: str):
|
| 39 |
+
text = (text or "").strip()
|
| 40 |
+
question = (question or "").strip()
|
| 41 |
+
if not text or not question:
|
| 42 |
+
return "Paste some source text and ask a question."
|
| 43 |
+
ws = _workspace(text)
|
| 44 |
+
answer = ws.ask(question)
|
| 45 |
+
lines = [answer.text, ""]
|
| 46 |
+
for index, citation in enumerate(answer.citations, start=1):
|
| 47 |
+
lines.append(f"[{index}] {citation.source_title} Β· {citation.locator} β {citation.snippet}")
|
| 48 |
+
lines.append("")
|
| 49 |
+
lines.append(f"Try the full product: {UTM}")
|
| 50 |
+
return "\n".join(lines)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
with gr.Blocks(title="Lynote Notes β Source-Grounded AI Note Taker") as demo:
|
| 54 |
+
gr.Markdown(
|
| 55 |
+
"# π Lynote Notes\n"
|
| 56 |
+
"Source-grounded notes with citations β every bullet links back to the exact "
|
| 57 |
+
"source chunk. Open source: [github.com/lynote-ai/lynote-notes]"
|
| 58 |
+
"(https://github.com/lynote-ai/lynote-notes)"
|
| 59 |
+
)
|
| 60 |
+
source = gr.Textbox(
|
| 61 |
+
label="Source text (80β5,000 characters)",
|
| 62 |
+
placeholder="Paste a lecture transcript, article, or meeting notesβ¦",
|
| 63 |
+
lines=10,
|
| 64 |
+
)
|
| 65 |
+
with gr.Tab("Generate note"):
|
| 66 |
+
title = gr.Textbox(label="Note title", value="Your note")
|
| 67 |
+
note_button = gr.Button("Generate cited note", variant="primary")
|
| 68 |
+
note_output = gr.Markdown()
|
| 69 |
+
note_button.click(make_note, inputs=[source, title], outputs=note_output)
|
| 70 |
+
with gr.Tab("Ask a question"):
|
| 71 |
+
question = gr.Textbox(label="Question", placeholder="What did we decide about pricing?")
|
| 72 |
+
ask_button = gr.Button("Ask", variant="primary")
|
| 73 |
+
answer_output = gr.Markdown()
|
| 74 |
+
ask_button.click(ask_question, inputs=[source, question], outputs=answer_output)
|
| 75 |
+
|
| 76 |
+
if __name__ == "__main__":
|
| 77 |
+
demo.launch()
|
index.html
CHANGED
|
@@ -1,19 +1,155 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<title>Lynote Notes β Source-Grounded AI Note Taker (Open Source) | Lynote</title>
|
| 7 |
+
<meta name="description" content="Open-source, source-grounded AI note taker: turn documents, web pages, audio, video and YouTube links into notes where every bullet cites the exact source chunk. Local-first, bilingual, zero-dependency core." />
|
| 8 |
+
<meta name="keywords" content="open source ai note taker, source grounded notes, citations, rag notes, local first notes, ai notes cli, anki export, bilingual notes" />
|
| 9 |
+
<meta property="og:title" content="Lynote Notes β Source-Grounded AI Note Taker (Open Source)" />
|
| 10 |
+
<meta property="og:description" content="Notes where every bullet cites the exact source chunk. MIT licensed, local-first, bilingual." />
|
| 11 |
+
<style>
|
| 12 |
+
:root { --bg:#0f1420; --card:#171f31; --card2:#1b2540; --fg:#e8edf7; --muted:#9aa7c0; --accent:#7b6dff; --accent2:#34d399; --line:#23304a; }
|
| 13 |
+
* { margin:0; padding:0; box-sizing:border-box; }
|
| 14 |
+
body { background:var(--bg); color:var(--fg); font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif; line-height:1.7; }
|
| 15 |
+
.wrap { max-width:960px; margin:0 auto; padding:48px 24px 72px; }
|
| 16 |
+
.logo { font-size:15px; letter-spacing:3px; color:var(--muted); text-transform:uppercase; }
|
| 17 |
+
.badge { display:inline-block; font-size:13px; padding:4px 14px; border-radius:999px; border:1px solid #2c3a55; color:#b9c6e2; background:rgba(123,109,255,.08); margin:20px 0; }
|
| 18 |
+
h1 { font-size:clamp(30px,5.5vw,48px); line-height:1.2; margin:0 0 16px; background:linear-gradient(90deg,var(--accent),var(--accent2)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
|
| 19 |
+
.sub { font-size:18px; color:var(--muted); max-width:720px; }
|
| 20 |
+
.stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:14px; margin:34px 0 8px; }
|
| 21 |
+
.stat { background:var(--card); border:1px solid var(--line); border-radius:14px; padding:18px; text-align:center; }
|
| 22 |
+
.stat b { display:block; font-size:24px; background:linear-gradient(90deg,var(--accent),var(--accent2)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
|
| 23 |
+
.stat span { font-size:13px; color:var(--muted); }
|
| 24 |
+
h2 { font-size:26px; margin:56px 0 8px; }
|
| 25 |
+
.section-note { color:var(--muted); margin-bottom:22px; }
|
| 26 |
+
.grid { list-style:none; display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:14px; }
|
| 27 |
+
.grid li { background:var(--card); border:1px solid var(--line); border-radius:14px; padding:18px 20px; }
|
| 28 |
+
.grid strong { display:block; color:#fff; margin-bottom:6px; font-size:16px; }
|
| 29 |
+
.grid span { color:var(--muted); font-size:14.5px; }
|
| 30 |
+
.steps { list-style:none; display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:8px; }
|
| 31 |
+
.steps li { background:var(--card); border:1px solid var(--line); border-radius:14px; padding:20px; }
|
| 32 |
+
.steps em { display:block; font-style:normal; color:var(--accent2); font-size:13px; letter-spacing:1px; text-transform:uppercase; margin-bottom:6px; }
|
| 33 |
+
.steps strong { display:block; font-size:16px; margin-bottom:6px; }
|
| 34 |
+
.steps span { color:var(--muted); font-size:14.5px; }
|
| 35 |
+
pre { background:var(--card2); border:1px solid var(--line); border-radius:12px; padding:16px 18px; overflow-x:auto; font-size:13.5px; line-height:1.6; color:#d7e1f5; }
|
| 36 |
+
code { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
|
| 37 |
+
details { background:var(--card); border:1px solid var(--line); border-radius:12px; padding:14px 18px; margin-bottom:10px; }
|
| 38 |
+
summary { cursor:pointer; font-weight:600; color:#fff; }
|
| 39 |
+
details p { color:var(--muted); font-size:14.5px; margin-top:8px; }
|
| 40 |
+
.cta { display:inline-block; background:linear-gradient(90deg,var(--accent),var(--accent2)); color:#fff; font-size:17px; font-weight:600; padding:14px 30px; border-radius:12px; text-decoration:none; margin:36px 0 8px; }
|
| 41 |
+
.cta:hover { opacity:.9; }
|
| 42 |
+
.cta.secondary { background:var(--card); border:1px solid var(--line); font-weight:500; margin-left:10px; }
|
| 43 |
+
.links-label { font-size:12px; color:var(--muted); letter-spacing:1.5px; text-transform:uppercase; margin-top:36px; }
|
| 44 |
+
.links { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin-top:10px; }
|
| 45 |
+
.chip { font-size:14px; padding:8px 18px; border-radius:999px; border:1px solid var(--line); color:var(--fg); text-decoration:none; background:var(--card); }
|
| 46 |
+
.chip b { color:var(--accent2); }
|
| 47 |
+
.chip:hover { border-color:var(--accent); color:#fff; }
|
| 48 |
+
.note { font-size:13.5px; color:var(--muted); margin-top:24px; max-width:780px; }
|
| 49 |
+
</style>
|
| 50 |
+
</head>
|
| 51 |
+
<body>
|
| 52 |
+
<div class="wrap">
|
| 53 |
+
|
| 54 |
+
<div class="logo">Lynote</div>
|
| 55 |
+
<span class="badge">OPEN SOURCE Β· MIT Β· ZERO-DEPENDENCY CORE</span>
|
| 56 |
+
<h1>Lynote Notes</h1>
|
| 57 |
+
<p class="sub">
|
| 58 |
+
Source-grounded, bilingual, local-first AI note taker. Turn documents, web pages,
|
| 59 |
+
recordings, videos and YouTube links into structured notes where every bullet cites
|
| 60 |
+
the exact source chunk it came from β so you can verify, edit and reuse notes
|
| 61 |
+
instead of trusting a black box.
|
| 62 |
+
</p>
|
| 63 |
+
|
| 64 |
+
<a class="cta" href="https://github.com/lynote-ai/lynote-notes" target="_blank" rel="noopener">
|
| 65 |
+
View on GitHub β
|
| 66 |
+
</a>
|
| 67 |
+
<a class="cta secondary" href="https://lynote.ai/ai-notes?utm_source=huggingface&utm_medium=space&utm_campaign=hf_launch&utm_content=oss_notes" target="_blank" rel="noopener">
|
| 68 |
+
Try Lynote AI Notes
|
| 69 |
+
</a>
|
| 70 |
+
|
| 71 |
+
<div class="links-label">Free Lynote tools Β· open source</div>
|
| 72 |
+
<div class="links">
|
| 73 |
+
<a class="chip" href="https://github.com/lynote-ai/lynote-notes" target="_blank" rel="noopener"><b>GitHub</b> β lynote-ai/lynote-notes</a>
|
| 74 |
+
<a class="chip" href="https://huggingface.co/spaces/Lynote/free-ai-notes" target="_blank" rel="noopener">Free AI Note Taker β</a>
|
| 75 |
+
<a class="chip" href="https://huggingface.co/spaces/Lynote/free-ai-humanizer" target="_blank" rel="noopener">Free AI Humanizer β</a>
|
| 76 |
+
<a class="chip" href="https://huggingface.co/spaces/Lynote/free-ai-detector" target="_blank" rel="noopener">Free AI Detector β</a>
|
| 77 |
+
<a class="chip" href="https://huggingface.co/spaces/Lynote/free-ai-image-detector" target="_blank" rel="noopener">Free AI Image Detector β</a>
|
| 78 |
+
</div>
|
| 79 |
+
|
| 80 |
+
<div class="stats">
|
| 81 |
+
<div class="stat"><b>58</b><span>Tests Passing</span></div>
|
| 82 |
+
<div class="stat"><b>92%</b><span>Test Coverage</span></div>
|
| 83 |
+
<div class="stat"><b>0</b><span>Core Dependencies</span></div>
|
| 84 |
+
<div class="stat"><b>MIT</b><span>License</span></div>
|
| 85 |
+
</div>
|
| 86 |
+
|
| 87 |
+
<h2>Why Source-Grounded?</h2>
|
| 88 |
+
<p class="section-note">AI note tools usually give you a summary you cannot check. Lynote Notes is built around traceability.</p>
|
| 89 |
+
<ul class="grid">
|
| 90 |
+
<li><strong>Citations as a Contract</strong><span>Every bullet carries a source citation. Providers return chunk ids; the core resolves them and drops anything that does not exist β a hallucinated citation cannot leak into a note.</span></li>
|
| 91 |
+
<li><strong>Offline by Default</strong><span>The default extractive provider needs no model and no network. Configure any OpenAI-compatible endpoint (Ollama, vLLM, OpenAI) for generative notes, with automatic fallback.</span></li>
|
| 92 |
+
<li><strong>Bilingual by Design</strong><span>CJK unigrams + bigrams, sentence splitting on γοΌοΌοΌ β English and Chinese work out of the box.</span></li>
|
| 93 |
+
<li><strong>Local-First Workspace</strong><span>One workspace is one SQLite file. No server, no account, inspectable with standard tools.</span></li>
|
| 94 |
+
<li><strong>Media Timestamps</strong><span>Audio and video citations point to HH:MM:SS, not just "somewhere in the file".</span></li>
|
| 95 |
+
<li><strong>Reuse Built In</strong><span>Export Markdown for reading or Anki TSV for memorising β straight from the same cited note.</span></li>
|
| 96 |
+
</ul>
|
| 97 |
+
|
| 98 |
+
<h2>Quickstart</h2>
|
| 99 |
+
<p class="section-note">Python 3.9+, works offline.</p>
|
| 100 |
+
<pre><code>git clone https://github.com/lynote-ai/lynote-notes.git
|
| 101 |
+
cd lynote-notes
|
| 102 |
+
pip install -e .
|
| 103 |
+
|
| 104 |
+
lynote-notes add lecture.md
|
| 105 |
+
lynote-notes add https://example.com/post
|
| 106 |
+
lynote-notes note --title "Weekly reading"
|
| 107 |
+
lynote-notes ask "What did we decide about pricing?"
|
| 108 |
+
lynote-notes export --note note_xxx --format anki --out cards.tsv</code></pre>
|
| 109 |
+
|
| 110 |
+
<h2>How It Works</h2>
|
| 111 |
+
<p class="section-note">Five small stages, one traceable pipeline.</p>
|
| 112 |
+
<ol class="steps">
|
| 113 |
+
<li><em>Step 1</em><strong>Ingest</strong><span>Text/Markdown, web pages, PDF, DOCX, YouTube captions, audio and video β optional backends stay behind extras.</span></li>
|
| 114 |
+
<li><em>Step 2</em><strong>Chunk</strong><span>Paragraph-aware splitting with overlap; media keeps timestamps.</span></li>
|
| 115 |
+
<li><em>Step 3</em><strong>Note</strong><span>A provider drafts sections from chunks; the core resolves every bullet to a real citation.</span></li>
|
| 116 |
+
<li><em>Step 4</em><strong>Ask</strong><span>BM25-lite retrieval finds the evidence; answers cite the chunks they came from.</span></li>
|
| 117 |
+
<li><em>Step 5</em><strong>Export</strong><span>Markdown for reading, Anki TSV for memorising.</span></li>
|
| 118 |
+
</ol>
|
| 119 |
+
|
| 120 |
+
<h2>Limitations</h2>
|
| 121 |
+
<ul class="grid">
|
| 122 |
+
<li><strong>Extractive Default</strong><span>The default provider selects and organises sentences from your sources rather than rewriting them. Use an LLM provider for more fluent notes.</span></li>
|
| 123 |
+
<li><strong>Lexical Retrieval</strong><span>BM25 matches words, not meanings. Paraphrased questions can miss relevant passages; embeddings are on the roadmap.</span></li>
|
| 124 |
+
<li><strong>Transcription Quality</strong><span>Depends on the ASR model size and audio quality β check important details against the source.</span></li>
|
| 125 |
+
<li><strong>No Live Capture</strong><span>No meeting bots by design: export the recording and upload it.</span></li>
|
| 126 |
+
</ul>
|
| 127 |
+
|
| 128 |
+
<h2>FAQ</h2>
|
| 129 |
+
<details>
|
| 130 |
+
<summary>Is Lynote Notes the same as Lynote AI Notes?</summary>
|
| 131 |
+
<p>Lynote Notes is the open-source core (MIT). Lynote AI Notes is the hosted product at lynote.ai/ai-notes, which adds a workspace UI, more formats and managed AI. The CLI and library here work standalone.</p>
|
| 132 |
+
</details>
|
| 133 |
+
<details>
|
| 134 |
+
<summary>Do I need an API key?</summary>
|
| 135 |
+
<p>No. The default extractive provider runs offline. An OpenAI-compatible endpoint is optional for generative notes.</p>
|
| 136 |
+
</details>
|
| 137 |
+
<details>
|
| 138 |
+
<summary>Does it work with Chinese content?</summary>
|
| 139 |
+
<p>Yes β tokenization and sentence splitting are bilingual by design, and notes can be generated from mixed-language workspaces.</p>
|
| 140 |
+
</details>
|
| 141 |
+
<details>
|
| 142 |
+
<summary>How do I verify a citation?</summary>
|
| 143 |
+
<p>Every citation names the source, a locator ("chunk 4" or "00:12:30") and a snippet. Open the source at that locator and compare β that is the point of the design.</p>
|
| 144 |
+
</details>
|
| 145 |
+
|
| 146 |
+
<p class="note">
|
| 147 |
+
This Space is a static demo page for the open-source project. The interactive Gradio demo
|
| 148 |
+
(paste text β cited note β ask questions) is kept ready in this repository and will be
|
| 149 |
+
enabled once the account has PRO hosting. Full product:
|
| 150 |
+
<a href="https://lynote.ai/ai-notes" style="color:var(--accent)">lynote.ai/ai-notes</a>.
|
| 151 |
+
AI notes can miss context or nuance β always check important details against the cited source.
|
| 152 |
+
</p>
|
| 153 |
+
</div>
|
| 154 |
+
</body>
|
| 155 |
</html>
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=4.0
|
| 2 |
+
lynote-notes @ git+https://github.com/lynote-ai/lynote-notes.git@v0.1.0
|