Skip to content

Commit cefc300

Browse files
committed
feat: add rag cli
1 parent bf59012 commit cefc300

7 files changed

Lines changed: 905 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ base64 = "0.22"
1616
papers-openalex = { path = "crates/papers-openalex", version = "0.2.0" }
1717
papers-zotero = { path = "crates/papers-zotero", version = "0.2.0" }
1818
papers-core = { path = "crates/papers-core", version = "0.2.0" }
19+
papers-rag = { path = "crates/papers-rag", version = "0.2.0" }
1920
dirs = "6"
2021
bon = "3"
2122
clap = { version = "4", features = ["derive", "wrap_help"] }

crates/papers-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ path = "src/main.rs"
1515
papers-core.workspace = true
1616
papers-zotero.workspace = true
1717
papers-datalab.workspace = true
18+
papers-rag.workspace = true
1819
clap.workspace = true
1920
dirs.workspace = true
2021
serde.workspace = true

crates/papers-cli/src/cli.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,153 @@ pub enum EntityCommand {
8282
#[command(subcommand)]
8383
cmd: SelectionCommand,
8484
},
85+
/// Local RAG index: semantic search over your indexed papers
86+
Rag {
87+
#[command(subcommand)]
88+
cmd: RagCommand,
89+
},
90+
}
91+
92+
#[derive(Subcommand)]
93+
pub enum RagCommand {
94+
/// Semantic search over indexed paper chunks
95+
Search {
96+
/// Natural language search query
97+
query: String,
98+
#[arg(long)]
99+
selection: Option<String>,
100+
#[arg(long)]
101+
paper_id: Option<String>,
102+
#[arg(long)]
103+
chapter_idx: Option<u16>,
104+
#[arg(long)]
105+
section_idx: Option<u16>,
106+
#[arg(long)]
107+
year_min: Option<u16>,
108+
#[arg(long)]
109+
year_max: Option<u16>,
110+
#[arg(long)]
111+
venue: Option<String>,
112+
#[arg(long)]
113+
tag: Option<Vec<String>>,
114+
/// Granularity: chapter | section | paragraph
115+
#[arg(long)]
116+
depth: Option<String>,
117+
#[arg(long, short = 'n', default_value = "5")]
118+
limit: u16,
119+
#[arg(long)]
120+
json: bool,
121+
},
122+
/// Search for figures, tables, and diagrams
123+
SearchFigures {
124+
/// Natural language description of the figure to find
125+
query: String,
126+
#[arg(long)]
127+
selection: Option<String>,
128+
#[arg(long)]
129+
paper_id: Option<String>,
130+
/// Filter: "figure" or "table"
131+
#[arg(long)]
132+
figure_type: Option<String>,
133+
#[arg(long, short = 'n', default_value = "5")]
134+
limit: u16,
135+
#[arg(long)]
136+
json: bool,
137+
},
138+
/// Retrieve a specific chunk by ID
139+
GetChunk {
140+
/// Chunk ID (e.g. YFACFA8C/ch1/s2/p3)
141+
chunk_id: String,
142+
#[arg(long)]
143+
json: bool,
144+
},
145+
/// Fetch all chunks in a section in reading order
146+
GetSection {
147+
/// Paper ID (DOI or item key)
148+
paper_id: String,
149+
#[arg(long)]
150+
chapter_idx: u16,
151+
#[arg(long)]
152+
section_idx: u16,
153+
#[arg(long)]
154+
json: bool,
155+
},
156+
/// Fetch all content of a chapter
157+
GetChapter {
158+
/// Paper ID (DOI or item key)
159+
paper_id: String,
160+
#[arg(long)]
161+
chapter_idx: u16,
162+
#[arg(long)]
163+
json: bool,
164+
},
165+
/// Get figure details by ID
166+
GetFigure {
167+
/// Figure ID (e.g. YFACFA8C/fig3)
168+
figure_id: String,
169+
#[arg(long)]
170+
json: bool,
171+
},
172+
/// Show the table of contents for a paper
173+
Outline {
174+
/// Paper ID (DOI or item key)
175+
paper_id: String,
176+
#[arg(long)]
177+
json: bool,
178+
},
179+
/// List indexed papers with optional filters
180+
ListPapers {
181+
#[arg(long)]
182+
selection: Option<String>,
183+
#[arg(long)]
184+
year_min: Option<u16>,
185+
#[arg(long)]
186+
year_max: Option<u16>,
187+
#[arg(long)]
188+
venue: Option<String>,
189+
#[arg(long)]
190+
tag: Option<Vec<String>>,
191+
#[arg(long)]
192+
author: Option<Vec<String>>,
193+
/// Sort by: "year" (default) or "title"
194+
#[arg(long)]
195+
sort: Option<String>,
196+
#[arg(long, short = 'n', default_value = "50")]
197+
limit: u16,
198+
#[arg(long)]
199+
json: bool,
200+
},
201+
/// List all tags and counts
202+
ListTags {
203+
#[arg(long)]
204+
selection: Option<String>,
205+
#[arg(long)]
206+
json: bool,
207+
},
208+
/// Index a paper from local DataLab cache into the RAG database
209+
Ingest {
210+
/// Zotero item key (directory name under the DataLab cache)
211+
item_key: String,
212+
/// Override paper_id (default: DOI from meta.json, else item_key)
213+
#[arg(long)]
214+
paper_id: Option<String>,
215+
/// Add tags to this paper (repeatable)
216+
#[arg(long)]
217+
tag: Option<Vec<String>>,
218+
/// Force re-index even if already indexed
219+
#[arg(long)]
220+
force: bool,
221+
#[arg(long)]
222+
json: bool,
223+
},
224+
/// Index all papers in the DataLab cache
225+
IngestAll {
226+
/// Force re-index all papers
227+
#[arg(long)]
228+
force: bool,
229+
#[arg(long)]
230+
json: bool,
231+
},
85232
}
86233

87234
#[derive(Subcommand)]

0 commit comments

Comments
 (0)