Compare commits

...
479 Commits
Author SHA1 Message Date
Hua.T e981d2d8fc Forward backend options during streaming speech generation (#1389) (#1390) 2026-10-11 17:23:05 -04:00
PerryLink 55fadb4c56 Reject a semicolon in a SQL query instead of silently cutting the statement (#1388) 2026-10-11 17:21:01 -04:00
Rızgar Ozan fe5be99bfa Handle ServiceTask responses without a Content-Type or body (#1387) 2026-10-11 17:17:06 -04:00
David Mezzetti 243aaa191d Merge pull request #1385 from kartsan03/sqlite-load-switch
Switch SQLite ANN connections when load() is given a new path
2026-10-11 17:13:58 -04:00
leeshengis 93a767f004 Preserve workflow and task configuration dictionaries (#1377) 2026-10-11 17:12:41 -04:00
davidmezzetti 62099b9a34 Cleanup open connection in test 2026-10-11 12:03:14 -04:00
David Mezzetti c786f1b5ec Replace continue statement in HTMLToMarkdown list handler (#1357) (#1386) 2026-10-11 11:02:08 -04:00
amengnew 738df97d5f Fall back to row index when Tabular IDs are NaN (#1366) 2026-10-11 10:37:51 -04:00
Raphael Malikian 4605ee001f Fix LogOdds.calibrate to compute the mean once instead of per score (#1365) 2026-10-10 08:06:37 -04:00
Rızgar Ozan 46516fa4e6 Replace continue statement in HTMLToMarkdown list handler (#1357) 2026-10-10 14:24:22 +03:00
kartsan03 fe1fbbc933 Switch SQLite ANN connections when load() is given a new path 2026-10-10 11:11:24 +00:00
Hua.T 084a1eca4d Fix audio trimming of partial detection windows (#1374) (#1375) 2026-10-10 06:35:44 -04:00
Muneeb Ullah ba9d52310a Fix infertopics ignoring topiced neighbors when untopiced ones outnumber them (#1373) 2026-10-10 06:33:12 -04:00
Jasper ca9563daac Use only the query argument of similar() clauses in terms and explain (#1367) 2026-10-09 10:29:46 -04:00
D41910 0e7202caee Honor an empty allow list in the bash agent tool (#1362) 2026-10-08 15:55:25 -04:00
David Mezzetti c1f1686889 Merge pull request #1361 from kartsan03/rdbms-graph-addattribute
Write RDBMS graph attribute changes to the database
2026-10-08 13:06:57 -04:00
kartsan03 04f5bf1998 Write RDBMS graph attribute changes to the database 2026-10-08 12:52:02 +00:00
Gaurav Chintakunta c8e7d813af Preserve ordered-list start values in HTMLToMarkdown (#1355) (#1356) 2026-10-08 07:05:07 -04:00
Yuilona edf61d1d4a Use each query's hybrid weights when batching similar clauses (#1359) 2026-10-07 16:21:36 -04:00
Raphael Malikian 7e92f5a7d7 Fix StorageTask listing failing on tagged storage inputs (#1348) 2026-10-07 14:15:17 -04:00
Raashish Aggarwal b2ff9bd85c Sort NULL values like SQLite when merging ordered results (#1353) 2026-10-07 13:09:08 -04:00
Raashish Aggarwal 9c718f7876 Merge aggregate columns written in uppercase across shards (#1352) 2026-10-07 09:00:39 -04:00
Moinuddin Shaik c486f4706e Return no results from Reranker when a search has no matches (#1350) 2026-10-07 09:00:03 -04:00
Lukas 341184ba46 Keep word spacing and drop empty link targets in HTMLToMarkdown (#1347) 2026-10-07 08:58:51 -04:00
Lukas 647d80f95e Replace HTML line breaks with newlines in HTMLToMarkdown (#1345) 2026-10-07 07:22:03 -04:00
Yash Raj Pandey 408c25d201 Explain DuckDB query errors that abort the transaction (#1341) 2026-10-07 06:34:30 -04:00
davidmezzetti b0f29a11d1 Bump Docker version 2026-10-06 10:18:15 -04:00
davidmezzetti 49a64943b8 Bump version 2026-10-06 10:18:02 -04:00
David Mezzetti af33f2e024 Merge pull request #1333 from HuaTNA/fix-tabular-falsy-idcolumn
Respect explicitly selected falsy ID column names in Tabular
2026-10-05 11:06:24 -04:00
davidmezzetti f908b5d88d Support trust_remote_code in associated AutoModels, closes #1342 2026-10-05 10:25:41 -04:00
David Mezzetti 2e8493dfca Merge pull request #1338 from serhiizghama/fix/duckdb-bind-parameter-order
Keep DuckDB bind values in query order when a parameter repeats
2026-10-05 08:53:15 -04:00
shabeeth2 d7e3e29ac3 docs: match task input tuple in explanation (#1337) 2026-10-05 06:22:06 -04:00
Mohammad Hijjawi 4e2efa2cbc Keep node id 0 in graph path search results (#1335) 2026-10-05 06:19:12 -04:00
Gaurav Chintakunta ffcbc0b815 Skip NULL aggregate values from shards with no matching rows (#1331) 2026-10-05 06:17:05 -04:00
tuanzirwar f14c26c4c7 Fix ordinary streaming output buffering with stripthink enabled (#1311) 2026-10-05 06:15:44 -04:00
serhiizghama 346bb9d282 Test a repeated bind parameter followed by another parameter 2026-10-05 11:12:23 +07:00
serhiizghama e3e0413747 Keep DuckDB bind values in query order when a parameter repeats 2026-10-05 10:47:53 +07:00
David Mezzetti 32655393e0 Merge pull request #1323 from Lesereingrape/fix/concat-merge-falsy-values-1003
Keep 0 and False in concat merge outputs
2026-10-04 11:08:45 -04:00
davidmezzetti 9118875980 Move coverage check to only run for Linux GitHub action 2026-10-04 09:45:08 -04:00
Manobhi Sriram d9b4476187 Decode bash tool output as UTF-8 instead of locale encoding, closes #1326 (#1327) 2026-10-04 09:32:30 -04:00
Grapette.L ff5aec468a Fix DuckDB bind parameters followed by a non-word character not being converted (#1325) 2026-10-04 09:01:16 -04:00
davidmezzetti 3446a4ef13 Fail if code coverage less than 100% 2026-10-04 08:57:07 -04:00
HuaTNA 84aa1c81c7 Fix Tabular handling of explicitly selected falsy ID columns (#1332) 2026-10-03 19:14:23 -04:00
Lesereingrape 6bc76132d0 Keep 0 and False in concat merge outputs 2026-10-03 11:34:59 +08:00
Morgan Carr 893d0424be Cache document token vectors in Reranker (#1321) 2026-10-02 14:32:17 -04:00
Edson 98c965cc3b Keep all rows for native vstack merges with list inputs (#1320) 2026-10-02 14:30:31 -04:00
Yash Raj Pandey 00622f2cf1 Parse true and false as boolean literals in SQL queries (#1316) 2026-10-02 14:28:51 -04:00
Yash Raj Pandey 55d52fda92 Keep graph categories aligned with topics after a delete (#1315) 2026-10-02 14:24:59 -04:00
Ni0ri 20c9b8e0be Add Zvec Sparse ANN (#1307) 2026-10-01 09:53:38 -04:00
Mohammad Hijjawi 3f33fb2918 Format nested HTML lists without duplicating items (#1286) 2026-10-01 06:48:14 -04:00
davidmezzetti 3c7a548923 Remove build script workaround, closes #1239 2026-09-30 13:03:03 -04:00
Pablo Miguel Argudo c78fbd976c Support append and delete in the RaBitQ ivf mode (#1304) 2026-09-30 12:44:19 -04:00
David Mezzetti 2d535ff215 Merge pull request #1303 from kartsan03/fix/ann-delete-numpy-ids
Delete the requested rows when ANN ids are a NumPy array
2026-09-30 12:40:40 -04:00
kartsan03 6765330f4a Delete the requested rows when ANN ids are a NumPy array 2026-09-30 15:26:24 +00:00
davidmezzetti 1d5041b6e7 Fix test merge error 2026-09-30 11:07:02 -04:00
davidmezzetti d467878064 Refactor ANN tests, closes #1305 2026-09-30 11:04:07 -04:00
davidmezzetti 3bc07b3f09 Remove unnecessary note 2026-09-30 11:03:37 -04:00
Hua.T 8ef454d0bf Preserve keyword document ID types across save/load (#1274) (#1275) 2026-09-30 10:57:41 -04:00
Jin 47d3e65756 Fix training with pandas DataFrames, closes #1265 (#1266) 2026-09-30 10:55:44 -04:00
LimbC-C 81f908874b Open lazy SQLite connections before saving indexes (#1290) 2026-09-30 09:30:14 -04:00
David Mezzetti bed91a0b9f Merge pull request #1301 from Bdysj/openai-compliant-chat-completions
Return OpenAI-compliant index, created and finish_reason from chat completions
2026-09-30 09:05:50 -04:00
David Mezzetti 7df50abb61 Merge pull request #1282 from LimbC-C/fix/sqlite-binary-scores
Normalize SQLite binary ANN similarity scores
2026-09-30 09:03:45 -04:00
David Mezzetti 80b8ceff4a Merge pull request #1279 from LimbC-C/fix/array-negative-delete-ids
Ignore negative deletion IDs in NumPy and Torch ANN indexes
2026-09-30 08:59:03 -04:00
David Mezzetti de9e09e9ae Merge pull request #1299 from LimbC-C/fix/tabular-numeric-types
Preserve integer document IDs and numeric column types in Tabular
2026-09-30 08:19:59 -04:00
Morgan Carr 69ede9ec3e Fall back to root tokenizers for ONNX and LiteRT Hub subdirectory models (#1277) 2026-09-30 07:41:03 -04:00
Pablo Miguel Argudo f8689ed903 Store only the quantized index in the RaBitQ backend (#1297) 2026-09-30 07:05:37 -04:00
bob 0abf3763b4 Return OpenAI-compliant index, created and finish_reason from chat completions, closes #1300 2026-09-30 14:51:02 +08:00
LimbC-C 11b2cfe298 Preserve numeric column types in Tabular rows (#1298) 2026-09-30 09:45:58 +08:00
LimbC-C d0cc2bed9c Simplify regression test in existing TestDense class (#1282) 2026-09-30 09:39:23 +08:00
LimbC-C a5ea35d7a7 Simplify regression test in existing TestDense class (#1279) 2026-09-30 09:39:18 +08:00
Yash Raj Pandey 6a15ed8490 Include offset rows in similar() candidates (#1291) 2026-09-29 17:25:52 -04:00
David Mezzetti 76147369fb Merge pull request #1295 from Bdysj/pad-summary-batches
Pad batched inputs in the Summary pipeline
2026-09-29 15:27:58 -04:00
bob 2e89af0845 Pad batched inputs in the Summary pipeline, closes #1294 2026-09-30 01:19:38 +08:00
davidmezzetti d9d6a1cbb1 Update pooling mode check 2026-09-29 11:05:04 -04:00
davidmezzetti f87574de4c Support pooling_mode with models trained with recent Sentence Transformers, closes #1292 2026-09-29 10:23:16 -04:00
Mohammad Hijjawi e313248ff2 Keep uppercase tokens in alphanumeric tokenization with lowercase=False (#1287) 2026-09-29 09:03:03 -04:00
davidmezzetti 5cba72c88a Update pylintrc file and remove warning overrides for new limits 2026-09-29 07:11:03 -04:00
davidmezzetti 45d334f4ce Remove unnecessary new test file and consolidate test into existing class 2026-09-29 07:10:09 -04:00
Jin 95d4c1c881 Label QA spans without the answer with the CLS token, closes #1263 (#1264) 2026-09-29 06:36:47 -04:00
LimbC-C ef28da8735 Reject iterator inputs for multi-action tasks without buffering (#1272) 2026-09-28 10:40:36 -04:00
LimbC-C f1304d8403 Normalize SQLite binary ANN similarity scores (#1281) 2026-09-28 09:43:12 +08:00
davidmezzetti 97ee7e073a Bump job timeout given that the Windows build frequently times out 2026-09-27 05:51:01 -04:00
LimbC-C 1d3f8e9ebf Ignore negative NumPy and Torch ANN deletion IDs (#1278) 2026-09-26 09:43:32 +08:00
davidmezzetti f3ceece76a Add test for missing SQLite ANN coverage 2026-09-25 09:18:02 -04:00
Pablo Miguel Argudo 6737ee4e01 Add RaBitQ as an ANN backend (#1251) 2026-09-25 08:39:39 -04:00
davidmezzetti e30e8edbcc Add test for missing SQLite ANN coverage 2026-09-25 08:00:21 -04:00
davidmezzetti 483dbd3b3b Update test 2026-09-24 21:49:06 -04:00
davidmezzetti c09a6f24f1 Update test 2026-09-24 21:46:09 -04:00
davidmezzetti 6e7f0d260e Update test 2026-09-24 21:12:15 -04:00
davidmezzetti 793ecc8dc2 Require Python 3.11, closes #1273 2026-09-24 16:58:32 -04:00
David Mezzetti 37500887ae Merge pull request #1268 from HuaTNA/fix-rag-input-mutation
Preserve reusable RagTask inputs
2026-09-24 16:35:58 -04:00
David Mezzetti 4e2eb242b6 Support explicit LIKE escapes in wildcard term queries (#1259) 2026-09-24 16:34:16 -04:00
Jin 83c75ea28a Pack rows into chunks up to and including maxlength, closes #1269 (#1270) 2026-09-24 16:31:37 -04:00
LimbC-C f47d389735 Preserve wildcard compatibility and support explicit LIKE escapes 2026-09-24 23:54:33 +08:00
HuaTNA 4bb2141954 Preserve reusable RagTask inputs (#1267) 2026-09-23 23:48:46 -04:00
David Mezzetti 5d8c999ae0 Merge pull request #1262 from HuaTNA/fix-template-falsy-rules
Preserve falsy TemplateTask rule matches
2026-09-23 16:36:47 -04:00
HuaTNA 48a34e21c3 Preserve falsy TemplateTask rule matches (#1261) 2026-09-23 13:22:36 -04:00
davidmezzetti 262b03027e Code cleanup 2026-09-23 08:01:47 -04:00
刘冠杰 36c375b86e Honor the nfeatures setting in IVFSparse (#1250) 2026-09-23 07:53:18 -04:00
David Mezzetti b715812e68 Merge pull request #1248 from LimbC-C/fix/deleted-keyword-results
Keep deleted keyword results excluded after common-term scoring
2026-09-23 07:51:27 -04:00
hylin dcdded892d Keep community nodes that match none of the topic terms (#1243) 2026-09-23 07:40:25 -04:00
LimbC-C e7894cdb00 Escape literal SQL wildcard characters in term expansion (#1258) 2026-09-23 13:06:27 +08:00
LimbC-C 9f9b32e070 Clear deleted scores at the end of common-term merging 2026-09-23 13:00:30 +08:00
David Mezzetti 00167b9f08 Merge pull request #1256 from dingpuyu/codex/fix-retrieve-local-filenames
Preserve local filenames in RetrieveTask
2026-09-22 14:00:19 -04:00
dingpuyu 3c07766199 Preserve local filenames in RetrieveTask 2026-09-23 00:36:08 +08:00
Amir Fathi 7cb6bd09db Fix DuckDB.formatargs dropping repeated named bind parameters (#1253) 2026-09-22 12:22:45 -04:00
Caner Olcay 4b7d70e9e8 Keep SQLite ANN data when saving a modified index to a new path (#1249) 2026-09-22 06:55:29 -04:00
David Mezzetti 2ed4e46ebf Merge pull request #1245 from serhiizghama/fix/cluster-forward-weights-and-encode-parameters
fix(api): forward zero weights and url-encode parameters in Cluster search
2026-09-22 06:54:14 -04:00
LimbC-C 47d5f56768 Keep deleted keyword results excluded after common-term scoring (#1247) 2026-09-19 09:46:09 +08:00
serhiizghama d5db643540 test: cover cluster search argument forwarding 2026-09-18 09:15:19 +07:00
serhiizghama 9f7b4ddd42 fix(api): forward zero weights and url-encode parameters in Cluster search 2026-09-18 08:56:12 +07:00
Morgan Carr 19ff237c37 Set the HNSW delete counter when loading an index (#1242) 2026-09-15 14:21:46 -04:00
Morgan Carr ad77514b32 Store IVFSparse deletes as int (#1241) 2026-09-15 14:20:36 -04:00
davidmezzetti 144a957d42 Test latest version of LiteLLM #1193 2026-09-15 07:51:21 -04:00
Serhii Zghama 2e8a3d7892 fix(database): don't drop rows when sorting or grouping by a JSON field (#1238) 2026-09-14 10:19:52 -04:00
Amir Fathi 72f9ca7605 Fix Cluster combining avg() as an unweighted mean of shard averages (#1237) 2026-09-14 10:18:52 -04:00
Amir Fathi ebe13ae304 Fix quantize: false silently enabling Q8_0 quantization in the GGML backend (#1236) 2026-09-11 08:25:40 -04:00
Serhii Zghama 5d0e995f7f fix(ann): honor quantize: false in the Faiss and SQLite backends (#1234) 2026-09-11 08:22:49 -04:00
davidmezzetti 7965a7f42e Build script workaround #1239 2026-09-10 08:52:56 -04:00
Amir Fathi 2bae6e4d43 Fix Transform.stream() yielding a None text value into the encoder (#1231) 2026-09-08 09:44:53 -04:00
Morgan Carr 767272f2d5 Key the vectors model cache by configuration (#1223) 2026-09-04 16:47:49 -04:00
Morgan Carr 21460347dd Fix ANN delete on quantized Torch stores and tiny GGML indexes (#1228) 2026-09-04 09:54:42 -04:00
Morgan Carr f3945f9120 Select the top documents in LateEncoder by the document axis (#1227) 2026-09-04 09:52:40 -04:00
Paco Cartones 3a7b597d78 fix(workflow): add request timeout to ServiceTask (#1226) 2026-09-04 09:00:49 -04:00
Morgan Carr 20e2dc41e1 Save empty keyword and content indexes without errors (#1224) 2026-09-04 08:21:11 -04:00
Morgan Carr eafe574d92 Keep the archive working directory alive when saving a loaded index (#1222) 2026-09-04 08:19:36 -04:00
Morgan Carr 7e98746d78 Delete every index entry for an id in Terms (#1219) 2026-09-04 08:11:47 -04:00
Morgan Carr 6ebfbbb716 Improve late pooling configuration errors (#1217) 2026-09-03 13:52:46 -04:00
David Mezzetti 8fef6ac454 Merge pull request #1220 from serhiizghama/fix/sparse-vectors-remove-spool-file
fix(vectors): remove the sparse spool file when checkpointing is disabled
2026-09-03 13:05:09 -04:00
davidmezzetti 0eafc0580f Update vectors package to standardize fallback logic, closes #1221 2026-09-03 11:53:55 -04:00
serhiizghama 5ade7881c8 test: cover spool file cleanup for sparse vectors 2026-09-03 20:19:31 +07:00
serhiizghama 948dc42d19 fix(vectors): remove the sparse spool file when checkpointing is disabled 2026-09-03 19:58:47 +07:00
David Mezzetti 2e8af221f4 Keep count() accurate after repeated deletes in GGML and IVFSparse (#1218)
Deleting an id that is already marked deleted no longer decrements count()
again in the GGML and IVFSparse ANN backends. IVFSparse also ignores ids that
were never indexed, matching the dense backends.
2026-09-02 18:18:11 -04:00
Morgan Carr 396b3b8065 Resolve label filters by label id (#1216) 2026-09-02 17:15:45 -04:00
Morgan Carr 80420ee10a Ignore padding rows in LateEncoder scores (#1215) 2026-09-02 17:14:39 -04:00
David Mezzetti 1d45e88569 Merge pull request #1214 from morgan-coded/fix/milvus-load-collection
Load the Milvus collection when opening a saved index
2026-09-02 15:25:19 -04:00
Joe Bergin 007d61077a Add ONNX vectors backend (#1212) 2026-09-02 12:19:57 -04:00
David Mezzetti 84fcd81039 fix(api): parse the graph query parameter as a bool (#1213) 2026-09-02 11:18:16 -04:00
morgan-coded cfe2227f30 Load the Milvus collection when opening a saved index
With milvus-lite 3.2.1, a reopened collection that has an index starts in the
released state, so search failed after save and after load while count worked.
2026-09-02 03:20:29 -05:00
morgan-coded 82b5320da3 Keep count() accurate after repeated deletes in GGML and IVFSparse
Deleting an id that is already marked deleted no longer decrements count()
again in the GGML and IVFSparse ANN backends. IVFSparse also ignores ids that
were never indexed, matching the dense backends.
2026-09-02 02:53:52 -05:00
serhiizghama 18b93be702 test: cover graph parameter parsing in the search API 2026-09-02 11:06:18 +07:00
serhiizghama 027c07deb9 fix(api): parse the graph query parameter as a bool 2026-09-02 10:53:23 +07:00
Paco Cartones 876cd07cf7 Fix bash tool hanging on commands that read stdin (#1210) 2026-09-01 20:04:29 -04:00
davidmezzetti 546e7777f1 Bump version 2026-08-27 12:48:36 -04:00
Yash Raj Pandey 27542ca64b Index zero and False values in the tabular pipeline (#1207) 2026-08-27 07:39:36 -04:00
David Mezzetti f0ee7d2b2d Merge pull request #1206 from morgan-coded/fix/nprobe-clamp
Clamp default Faiss nprobe to nlist
2026-08-26 08:23:31 -04:00
morgan-coded bba7fd589e Clamp default nprobe to nlist 2026-08-25 17:18:46 -05:00
David Mezzetti 6349ca2eac Merge pull request #1205 from Evhye38496/fix-safetensors-import
Fix safetensors numpy/torch submodule imports
2026-08-25 07:58:29 -04:00
Evhye38496 ba1693480e Fix safetensors numpy/torch submodule imports #1204 2026-08-25 12:57:51 +08:00
Sainikhil Juluri e90c67ef06 fix(scoring): keep count() accurate when an id is deleted more than once (#1202) 2026-08-24 21:55:11 -04:00
Amir Fathi 57991cb164 Fix WordVectors.index() silently dropping the checkpoint argument (#1198) 2026-08-24 20:38:28 -04:00
David Mezzetti c2b264d297 Merge pull request #1201 from serhiizghama/fix/numpy-hamming-search-skip-deleted-rows
fix(ann): exclude deleted rows from quantized numpy search results
2026-08-24 15:57:28 -04:00
serhiizghama 406e417be0 test(ann): cover deleted-row exclusion for quantized numpy backend 2026-08-24 17:18:26 +07:00
serhiizghama 954b17af4d fix(ann): exclude deleted rows from quantized numpy search results 2026-08-24 17:05:58 +07:00
davidmezzetti 2a139449dc Re-add LiteLLM workaround #1193 2026-08-23 19:08:33 -04:00
davidmezzetti a10667a1c2 Test new version of LiteLLM #1193 2026-08-22 22:10:01 -04:00
davidmezzetti 34e6efcdd6 Update docs 2026-08-22 22:09:34 -04:00
David Mezzetti 9b7a96b4d1 Resolve LEMUR and MUVERA settings (#1196) 2026-08-22 21:49:14 -04:00
morgan-coded b94f770301 Resolve LEMUR and MUVERA settings 2026-08-22 16:19:06 -05:00
Arnaud Thery adbcccda46 Merge pull request #1195 from St4r4x/fix/crossencoder-multiclass-labels
fix: rank CrossEncoder by a fixed label, not top-1 position
2026-08-22 14:15:21 -04:00
David Mezzetti 20f818f72c Merge pull request #1194 from morgan-coded/fix/1190-lemur-collection-centering
Fix LEMUR collection centering
2026-08-19 06:37:51 -04:00
morgan-coded ee0416e87b Add centermean validation test 2026-08-18 20:22:07 -05:00
morgan-coded 00ec81a10e Fix LEMUR collection centering 2026-08-18 10:54:10 -05:00
davidmezzetti 059ecec2ee Build script workaround #1193 2026-08-18 09:58:35 -04:00
davidmezzetti 21c2c38b98 Build script workaround #1193 2026-08-18 09:56:00 -04:00
davidmezzetti 47c05994bf Cleanup of Pooling PRs 2026-08-18 09:53:29 -04:00
Kole Harvey 8f3735101b Resolve pooling method from a config missing pooling_mode_mean_tokens 2026-08-18 09:14:20 -04:00
Aryan Pardeshi 438ade31b6 Add max pooling 2026-08-18 09:12:32 -04:00
davidmezzetti 3ea197468d Code cleanup 2026-08-12 09:35:13 -04:00
LHMQ878 99ebbdfea2 fix: create default agent tools on first use (#1175) 2026-08-12 07:30:37 -04:00
David Mezzetti 5570dbc7b6 Merge pull request #1183 from FU-max-boop/fix/openai-latest-message
Fix OpenAI chat message selection
2026-08-12 07:29:43 -04:00
FU-max-boop 01b456900a Fix OpenAI chat message selection 2026-08-11 13:26:29 +08:00
davidmezzetti a0857e980a Update output validation #1181 2026-08-10 22:02:42 -04:00
davidmezzetti 84be3476d8 Add safeopen validation to retrieve task output, closes #1181 2026-08-10 19:29:05 -04:00
davidmezzetti f35d932979 Refactor late encoding logic to cleanup logic paths, closes #1180 2026-08-10 18:47:58 -04:00
Tai An a1c9b94d00 fix(muvera): consume true token rows instead of batch-padded ones (#1177) 2026-08-10 13:24:21 -04:00
Aryan Pardeshi 11ebacdb23 Convert MUVERA algorithm from NumPy to Torch (#1178) 2026-08-10 13:20:58 -04:00
davidmezzetti 5986fa6082 Test Docling build #1176 2026-08-10 10:57:48 -04:00
davidmezzetti 893a333887 Test Docling build fix #1176 2026-08-10 10:15:16 -04:00
David Mezzetti e54255f4e4 Merge pull request #1179 from latent-9/fix-spelling-typos
Fix spelling typos in documentation and docstrings
2026-08-10 09:08:58 -04:00
latent-9 f89835bc77 Fix spelling typos in documentation and docstrings 2026-08-10 04:40:37 +12:00
davidmezzetti ea531b3420 Build script workaround #1176 2026-08-04 12:24:05 -04:00
davidmezzetti 756917f14b Build script workaround #1176 2026-08-04 12:20:17 -04:00
davidmezzetti b1f4845284 Build script workaround #1176 2026-08-04 12:13:14 -04:00
David Mezzetti d2b1d3634f Merge pull request #1172 from morgan-coded/feat/lemur-trainer
Consolidate LEMUR training in the trainer pipeline
2026-08-04 10:12:05 -04:00
morgan-coded 193facd144 test: cover the tqdm library stub 2026-08-03 20:50:04 -05:00
morgan-coded 436662e32b feat: promote tqdm to a default library dependency 2026-08-03 14:32:12 -05:00
morgan-coded 54644a0526 chore: add lint pragma and docstring for relocated trainer tests 2026-08-02 18:11:54 -05:00
morgan-coded 817a2b142a fix: keep minimal installs importable 2026-08-02 17:04:51 -05:00
morgan-coded 987cff001f feat: consolidate LEMUR training in trainer
Move fitting, data preparation, model setup, epoch selection and progress feedback into LemurTrainer while keeping artifact loading and encoding in the pooler.
2026-08-02 16:55:32 -05:00
David Mezzetti 8383e6ce8d Merge pull request #1171 from morgan-coded/chore/lemur-style
Align LEMUR names with txtai style
2026-08-02 16:49:32 -04:00
morgan-coded 0be1231d8d chore: align LEMUR names with txtai style 2026-08-02 14:21:38 -05:00
David Mezzetti 79e277fb7d Merge pull request #1168 from morgan-coded/feat/center
Add configurable mean centering to late pooling
2026-08-02 13:36:13 -04:00
morgan-coded f4472312ba test: use portable tolerances for cross-batch comparisons 2026-08-02 06:47:56 -05:00
morgan-coded 90f7cc2078 test: isolate uncentered LEMUR coverage 2026-08-01 22:40:57 -05:00
morgan-coded ce11b08ab1 fix: address centering review feedback 2026-08-01 22:13:38 -05:00
morgan-coded 75b4ce5c7f feat: add configurable late pooling centering 2026-08-01 18:37:42 -05:00
David Mezzetti 2ef401bb78 Merge pull request #1164 from morgan-coded/feat/lemur
Add LEMUR fixed dimensional encoding
2026-08-01 17:35:07 -04:00
davidmezzetti 8c43c70687 Bump version 2026-07-30 17:43:11 -04:00
David Mezzetti 48e22b593c Merge pull request #1163 from AmirF194/fix/scoring-delete-unindexed-id
Fix Scoring.delete() crashing on ids that were never indexed
2026-07-30 14:48:11 -04:00
davidmezzetti 3beea7f4bf Add safeopen option for retrieve task, closes #1166 2026-07-30 14:36:52 -04:00
morgan-coded 626cc8fbe0 Add LEMUR validation coverage 2026-07-30 12:03:07 -05:00
davidmezzetti 21b9049c86 Allow disabling API routes, closes #1165 2026-07-30 12:49:38 -04:00
davidmezzetti abf504f70e Update configuration section for workflow tasks 2026-07-30 12:44:34 -04:00
davidmezzetti d9e9a9e684 Pin mcp < 2.0 until upstream issues resolved #1161 2026-07-30 12:43:47 -04:00
Amir Fathi bd199158b6 Fix Scoring.delete() crashing on ids that were never indexed 2026-07-30 12:35:35 +00:00
morgan-coded 390cc08b11 Document LEMUR training and configuration 2026-07-30 07:02:16 -05:00
morgan-coded feac4c8306 Test LEMUR pooling and training 2026-07-30 07:02:16 -05:00
morgan-coded d7f974b3d7 Add LEMUR training pipeline 2026-07-30 07:02:16 -05:00
morgan-coded d8fa848f73 Integrate LEMUR late pooling 2026-07-30 07:02:16 -05:00
morgan-coded bbd23bb12c Add LEMUR fixed dimensional encoding 2026-07-30 07:02:16 -05:00
David Mezzetti 8362110c64 Merge pull request #1162 from morgan-coded/fix/milvus-lite-version-floor
Set minimum milvus-lite version
2026-07-29 07:51:07 -04:00
morgan-coded 83e1835b6d Set minimum milvus-lite version 2026-07-28 20:33:31 -05:00
davidmezzetti cf2368269f Build script workaround #1161 2026-07-28 11:14:49 -04:00
davidmezzetti a910ddbbea Add Milvus tests on Windows #1156 2026-07-28 10:37:38 -04:00
davidmezzetti 7b49504dca Update test 2026-07-23 11:54:09 -04:00
davidmezzetti 86af7ec344 Test updates 2026-07-23 10:10:28 -04:00
Amir Fathi 50ca7b2fde Fix HNSW search RuntimeError when limit exceeds indexed element count (#1159) 2026-07-23 08:42:33 -04:00
David Mezzetti 7c8d001492 Merge pull request #1151 from link89/fix-openapi-auth-ui
fix Swagger UI auth issue
2026-07-23 08:30:09 -04:00
weihong.xu dea0a65fd1 implement auth with HTTPBearer for correct openapi spec 2026-07-23 09:56:26 +08:00
davidmezzetti a1224c06f1 Doc and test update 2026-07-22 09:43:36 -04:00
davidmezzetti 162b65d3d9 Remove file 2026-07-22 07:38:17 -04:00
davidmezzetti 363f8ca7cf Ensure explain / batchexplain don't return numpy values, closes #1157 2026-07-22 06:53:07 -04:00
davidmezzetti 1d084941f4 Code cleanup 2026-07-22 06:37:42 -04:00
Andrew Chen 597ba8133d Fix msgpack Accept header crashing streaming API endpoints (#1144) 2026-07-22 06:14:07 -04:00
Andrew Chen 6bbb25872a Fix Terms KeyError on a query with no similar() clause (#1142) 2026-07-22 06:13:33 -04:00
davidmezzetti f22bf5bbb5 Update test 2026-07-21 14:29:12 -04:00
davidmezzetti 83871c6fe3 Add documentation for Milvus ANN 2026-07-21 13:24:23 -04:00
davidmezzetti 2c6ec162d0 Skip Milvus tests on Windows #1156 2026-07-21 13:10:56 -04:00
davidmezzetti d59c88424d Code cleanup 2026-07-21 12:59:57 -04:00
David Mezzetti 95c7b8df1e Merge pull request #1149 from morgan-coded/milvus-lite-backend
Add milvus-lite embedded dense ANN backend
2026-07-21 12:41:05 -04:00
Loi Nguyen 2389b5946c Fix Segmentation dropping paragraph/section splits on CRLF line endings (#1152) 2026-07-21 12:29:12 -04:00
Andrew Chen b246b642c7 Fix LIMIT bind-parameter crashing content SQL search (#1148) 2026-07-21 12:26:15 -04:00
Andrew Chen 46467a3453 Raise SQLError on empty select expressions and a dangling AS (#1147) 2026-07-21 12:24:12 -04:00
davidmezzetti fcfd340ff1 Cleanup tests 2026-07-21 12:18:35 -04:00
Andrew Chen 77965f44dd Fix Cluster.shard TypeError on tuple documents and empty-string ids (#1146) 2026-07-21 11:57:57 -04:00
Andrew Chen 7435297bac Fix console printing a traceback for a query with no results (#1145) 2026-07-21 11:51:11 -04:00
Andrew Chen 3bb34eae2e Fix Terms.search AttributeError on an empty terms index (#1143) 2026-07-21 11:40:43 -04:00
Andrew Chen 79a28641b2 Fix TemplateTask.match KeyError when a rule key is missing from element (#1141) 2026-07-21 11:25:58 -04:00
Andrew Chen 7c77c134e2 Fix HTMLToMarkdown crash on a meta description tag with no content attribute (#1140) 2026-07-21 11:23:29 -04:00
Andrew Chen d6f696d795 Fix Aggregate IndexError on a SQL query that matched nothing across shards (#1139) 2026-07-21 11:19:28 -04:00
davidmezzetti d8ae6776f8 Only resolve transform functions when env variable set, closes #1155 2026-07-21 11:07:58 -04:00
davidmezzetti e18e3d1245 Reduce verbose comment 2026-07-21 10:40:32 -04:00
Andrew Chen ee0d1a0214 fix: Task.filteredrun crashes/corrupts output for single-action tasks with merge disabled (#1138) 2026-07-21 10:16:26 -04:00
davidmezzetti 5ddedf07cd Fix test order 2026-07-21 10:13:44 -04:00
David Mezzetti 590c71f593 Merge pull request #1154 from winklemad/fix/ivfsparse-sort-order
Fix IVFSparse returning unsorted sparse ANN search results
2026-07-21 10:11:17 -04:00
winklemad c33188a0f8 Fix IVFSparse returning unsorted sparse ANN search results
IVFSparse.topn selects the top n with np.argpartition but never sorts them, so
search results came back in arbitrary order instead of ranked by score descending
like every other backend (numpy argsort, hnsw/faiss, sqlite ORDER BY, pgvector).
Sort each row by score after the partition. The LateEncoder pipeline used the same
argpartition-without-sort pattern in its ranking path and is fixed the same way.
2026-07-21 18:46:36 +05:30
davidmezzetti 638a2e12b1 Validate resolver target classes, closes #1153 2026-07-21 09:13:43 -04:00
morgan-coded 03da5c96fb Rename milvuslite backend to milvus per maintainer request 2026-07-17 08:08:57 -05:00
morgan-coded 99086302ce Add milvus-lite as a dense ANN backend 2026-07-16 11:15:18 -05:00
davidmezzetti 2f11f93743 Code cleanup 2026-07-14 15:27:55 -04:00
davidmezzetti 783d9cf680 Cleanup docs 2026-07-14 15:15:21 -04:00
David Mezzetti 281babeff7 Merge pull request #1137 from chuenchen309/fix/graph-filter-unknown-node-id
Fix Graph.filter() crash on ids that don't exist in the graph
2026-07-14 14:19:06 -04:00
David Mezzetti a71732198a Merge branch 'master' into fix/graph-filter-unknown-node-id 2026-07-14 14:18:14 -04:00
Morgan Carr 14cbe51e04 Add zvec as a dense ANN backend (#1130) 2026-07-14 13:41:35 -04:00
davidmezzetti 5d15f7fa66 Revert #1136 as it's confirmed to not be necessary 2026-07-14 13:40:09 -04:00
davidmezzetti ac2dc6a30b Code cleanup 2026-07-14 13:36:50 -04:00
chuenchen309andClaude Opus 4.8 7791174c1b Fix Graph.filter() crash on ids that don't exist in the graph
Graph.filter() unpacked self.node(node) with ** into addnode() for every
input id, but self.node() returns None for an id not present in the
graph. **None raises TypeError instead of the filter simply skipping an
id it doesn't recognize - the docstring says nodes are "nodes to select",
with no stated precondition that every id must already exist.

Skip ids where self.node() returns None instead of crashing.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-15 00:09:32 +08:00
David Mezzetti b21ba7065e Merge pull request #1136 from chuenchen309/fix/graph-insert-none-text-index-desync
Fix Graph.insert() node id desync when a document's text/object field is None
2026-07-14 11:11:06 -04:00
chuenchen309andClaude Opus 4.8 10a6b23304 Fix Graph.insert() node id desync when a document's text/object field is None
Graph.insert() decided whether a document consumed an indexid slot based
on whether the resolved text/object value was not None. But the actual
vector index offset, computed by Transform.stream() (embeddings/index/
transform.py), increments based on key presence (`self.text in
document[1]`), regardless of the value. A document like {"text": None}
consumes a real vector index slot but was skipped by Graph.insert()
without incrementing its own index counter, so every subsequent document
in the batch got assigned to the wrong graph node id - a silent,
permanent misattribution of node ids to the wrong document data.

Track slot consumption with the same key-presence criterion Transform.
stream() uses (hasfield), separately from whether a node actually gets
created for that slot (still gated on the resolved value being non-None,
so no node is created for a genuinely empty document - but the index
still advances, leaving a gap instead of shifting every later id).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-14 22:55:12 +08:00
David Mezzetti 576f0ddcd7 Merge pull request #1135 from chuenchen309/fix/filetask-urltask-non-string-crash
Fix FileTask/UrlTask crash on non-string elements
2026-07-14 10:36:26 -04:00
chuenchen309andClaude Opus 4.8 9b8a606a16 Fix FileTask/UrlTask crash on non-string elements
Task.accept() is deliberately written to tolerate arbitrary element types
(including None) so heterogeneous batches can flow through a multi-task
workflow, letting a task pass through elements it doesn't recognize rather
than crashing. UrlTask.accept and FileTask.accept override this but called
element.lower()/re.sub(..., element) unconditionally, assuming element was
already a string:

- UrlTask.accept: super().accept(element) short-circuits True whenever no
  select filter is configured, then element.lower() raises AttributeError
  on any non-string element (including None).
- FileTask.accept: re.sub(FileTask.FILE, "", element) ran before the
  isinstance(element, str) check further down, so that check was dead code
  for the exact case it looked like it guarded against, and raised
  TypeError on any non-string element.

Both now check isinstance(element, str) before doing string operations, so
non-string/None elements pass through unchanged instead of crashing.
ImageTask inherits FileTask.accept and needed no change - it's protected
by the same fix via short-circuit evaluation.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-14 21:54:43 +08:00
davidmezzetti 01344b021c Test Python with build script #1134 2026-07-14 09:33:15 -04:00
davidmezzetti dd00608b9a Test Python with build script #1134 2026-07-14 09:28:05 -04:00
davidmezzetti 702e0b880f Test Python with build script #1134 2026-07-14 09:25:48 -04:00
davidmezzetti 14ac0e4cc5 Test Python 3.11 with build script #1134 2026-07-14 09:08:13 -04:00
davidmezzetti 1f28e5401d Test Python 3.11 with build script #1134 2026-07-14 08:48:00 -04:00
davidmezzetti a84f0a388c Fix test 2026-07-13 19:47:15 -04:00
davidmezzetti 510f9c18ed Update build script 2026-07-13 17:55:21 -04:00
davidmezzetti ae67f63359 Update build script 2026-07-13 17:39:07 -04:00
davidmezzetti 0e16a22051 Update build script 2026-07-13 17:10:17 -04:00
davidmezzetti bfd0aa7ff4 Update build script 2026-07-13 17:06:29 -04:00
davidmezzetti ba2ea2db4e Update build script 2026-07-13 16:57:19 -04:00
davidmezzetti 1daac761aa Update build script 2026-07-13 16:55:07 -04:00
davidmezzetti e9e65393a0 Update build script 2026-07-13 16:52:26 -04:00
davidmezzetti 24ca4e36ca Update build script 2026-07-13 16:32:59 -04:00
davidmezzetti 8208780b6a Update build script 2026-07-13 16:30:29 -04:00
davidmezzetti c3735dd5d4 Add tokenbatch size to HFTrainer pipeline, closes #1133 2026-07-13 16:15:02 -04:00
davidmezzetti 6544d123f6 Update test to work with latest version of pgvector 2026-07-13 16:08:53 -04:00
davidmezzetti aa0a8cfc32 Cleanup code from #1125 2026-07-02 10:37:57 -04:00
David Mezzetti fc6f93828b Merge pull request #1125 from Sanjays2402/fix/unterminated-sql-clause
Raise SQLError on unterminated bracket, function and similar clauses
2026-07-02 09:41:17 -04:00
Sanjay Santhanam 796c5bb0a8 Raise SQLError on unterminated bracket, function and similar clauses
The token consumer loops in Expression.bracket(), Expression.function() and
Expression.similar() read the next token with next(iterator, (None, None)) but
never checked for the end-of-stream sentinel. When a clause was left
unterminated (e.g. "select [a from txtai", "select func(a from txtai" or
"select * from txtai where similar('abc'"), the iterator was exhausted and the
code indexed tokens[None], raising a cryptic

    TypeError: list indices must be integers or slices, not NoneType

instead of the SQLError that the database layer documents and callers catch for
invalid SQL. The parse step runs before the query is handed to the database, so
this TypeError escaped the SQLError wrapping in Database.execute().

Add Expression.advance(), a small helper that wraps next() and raises SQLError
when the token stream is exhausted mid-clause, and route the three delimited
consumer loops through it. Auto-closing the clause instead was rejected because
it would silently reinterpret malformed input (e.g. "select [a" would become the
valid column "a"), masking the user error. This mirrors the existing None-guard
convention already used in Expression.compound().

Behavior on valid queries is unchanged (advance() only diverges from the old
code path when the iterator is empty). Adds testUnterminated covering
unterminated bracket, function and similar clauses.
2026-07-01 23:11:21 -07:00
davidmezzetti 7613acd6e5 Bump version 2026-07-01 15:24:55 -04:00
davidmezzetti 9db11953c5 Bump Torch version 2026-07-01 15:24:49 -04:00
davidmezzetti 2ecf4412fc Update build script 2026-07-01 10:32:49 -04:00
davidmezzetti 13b1a0f986 Update commonprefix to commonpath, closes #1120 2026-06-22 12:58:57 -04:00
davidmezzetti 89d5207b6e Limit tabular pipeline to local CSV files, closes #1119 2026-06-22 12:55:31 -04:00
davidmezzetti 21e6ab8e6a Add missing dependency #1118 2026-06-19 11:22:36 -04:00
davidmezzetti ae898e6905 Add text extraction with LiteParse, closes #1118 2026-06-19 10:51:58 -04:00
davidmezzetti 7aee5f91af Support multiple Dense layers for Late Interaction Pooling, closes #1117 2026-06-18 13:28:01 -04:00
davidmezzetti 7844e2c597 Fix how custom encoding is added to routers, closes #1115 2026-06-16 10:40:31 -04:00
davidmezzetti f9bfc2cb0d Update test 2026-06-16 10:39:37 -04:00
David Mezzetti 535edaf3ad Merge pull request #1114 from JSap0914/fix/ngram-tokenizer-lowercase
fix(tokenizer): respect lowercase=False in ngramtokenize
2026-06-16 07:20:07 -04:00
JSap0914 f507c442fd fix(tokenizer): respect lowercase=False in ngramtokenize
ngramtokenize called text.lower() unconditionally, which silently
overrode the lowercase=False setting. __call__ already lowercases text
before delegating to ngramtokenize when self.lowercase is True, so the
extra .lower() inside ngramtokenize is both redundant for the default
case and incorrect when lowercase=False.

Remove the redundant .lower() call and add a regression test.
2026-06-16 18:51:28 +09:00
davidmezzetti 73e2f6ee51 Remove find from the default list of bash tools, closes #1113 2026-06-11 12:09:45 -04:00
davidmezzetti bc8847edb0 Set minimum transformers version 2026-06-11 11:30:50 -04:00
davidmezzetti d69b72492d Test Transformers required version 2026-06-11 09:59:24 -04:00
davidmezzetti e0ae1450b4 Use gliner fork to relax transformers version caps, closes #1112 2026-06-11 09:08:05 -04:00
davidmezzetti 24c20cc0ff Revert noisy logging workaround, closes #1106 2026-06-11 09:06:59 -04:00
davidmezzetti 5f233d4a74 Update test 2026-06-09 17:16:41 -04:00
davidmezzetti 11b32da720 Add reindex parameter for API, closes #1111 2026-06-09 15:32:04 -04:00
davidmezzetti 039568541b Add note on ALLOW_PICKLE 2026-06-09 15:31:12 -04:00
davidmezzetti df53803cf7 Add turbovec an ANN backend, closes #1109 2026-06-08 12:18:28 -04:00
davidmezzetti 3c4d32f8f7 Migrate from ggml-py to ggml-python #1105 2026-06-08 07:02:18 -04:00
davidmezzetti 68e1c5719e Bump version 2026-06-04 10:57:45 -04:00
davidmezzetti c3211fbce9 Bump Torch version 2026-06-04 10:57:39 -04:00
davidmezzetti 099b89114e Revert ggml-python migration for now until build issues are resolved #1105 2026-06-02 10:49:06 -04:00
davidmezzetti 0428a71243 Test ggml-python build 2026-06-02 10:34:58 -04:00
davidmezzetti 4ce690d225 Migrate from ggml-py to ggml-python, closes #1105 2026-06-02 10:06:50 -04:00
davidmezzetti 9bb4917c0e Update docs 2026-06-01 10:15:51 -04:00
davidmezzetti a3f95a6a26 Add a Progressive Distillation Example Notebook, closes #1104 2026-05-30 09:19:41 -04:00
davidmezzetti e8000315c0 Add a Knowledge Distillation Trainer, closes #1103 2026-05-30 09:19:14 -04:00
davidmezzetti f9ddb23c10 Reduce noisy logging messages with Transformers v5, closes #1102 2026-05-30 09:12:06 -04:00
davidmezzetti 1d058cf487 Add timeout, readlimit and IPv6 support #1100 2026-05-21 22:16:17 -04:00
davidmezzetti a5d097197e Update docs 2026-05-21 18:48:19 -04:00
davidmezzetti 32e098af84 Add URLRetrieve pipeline, closes #1100 2026-05-21 18:12:34 -04:00
davidmezzetti 8844ec96b4 Update test 2026-05-19 15:13:15 -04:00
davidmezzetti 3e8e495bd2 Add missing deps 2026-05-19 14:36:30 -04:00
davidmezzetti 9d5f82e824 Add support for LiteRT vectors, closes #1097 2026-05-19 14:30:04 -04:00
davidmezzetti 57de5b3a94 Update Dockerfile 2026-05-12 15:17:45 -04:00
davidmezzetti e240d0bb02 Bump version 2026-05-12 15:17:32 -04:00
davidmezzetti 08e3568d78 Update test 2026-05-10 05:41:38 -04:00
davidmezzetti 7ff55f32f7 LiteRT updates 2026-05-09 21:01:05 -04:00
davidmezzetti 0ca702cea2 Update tests 2026-05-08 22:52:47 -04:00
davidmezzetti bb8e9f8a03 Update test 2026-05-08 22:05:45 -04:00
davidmezzetti f2ab0087d5 Update build script 2026-05-08 21:38:16 -04:00
davidmezzetti 47620b194a Update build script 2026-05-08 21:13:55 -04:00
davidmezzetti 798ff2e0ed Add LiteRT-LM LLM, closes #1095 2026-05-08 16:26:15 -04:00
davidmezzetti 345aea0544 Zero dependency minimal install, closes #1094 2026-05-08 08:16:22 -04:00
davidmezzetti 65b72bfdfa Reduce dependencies to just numpy for minimal install, closes #1093 2026-05-07 16:27:05 -04:00
davidmezzetti b14229c1da Make transformers package optional for minimal install, closes #1091 2026-05-05 15:27:44 -04:00
davidmezzetti a0e2c9e4ab Add minimal Docker build script, closes #1092 2026-05-05 15:27:09 -04:00
davidmezzetti d0ddedc048 Add txtai_minimal package, closes #1090 2026-05-05 09:46:27 -04:00
davidmezzetti 6d15bd404a Update build script 2026-05-04 09:46:32 -04:00
davidmezzetti 20fff84a7e Support minimal install for edge devices, closes #1089 2026-05-04 09:26:52 -04:00
davidmezzetti 8643baec3e Update test 2026-05-01 11:43:39 -04:00
davidmezzetti 40c92c15d6 Code cleanup 2026-05-01 10:49:02 -04:00
davidmezzetti 8745aca849 Update test 2026-05-01 10:05:54 -04:00
davidmezzetti 109a4d3c66 Various training pipeline fixes for v5, closes #1088 2026-05-01 09:23:21 -04:00
davidmezzetti 676b997f57 Add custom Questions pipeline implementation, closes #1087 2026-05-01 09:22:07 -04:00
davidmezzetti 2f8860afde Add custom Sequences pipeline implementation, closes #1086 2026-05-01 09:21:17 -04:00
davidmezzetti 688734136c Add custom Summary pipeline implementation, closes #1085 2026-05-01 09:16:18 -04:00
davidmezzetti 1109094c78 Add custom Captions implementation, closes #1084 2026-05-01 09:15:18 -04:00
davidmezzetti cfbf235f54 Bump version 2026-04-29 13:38:32 -04:00
davidmezzetti c10a042cc3 Update build script 2026-04-29 10:41:34 -04:00
davidmezzetti f0715869a4 Test latest version of ggml-py library 2026-04-29 10:09:20 -04:00
davidmezzetti fbce87b9ee Limit template scope with Agents, closes #1080 2026-04-29 07:30:25 -04:00
davidmezzetti 0c6cb615d2 Add link to txtai paper 2026-04-21 08:52:18 -04:00
davidmezzetti 8e569462f2 Performance Improvement: Use JOIN when JSON fields being used, closes #1078 2026-04-20 10:57:57 -04:00
davidmezzetti 12c8b52b5e Update recommended models and links 2026-04-14 10:12:05 -04:00
davidmezzetti a67870aefd Update test 2026-04-08 11:20:37 -04:00
davidmezzetti 40da21b2c3 Update documentation 2026-04-08 11:02:40 -04:00
davidmezzetti 7b055c5b26 Update to handle /tmp being a symlink on macOS 2026-04-08 10:53:35 -04:00
davidmezzetti 6971dc422b Update test 2026-04-08 10:35:09 -04:00
davidmezzetti 511f479251 Add safeopen parameter for Textractor, closes #1077 2026-04-08 10:21:02 -04:00
davidmezzetti c2e2f5d86e Add support for streaming Labels pipeline, closes #1075 2026-04-07 13:16:29 -04:00
davidmezzetti efb0006793 MCP server updates, closes #899, closes #1073 2026-04-07 13:16:05 -04:00
davidmezzetti 04153bd737 Add support for last token pooling, closes #1072 2026-04-05 14:43:41 -04:00
davidmezzetti f2e02dff4a Update embeddings documentation to mention loading ONNX vector models, closes #1071 2026-04-05 10:00:51 -04:00
davidmezzetti b0b181d7e8 Remove build script workaround, closes #1067 2026-03-27 09:45:34 -04:00
davidmezzetti fe916d0049 Re-add build script workaround #1067 2026-03-27 09:25:39 -04:00
davidmezzetti a44dbd1809 Test build dependency fix #1067 2026-03-27 08:08:06 -04:00
davidmezzetti ba6d67498b Add build script workaround #1067 2026-03-27 07:37:37 -04:00
davidmezzetti 1e731c3eb7 Remove build script workaround, closes #1066 2026-03-26 13:51:08 -04:00
davidmezzetti 354b881318 Add build script workaround #1066 2026-03-24 21:29:53 -04:00
davidmezzetti 8fcfa6363a Bump torch version 2026-03-24 08:44:26 -04:00
davidmezzetti d582bf335b Bump version 2026-03-20 13:44:27 -04:00
davidmezzetti 7e3c0e16a4 Add video link 2026-03-17 13:32:32 -04:00
davidmezzetti d12a6681ea Add agent tools example notebook, closes #1062 2026-03-16 14:51:49 -04:00
davidmezzetti 80b90cdbd6 Update comment 2026-03-14 13:16:50 -04:00
davidmezzetti 6343779678 Apply sigmoid to fused BB25 scores, closes #1053 2026-03-14 13:14:29 -04:00
davidmezzetti 2d50a4c202 Add coding agent toolkit, closes #1054 2026-03-14 07:33:17 -04:00
davidmezzetti d2b3758005 Add write tool, closes #1061 2026-03-14 07:32:17 -04:00
davidmezzetti 4c03a8106f Add todowrite tool, closes #1060 2026-03-14 07:31:12 -04:00
davidmezzetti 8f583b2446 Add read tool, closes #1059 2026-03-14 07:30:37 -04:00
davidmezzetti e9c34adde3 Add grep tool, closes #1058 2026-03-14 07:30:02 -04:00
davidmezzetti 6ee6656d40 Add glob tool, closes #1057 2026-03-14 07:29:29 -04:00
davidmezzetti f388ecb4a1 Add edit tool, closes #1056 2026-03-14 07:28:57 -04:00
davidmezzetti 1a0b11654b Add bash tool, closes #1055 2026-03-14 07:28:24 -04:00
JiangNan 79908eee5a Fix translation chunk concatenation when showmodels is enabled (#1052)
* Fix translation chunk concatenation when showmodels is enabled

When translating long text that gets split into multiple chunks by the
tokenizer, the translate() method combines results from the same source
text segment. With showmodels=True, each result is a tuple (path, text).
Using += to combine tuples produces (path, text1, path, text2) instead
of the expected (path, text1+text2). This causes a ValueError when the
caller unpacks with "model, op = outputs[y]" since there are too many
values.

Fix by explicitly concatenating only the text portion of the tuple when
showmodels is enabled.

Signed-off-by: JiangNan <[email protected]>

* Add unit test for showmodels with chunked translation

Adds testLongTranslationWithShowmodels to verify that when text is long
enough to be chunked by the tokenizer, the showmodels result is still a
proper 3-tuple (translation, language, model) and not a malformed tuple
from incorrect concatenation.

Signed-off-by: JiangNan <[email protected]>

* Shorten test method name to fix build

Rename testLongTranslationWithShowmodels -> testShowmodelsChunked
as the previous name was too long for the test runner.

Signed-off-by: JiangNan <[email protected]>

---------

Signed-off-by: JiangNan <[email protected]>
2026-03-09 14:39:54 -04:00
davidmezzetti 69cc7538ac Remove coveralls build script workaround 2026-03-04 13:33:59 -05:00
davidmezzetti 0e3b7ff959 Bump version 2026-02-25 14:42:11 -05:00
davidmezzetti cd116aaa57 Add build script workaround while coveralls is down 2026-02-25 11:33:27 -05:00
davidmezzetti d1aa381e0e Add build script workaround while coveralls is down 2026-02-25 10:54:42 -05:00
davidmezzetti 96234c5754 Reformat docs 2026-02-24 17:36:25 -05:00
davidmezzetti 312f1653e7 Reformat docs 2026-02-24 17:33:52 -05:00
davidmezzetti 5cd7d7e407 Cache Agent Template, closes #1051 2026-02-24 17:08:54 -05:00
davidmezzetti 1a64d33823 Improve subindexes documentation 2026-02-24 17:07:36 -05:00
davidmezzetti 3073589ad6 Add deterministic setting to database functions closes #1048. Add ability to index database expressions #1049 2026-02-22 16:38:54 -05:00
davidmezzetti 2f2bd50027 Add ability to index database expressions, closes #1049 2026-02-22 16:37:11 -05:00
davidmezzetti f7380f64da Add store field to columns configuration, closes #1050 2026-02-22 16:36:08 -05:00
davidmezzetti a53b431492 Add support for custom SQL functions with DuckDB, closes #1047 2026-02-21 06:43:56 -05:00
davidmezzetti 2c937db56b Add sparse normalization info to docs 2026-02-21 06:43:24 -05:00
Jaepil Jeong ba0d1eaead Add BB25 normalization for sparse encoders (#1046)
* Add log-odds conjunction fusion for BB25 hybrid search

BB25 normalization outputs calibrated probabilities, but the existing
hybrid fusion uses convex combination which discards the Bayesian
probability semantics. This causes BB25 to regress on 4/5 BEIR datasets.

Add log-odds conjunction fusion (from "From Bayesian Inference to Neural
Computation") that correctly combines probability signals in logit space
with per-query dynamic calibration for dense cosine scores.

- scoring/normalize.py: Extract Bayesian method check into isbayes()
- scoring/base.py: Add default isbayes() returning False
- scoring/tfidf.py: Add isbayes() delegating to normalizer
- search/base.py: Add logodds(), convex(), rrf() fusion methods;
  dispatch based on isbayes()

BEIR nDCG@10 results (BB25+LogOdds vs Default):
  arguana +2.23, fiqa +2.03, scidocs +0.62, scifact +1.33, nfcorpus -1.96

* Extract Hybrid class for score fusion strategies

Move logodds, convex, and rrf fusion methods from Search into
a dedicated Hybrid class, following the same pattern as Normalize.

* Fix coding convention issues in Hybrid class for CI

- Fix black formatting: remove unnecessary parentheses, remove spaces around **
- Fix pylint too-many-branches: extract calibrate() method from logodds()
- Fix pylint unused-variable: rename score to _ in rrf()

* Add BB25 normalization for sparse encoders and fix IVFSparse topn bug

- Support `normalize: bb25` config for sparse encoder scoring, enabling
  Bayesian sigmoid calibration as an alternative to default linear
  normalization. Reuses existing Normalize.bayes() infrastructure.

- Fix dimension check in IVFSparse.topn(): use scores.shape[1] (number
  of data items) instead of scores.shape[0] (number of queries) for the
  argpartition kth bound check. The previous code caused ValueError when
  the number of centroids was less than nprobe.

* Add tests for BB25 sparse normalization and IVFSparse topn fix
2026-02-20 14:40:18 -05:00
davidmezzetti 89299926bd Add additional methods 2026-02-18 15:44:59 -05:00
davidmezzetti 00acd243b0 Code standardization and added tests #1041 2026-02-18 14:18:11 -05:00
Jaepil Jeong 48f0962a44 Add log-odds conjunction fusion for BB25 hybrid search (#1041)
* Add log-odds conjunction fusion for BB25 hybrid search

BB25 normalization outputs calibrated probabilities, but the existing
hybrid fusion uses convex combination which discards the Bayesian
probability semantics. This causes BB25 to regress on 4/5 BEIR datasets.

Add log-odds conjunction fusion (from "From Bayesian Inference to Neural
Computation") that correctly combines probability signals in logit space
with per-query dynamic calibration for dense cosine scores.

- scoring/normalize.py: Extract Bayesian method check into isbayes()
- scoring/base.py: Add default isbayes() returning False
- scoring/tfidf.py: Add isbayes() delegating to normalizer
- search/base.py: Add logodds(), convex(), rrf() fusion methods;
  dispatch based on isbayes()

BEIR nDCG@10 results (BB25+LogOdds vs Default):
  arguana +2.23, fiqa +2.03, scidocs +0.62, scifact +1.33, nfcorpus -1.96

* Extract Hybrid class for score fusion strategies

Move logodds, convex, and rrf fusion methods from Search into
a dedicated Hybrid class, following the same pattern as Normalize.

* Fix coding convention issues in Hybrid class for CI

- Fix black formatting: remove unnecessary parentheses, remove spaces around **
- Fix pylint too-many-branches: extract calibrate() method from logodds()
- Fix pylint unused-variable: rename score to _ in rrf()
2026-02-18 09:22:45 -05:00
davidmezzetti 1c181e4070 Update docs 2026-02-16 19:05:41 -05:00
davidmezzetti 371d5d8a19 Add test for bb25 2026-02-16 19:01:44 -05:00
davidmezzetti 834e4eb60d Fix cursor error with multithreaded keyword search, closes #1039 2026-02-16 19:01:27 -05:00
davidmezzetti fc579d77aa Update dtype to np.float32 2026-02-16 15:54:22 -05:00
Sigrid Jin (ง'̀-'́)ง oO 90e66075f6 Add Bayesian normalization "bb25" method for keyword scoring (#1037)
* Add Bayesian normalization for keyword scoring

* Add BB25 alias docs and references

* Align BB25 normalization with cognica candidate-set behavior
2026-02-16 15:53:26 -05:00
davidmezzetti 99339570cb Add new features to ngram tokenizer, closes #1038 2026-02-16 15:47:03 -05:00
davidmezzetti 38170a4ab1 Support ngram tokenization, closes #1017 2026-02-16 09:41:41 -05:00
Rin 5a66065b34 Escape single quotes in dynamic column names to prevent SQL injection (#1026) 2026-02-15 10:50:45 -05:00
davidmezzetti 090937a396 Bump version 2026-02-12 17:42:47 -05:00
davidmezzetti d6bd6fc4c6 Slight code improvement 2026-02-11 13:29:54 -05:00
davidmezzetti 90bee00f1d Add ability to store agent memory by session, closes #1025 2026-02-11 13:18:18 -05:00
davidmezzetti f013ca7d1d Workaround macOS test failure 2026-02-10 13:12:37 -05:00
davidmezzetti bfd1f13f2b Workaround macOS test failure 2026-02-10 12:20:32 -05:00
davidmezzetti f682fd949a Fix issue with latest version of FastAPI, closes #1022 2026-02-10 10:46:41 -05:00
davidmezzetti 4758907f3b Add input merging modes for language modeling training, closes #1021. Closes #1020 2026-02-10 09:42:23 -05:00
davidmezzetti b9cec19941 Update docs 2026-02-04 13:18:47 -05:00
davidmezzetti b7c9b156f6 Add example demonstrating how to use skill.md files, closes #1019 2026-02-04 13:18:39 -05:00
davidmezzetti 361b6fe2a5 Add example demonstrating how to use agents.md files, closes #1018 2026-02-04 13:18:21 -05:00
davidmezzetti 45e6080999 Update templates for agent memory 2026-02-04 13:17:49 -05:00
davidmezzetti 92461fe651 Add support for Agent memory, closes #1016 2026-01-30 16:22:01 -05:00
davidmezzetti 3a46f51f25 Add support for agents.md and skill.md. Closes #1014. Closes #1015 2026-01-30 15:35:19 -05:00
davidmezzetti 67543ab31c Update build script versions 2026-01-28 07:47:58 -05:00
davidmezzetti 14c440ac45 Bump version 2026-01-23 12:48:18 -05:00
davidmezzetti 7672f42743 httpx import at module level causes ModuleNotFoundError for Embeddings-only usage, closes #1012 2026-01-23 11:39:11 -05:00
davidmezzetti f360c2d98e Add minimal build workflow, closes #1013 2026-01-23 11:06:52 -05:00
davidmezzetti b4c80cf2e8 Bump torch version 2026-01-21 12:58:57 -05:00
davidmezzetti 831c3fd7d2 Bump version 2026-01-21 12:58:48 -05:00
davidmezzetti d3c498f316 Update documentation 2026-01-21 08:29:25 -05:00
davidmezzetti 001b97b0bf Add example notebook covering OpenCode LLM, closes #1011 2026-01-21 08:28:41 -05:00
davidmezzetti c48ecb3062 Add OpenCode LLM, closes #1010 2026-01-19 21:14:37 -05:00
davidmezzetti f7d5790d07 Update Faiss workaround code #1009 2026-01-16 04:46:18 -05:00
davidmezzetti 5e3492799b Update Faiss workaround code #1009 2026-01-15 20:56:19 -05:00
davidmezzetti 2c3a21490a Update imports 2026-01-15 17:42:44 -05:00
davidmezzetti 846cf2ddc7 Update notes on KMP_DUPLICATE_LIB_OK, closes #1009 2026-01-15 16:18:10 -05:00
davidmezzetti ceb7a4a8f8 Add KMP_DUPLICATE_OK workaround for Faiss OMP Error #1009 2026-01-15 16:06:04 -05:00
davidmezzetti 79e2f9bdef Add video link 2026-01-15 14:39:33 -05:00
davidmezzetti 8d8b29e41c Fix links 2026-01-15 13:21:54 -05:00
davidmezzetti bd2a516eb4 Add example notebook showing how to finetune LLMs, closes #1008 2026-01-15 12:52:07 -05:00
davidmezzetti d4e8ee41f4 Update baseball application #1003 2026-01-11 10:30:34 -05:00
davidmezzetti cdf9a40c8e Update baseball application #1003 2026-01-11 10:29:38 -05:00
davidmezzetti a6c64a6944 Add Tokenizer documentation 2026-01-11 09:38:44 -05:00
davidmezzetti 7132f63c46 Add additional tokenization methods for keyword search, closes #1006 2026-01-11 09:04:36 -05:00
davidmezzetti 1ff636de4a Add RAG video link 2026-01-08 15:27:04 -05:00
davidmezzetti 2a63caf83e Reformat code 2026-01-05 12:05:33 -05:00
davidmezzetti 86e768bccb Load instruction prompts for Sentence Transformers models, closes #1004 2026-01-05 12:03:48 -05:00
davidmezzetti 995428d96c Update application 2025-12-24 10:06:32 -05:00
davidmezzetti 7b97ddf9d8 Update application 2025-12-24 05:38:00 -05:00
davidmezzetti 172f804c1b Update application 2025-12-23 20:36:51 -05:00
davidmezzetti 17b4660abe Fix Baseball Sample Application, closes #1003 2025-12-23 19:20:07 -05:00
davidmezzetti 8c22567d10 Bump version 2025-12-22 20:34:03 -05:00
davidmezzetti 1d7b6a98c9 Sync parameter with LLM pipeline default #998 2025-12-15 13:29:46 -05:00
davidmezzetti 1545901d27 Update notebook 2025-12-15 13:29:25 -05:00
davidmezzetti c4b2bc4251 Add documentation for MUVERA vector settings 2025-12-12 21:07:40 -05:00
davidmezzetti 6021194ac9 Update notebook 2025-12-12 14:46:15 -05:00
davidmezzetti 9d4772bb65 Clean notebook 2025-12-12 14:17:48 -05:00
davidmezzetti a8507d024d Add notebook covering any search method with the RAG Pipeline, closes #1002 2025-12-12 14:11:41 -05:00
davidmezzetti 0c2eab7098 Update notebooks 2025-12-12 10:53:35 -05:00
davidmezzetti 4aa9db69fc Update model paths 2025-12-12 10:46:36 -05:00
davidmezzetti aca56cfe53 Modernize example notebooks, closes #1001 2025-12-12 10:31:27 -05:00
davidmezzetti 203855a9d7 Move LLM and RAG docs into their own folder 2025-12-11 21:31:10 -05:00
davidmezzetti 861545a1ed Update test 2025-12-11 21:30:52 -05:00
davidmezzetti 92d02d748d Add support for any callable search function in RAG pipeline, closes #1000 2025-12-11 20:49:57 -05:00
davidmezzetti 75c4f54f63 Add new LLM default parameters, closes #998. Closes #999. 2025-12-11 20:47:45 -05:00
davidmezzetti 5d6d3f7a6b Update deprecated transformers torch_dtype parameter, closes #997 2025-12-11 20:42:46 -05:00
davidmezzetti 48584abdb4 Update documentation 2025-12-10 18:31:46 -05:00
davidmezzetti 1c4f041b91 Update documentation 2025-12-10 17:52:38 -05:00
davidmezzetti 4ba611760d Update documentation 2025-12-10 17:51:27 -05:00
davidmezzetti c61e18a216 Update documentation 2025-12-10 17:47:29 -05:00
davidmezzetti fb257a2e5e Update documentation 2025-12-10 17:46:30 -05:00
davidmezzetti c26a61dcb6 Update documentation 2025-12-10 17:45:05 -05:00
davidmezzetti b5b3922464 Update documentation 2025-12-03 08:32:30 -05:00
davidmezzetti 441d0eabd7 Add Workflow Quickstart Example, closes #996 2025-12-01 18:44:14 -05:00
davidmezzetti 4d6c0ecc47 Update documentation to use more current LLMs, closes #995 2025-11-30 14:51:15 -05:00
davidmezzetti dd83a40197 model_id is not properly passed with current version of smolagents, closes #993 2025-11-30 14:50:35 -05:00
davidmezzetti 58664444a1 args and kwargs should be ignored when inspecting function parameters in agents, closes #994 2025-11-30 14:50:10 -05:00
davidmezzetti 0a401cb9a2 Add Agent Quickstart Example, closes #992 2025-11-30 14:49:08 -05:00
davidmezzetti d3d26a5ebd Add RAG Quickstart Example, closes #991 2025-11-29 07:22:16 -05:00
davidmezzetti d75be702dd Add support for wildcards in scoring term search, closes #990 2025-11-29 06:52:41 -05:00
davidmezzetti 60755501f5 Add Textractor as top level import, closes #989 2025-11-28 08:10:35 -05:00
davidmezzetti e0f8a9404f Upgrade GLiNER, closes #988 2025-11-25 17:23:30 -05:00
davidmezzetti 26ac43df1c Bump version 2025-11-21 17:03:15 -05:00
davidmezzetti b8da57eb88 Bump torch version 2025-11-21 17:02:55 -05:00
349 changed files with 24781 additions and 3479 deletions
+10 -8
View File
@@ -10,15 +10,15 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
timeout-minutes: 60
timeout-minutes: 75
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.10"
python-version: "3.11"
- name: Install Java
uses: actions/setup-java@v5
@@ -29,20 +29,18 @@ jobs:
- name: Install dependencies - Linux
run: |
sudo apt-get update
sudo apt-get install libportaudio2 libsndfile1
sudo apt-get install libportaudio2 libsndfile1 libegl1 libgles2
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
if: matrix.os == 'ubuntu-latest'
- name: Install dependencies - macOS
run: |
echo "OMP_NUM_THREADS=1" >> $GITHUB_ENV
echo "PYTORCH_MPS_DISABLE=1" >> $GITHUB_ENV
echo "LLAMA_NO_METAL=1" >> $GITHUB_ENV
echo "TIKA_STARTUP_SLEEP=30" >> $GITHUB_ENV
echo "TIKA_STARTUP_MAX_RETRY=10" >> $GITHUB_ENV
echo "KMP_DUPLICATE_LIB_OK=TRUE" >> $GITHUB_ENV
brew install portaudio
sudo xcode-select -s "/Applications/Xcode_16.app"
pip install torch==2.12.1 torchvision==0.27.1
if: matrix.os == 'macos-latest'
- name: Install dependencies - Windows
@@ -63,12 +61,16 @@ jobs:
HF_HUB_ETAG_TIMEOUT: 100
HF_HUB_DOWNLOAD_TIMEOUT: 100
HF_XET_CHUNK_CACHE_SIZE_BYTES: 0
DOCLING_DEVICE: "cpu"
DOCLING_INFERENCE_COMPILE_TORCH_MODELS: false
- uses: pre-commit/[email protected]
if: matrix.os == 'ubuntu-latest'
- name: Test Coverage
run: coveralls --service=github
run: |
coverage report --fail-under=100
coveralls --service=github
if: matrix.os == 'ubuntu-latest'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+12 -5
View File
@@ -7,12 +7,19 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
- name: Checkout code
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.10"
- run: |
python-version: "3.11"
- name: Install txtai
run: |
pip install -U pip wheel
pip install .[all,dev]
- run: mkdocs gh-deploy --force
- name: Deploy documentation
run: mkdocs gh-deploy --force
+22
View File
@@ -0,0 +1,22 @@
# GitHub Actions minimal build
name: minimal
on: ["push", "pull_request"]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Minimal install
run: |
pip install -U pip wheel
MINIMAL=1 pip install .
python -c "import txtai"
+2
View File
@@ -12,6 +12,8 @@ max-locals=40
max-returns=10
max-attributes=20
min-public-methods=0
max-public-methods=80
[FORMAT]
max-line-length=150
max-module-lines=1500
+1
View File
@@ -42,6 +42,7 @@ coverage:
coverage run -m unittest discover -v -k testdatabase -s ${TEST_DIR}
coverage run -m unittest discover -v -k testembeddings -s ${TEST_DIR}
coverage run -m unittest discover -v -k testgraph -s ${TEST_DIR}
coverage run -m unittest discover -v -k testlibrary -s ${TEST_DIR}
coverage run -m unittest discover -v -k testmodels -s ${TEST_DIR}
coverage run -m unittest discover -v -k testoptional -s ${TEST_DIR}
coverage run -m unittest discover -v -k testpipeline.testaudio -s ${TEST_DIR}
+24 -17
View File
@@ -49,9 +49,13 @@ Summary of txtai features:
- 🔋 Batteries included with defaults to get up and running fast
- ☁️ Run local or scale out with container orchestration
txtai is built with Python 3.10+, [Hugging Face Transformers](https://github.com/huggingface/transformers), [Sentence Transformers](https://github.com/UKPLab/sentence-transformers) and [FastAPI](https://github.com/tiangolo/fastapi). txtai is open-source under an Apache 2.0 license.
txtai is built with Python 3.11+, [Hugging Face Transformers](https://github.com/huggingface/transformers), [Sentence Transformers](https://github.com/UKPLab/sentence-transformers) and [FastAPI](https://github.com/tiangolo/fastapi). txtai is open-source under an Apache 2.0 license.
*Interested in an easy and secure way to run hosted txtai applications? Then join the [txtai.cloud](https://txtai.cloud) preview to learn more.*
> [!NOTE]
>
> [NeuML](https://neuml.com) is the company behind txtai and we provide AI consulting services around our stack. [Schedule a meeting](https://cal.com/neuml/intro) or [send a message](mailto:[email protected]) to learn more.
>
> We're also building an easy and secure way to run hosted txtai applications with [txtai.cloud](https://txtai.cloud).
## Why txtai?
@@ -87,7 +91,7 @@ curl -X GET "http://localhost:8000/search?query=positive"
## Use Cases
The following sections introduce common txtai use cases. A comprehensive set of over 60 [example notebooks and applications](https://neuml.github.io/txtai/examples) are also available.
The following sections introduce common txtai use cases. A comprehensive set of over 70 [example notebooks and applications](https://neuml.github.io/txtai/examples) are also available.
### Semantic Search
@@ -130,14 +134,15 @@ Agents connect embeddings, pipelines, workflows and other agents together to aut
![agent](https://raw.githubusercontent.com/neuml/txtai/master/docs/images/agent.png)
txtai agents are built on top of the [smolagents](https://github.com/huggingface/smolagents) framework. This supports all LLMs txtai supports (Hugging Face, llama.cpp, OpenAI / Claude / AWS Bedrock via LiteLLM).
txtai agents are built on top of the [smolagents](https://github.com/huggingface/smolagents) framework. This supports all LLMs txtai supports (Hugging Face, llama.cpp, OpenAI / Claude / AWS Bedrock via LiteLLM). Agent prompting with [`agents.md`](https://github.com/agentsmd/agents.md) and [`skill.md`](https://agentskills.io/specification) are also supported.
See the link below to learn more.
Check out this [Agent Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/agent_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Analyzing Hugging Face Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) | Explore a rich dataset with Graph Analysis and Agents | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) |
| [Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) | Agents that iteratively solve problems as they see fit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |
| [TxtAI got skills](https://github.com/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) | Integrate skill.md files with your agent | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) |
| [Agent Tools](https://github.com/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) [▶️](https://www.youtube.com/watch?v=RDNaFXQy3GQ) | Learn about the txtai agent toolkit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) |
| [Analyzing LinkedIn Company Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) | Exploring how to improve social media engagement with AI | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) |
#### Retrieval augmented generation
@@ -147,12 +152,12 @@ Retrieval augmented generation (RAG) reduces the risk of LLM hallucinations by c
![rag](https://raw.githubusercontent.com/neuml/txtai/master/docs/images/rag.png#gh-light-mode-only)
![rag](https://raw.githubusercontent.com/neuml/txtai/master/docs/images/rag-dark.png#gh-dark-mode-only)
A novel feature of txtai is that it can provide both an answer and source citation.
Check out this [RAG Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/rag_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Chunking your data for RAG](https://github.com/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) | Extract, chunk and index content for effective retrieval | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) [▶️](https://www.youtube.com/watch?v=t_OeAc8NVfQ) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [RAG is more than Vector Search](https://github.com/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) | Context retrieval via Web, SQL and other sources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) |
| [GraphRAG with Wikipedia and GPT OSS](https://github.com/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) | Deep graph search powered RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) |
| [Speech to Speech RAG](https://github.com/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) [▶️](https://www.youtube.com/watch?v=tH8QWwkVMKA) | Full cycle speech to speech workflow with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) |
@@ -165,6 +170,8 @@ Language model workflows, also known as semantic workflows, connect language mod
While LLMs are powerful, there are plenty of smaller, more specialized models that work better and faster for specific tasks. This includes models for extractive question-answering, automatic summarization, text-to-speech, transcription and translation.
Check out this [Workflow Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/workflow_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Run pipeline workflows](https://github.com/neuml/txtai/blob/master/examples/14_Run_pipeline_workflows.ipynb) [▶️](https://www.youtube.com/watch?v=UBMPDCn1gEU) | Simple yet powerful constructs to efficiently process data | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/14_Run_pipeline_workflows.ipynb) |
@@ -183,9 +190,9 @@ The easiest way to install is via pip and PyPI
pip install txtai
```
Python 3.10+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.
Python 3.11+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.
See the detailed [install instructions](https://neuml.github.io/txtai/install) for more information covering [optional dependencies](https://neuml.github.io/txtai/install/#optional-dependencies), [environment specific prerequisites](https://neuml.github.io/txtai/install/#environment-specific-prerequisites), [installing from source](https://neuml.github.io/txtai/install/#install-from-source), [conda support](https://neuml.github.io/txtai/install/#conda) and how to [run with containers](https://neuml.github.io/txtai/cloud).
See the detailed [install instructions](https://neuml.github.io/txtai/install) for more information covering [optional dependencies](https://neuml.github.io/txtai/install/#optional-dependencies), [environment specific prerequisites](https://neuml.github.io/txtai/install/#environment-specific-prerequisites), [installing from source](https://neuml.github.io/txtai/install/#install-from-source), [conda support](https://neuml.github.io/txtai/install/#conda), [lightweight minimal installation](https://neuml.github.io/txtai/install/#minimal-install) and how to [run with containers](https://neuml.github.io/txtai/cloud).
## Model guide
@@ -197,9 +204,9 @@ See the table below for the current recommended models. These models all allow c
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| [Embeddings](https://neuml.github.io/txtai/embeddings) | [all-MiniLM-L6-v2](https://hf.co/sentence-transformers/all-MiniLM-L6-v2) |
| [Image Captions](https://neuml.github.io/txtai/pipeline/image/caption) | [BLIP](https://hf.co/Salesforce/blip-image-captioning-base) |
| [Labels - Zero Shot](https://neuml.github.io/txtai/pipeline/text/labels) | [BART-Large-MNLI](https://hf.co/facebook/bart-large) |
| [Labels - Zero Shot](https://neuml.github.io/txtai/pipeline/text/labels) | [DeBERTa v3 Zeroshot](https://hf.co/MoritzLaurer/deberta-v3-base-zeroshot-v2.0-c) |
| [Labels - Fixed](https://neuml.github.io/txtai/pipeline/text/labels) | Fine-tune with [training pipeline](https://neuml.github.io/txtai/pipeline/train/trainer) |
| [Large Language Model (LLM)](https://neuml.github.io/txtai/pipeline/text/llm) | [Llama 3.1 Instruct](https://hf.co/meta-llama/Llama-3.1-8B-Instruct) |
| [Large Language Model (LLM)](https://neuml.github.io/txtai/pipeline/text/llm) | [Gemma 4 31B](https://hf.co/google/gemma-4-31B) |
| [Summarization](https://neuml.github.io/txtai/pipeline/text/summary) | [DistilBART](https://hf.co/sshleifer/distilbart-cnn-12-6) |
| [Text-to-Speech](https://neuml.github.io/txtai/pipeline/audio/texttospeech) | [ESPnet JETS](https://hf.co/NeuML/ljspeech-jets-onnx) |
| [Transcription](https://neuml.github.io/txtai/pipeline/audio/transcription) | [Whisper](https://hf.co/openai/whisper-base) |
@@ -211,9 +218,8 @@ See the following links to learn more.
- [Hugging Face Tasks](https://hf.co/tasks)
- [Hugging Face Model Hub](https://hf.co/models)
- [MTEB Leaderboard](https://hf.co/spaces/mteb/leaderboard)
- [LMSYS LLM Leaderboard](https://chat.lmsys.org/?leaderboard)
- [Open LLM Leaderboard](https://hf.co/spaces/HuggingFaceH4/open_llm_leaderboard)
- [Embeddings Leaderboard](https://hf.co/spaces/mteb/leaderboard)
- [LLM Leaderboard](https://hf.co/spaces/lmarena-ai/arena-leaderboard)
## Powered by txtai
@@ -224,7 +230,7 @@ The following applications are powered by txtai.
| Application | Description |
|:------------ |:-------------|
| [rag](https://github.com/neuml/rag) | Retrieval Augmented Generation (RAG) application |
| [ragdata](https://github.com/neuml/ragdata) | Build knowledge bases for RAG |
| [ncoder](https://github.com/neuml/ncoder) | Open-Source AI coding agent |
| [paperai](https://github.com/neuml/paperai) | AI for medical and scientific papers |
| [annotateai](https://github.com/neuml/annotateai) | Automatically annotate papers with LLMs |
@@ -236,6 +242,7 @@ In addition to this list, there are also many other [open-source projects](https
![further](https://raw.githubusercontent.com/neuml/txtai/master/docs/images/further-ghdark.png#gh-dark-mode-only)
- [Introducing txtai, the all-in-one AI framework](https://medium.com/neuml/introducing-txtai-the-all-in-one-ai-framework-0660ecfc39d7)
- [txtai: An All-in-One AI Framework for Semantic Search and LLM Workflows](https://github.com/neuml/papers/blob/master/txtai/txtai.pdf)
- [Tutorial series on Hashnode](https://neuml.hashnode.dev/series/txtai-tutorial) | [dev.to](https://dev.to/neuml/tutorial-series-on-txtai-ibg)
- [What's new in txtai 9.0](https://medium.com/neuml/whats-new-in-txtai-9-0-d522bb150afa) | [8.0](https://medium.com/neuml/whats-new-in-txtai-8-0-2d7d0ab4506b) | [7.0](https://medium.com/neuml/whats-new-in-txtai-7-0-855ad6a55440) | [6.0](https://medium.com/neuml/whats-new-in-txtai-6-0-7d93eeedf804) | [5.0](https://medium.com/neuml/whats-new-in-txtai-5-0-e5c75a13b101) | [4.0](https://medium.com/neuml/whats-new-in-txtai-4-0-bbc3a65c3d1c)
- [Getting started with semantic search](https://medium.com/neuml/getting-started-with-semantic-search-a9fd9d8a48cf) | [workflows](https://medium.com/neuml/getting-started-with-semantic-workflows-2fefda6165d9) | [rag](https://medium.com/neuml/getting-started-with-rag-9a0cca75f748)
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 295 KiB

+4 -4
View File
@@ -1,5 +1,5 @@
# Set base image
ARG BASE_IMAGE=python:3.10-slim
ARG BASE_IMAGE=python:3.11-slim
FROM $BASE_IMAGE
# Install GPU-enabled version of PyTorch if set
@@ -8,7 +8,7 @@ ARG GPU
# Target CPU architecture
ARG TARGETARCH
# Set Python version (i.e. 3, 3.10)
# Set Python version (i.e. 3, 3.11)
ARG PYTHON_VERSION=3
# List of txtai components to install
@@ -21,13 +21,13 @@ ENV LANG=C.UTF-8
RUN \
# Install required packages
apt-get update && \
apt-get -y --no-install-recommends install libgomp1 libportaudio2 libsndfile1 git gcc g++ python${PYTHON_VERSION} python${PYTHON_VERSION}-dev python3-pip && \
apt-get -y --no-install-recommends install libgomp1 libportaudio2 libsndfile1 libegl1 libgles2 libvulkan1 git gcc g++ python${PYTHON_VERSION} python${PYTHON_VERSION}-dev python3-pip && \
rm -rf /var/lib/apt/lists && \
\
# Install txtai project and dependencies
ln -s /usr/bin/python${PYTHON_VERSION} /usr/bin/python && \
python -m pip install --no-cache-dir -U pip wheel setuptools && \
if [ -z ${GPU} ] && { [ -z ${TARGETARCH} ] || [ ${TARGETARCH} = "amd64" ] ;}; then pip install --no-cache-dir torch==2.9.0+cpu torchvision==0.24.0+cpu -f https://download.pytorch.org/whl/torch -f https://download.pytorch.org/whl/torchvision; fi && \
if [ -z ${GPU} ]; then pip install --no-cache-dir torch==2.14.1+cpu torchvision==0.29.1+cpu -f https://download.pytorch.org/whl/torch -f https://download.pytorch.org/whl/torchvision; fi && \
python -m pip install --no-cache-dir txtai${COMPONENTS} && \
python -c "import sys, importlib.util as util; 1 if util.find_spec('nltk') else sys.exit(); import nltk; nltk.download(['punkt', 'punkt_tab', 'averaged_perceptron_tagger_eng'])" && \
\
+20
View File
@@ -0,0 +1,20 @@
# Set base image
ARG BASE_IMAGE=python:3.11-slim
FROM $BASE_IMAGE
# Target CPU architecture
ARG TARGETARCH
# Set Python version (i.e. 3, 3.11)
ARG PYTHON_VERSION=3
# Locale environment variables
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN \
# Install minimal txtai project and dependencies
MINIMAL=1 python -m pip install --no-cache-dir txtai_minimal
# Set default working directory
WORKDIR /app
+42 -4
View File
@@ -34,7 +34,7 @@ def today() -> str:
return datetime.today().isoformat()
agent = Agent(
model="hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4",
model="Qwen/Qwen3-4B-Instruct-2507",
tools=[today, wikipedia, arxiv, "websearch"],
)
```
@@ -81,14 +81,52 @@ Embeddings indexes have built-in support. Provide the following dictionary confi
### tool
A tool instance can be provided. Additionally, the following strings load tools directly.
The following shortcut strings load tools directly. Passing a Tool instance is also supported.
| Tool | Description |
|:------------|:----------------------------------------------------------|
| http.* | HTTP Path to a Model Context Protocol (MCP) server |
| bash | Runs a shell command through subprocess |
| defaults | Loads all of these tools as the default toolkit |
| edit | Edits a file in place and returns a diff |
| glob | Finds matching file patterns in a directory |
| grep | Finds matching file content in a directory |
| http.* | HTTP Path to a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) server |
| python | Runs a Python action |
| read | Reads file or url content, supports text extraction |
| todowrite | Generates a task list to organize complex tasks |
| websearch | Runs a websearch using the built-in websearch tool |
| webview | Extracts content from a web page |
| webview | Extracts content from a web page. Alias for `read` tool |
| write | Writes content to file |
| *.md | Loads a [`skill.md`](https://agentskills.io/specification) file |
## instructions
```yaml
instructions: string|path
```
Supports loading an `agents.md` file. Can be provided directly as a string or as a path to a file.
[Read more about agents.md here](https://github.com/agentsmd/agents.md)
## template
```yaml
template: string
```
Customize the prompt template used by this agent. Supports Jinja templates. Uses a default template when this parameter is not provided.
Must include `{{ text }}` and `{{ memory }}` placeholders.
## memory
```yaml
memory: int
```
Keeps a rolling window of `memory` inputs and outputs. These are added to future prompts and serve as "agent memory".
Supports storing memory by `session` to enable multiple conversation threads. Defaults to shared memory when not set. See the [method documentation](../methods#txtai.agent.base.Agent.__call__) for more information.
## method
+9 -5
View File
@@ -5,6 +5,8 @@
An agent automatically creates workflows to answer multi-faceted user requests. Agents iteratively prompt and/or interface with tools to
step through a process and ultimately come to an answer for a request.
Agent prompting with [`agents.md`](https://github.com/agentsmd/agents.md) and [`skill.md`](https://agentskills.io/specification) are also supported. [Read the configuration](./configuration/#tool) for more on how to setup those up.
Agents excel at complex tasks where multiple tools and/or methods are required. They incorporate a level of randomness similar to different
people working on the same task. When the request is simple and/or there is a rule-based process, other methods such as RAG and Workflows
should be explored.
@@ -41,7 +43,7 @@ def today() -> str:
return datetime.today().isoformat()
agent = Agent(
model="hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4",
model="Qwen/Qwen3-4B-Instruct-2507",
tools=[today, wikipedia, arxiv, "websearch"],
max_steps=10,
)
@@ -83,7 +85,7 @@ Agents can also be tools. This enables the concept of building "Agent Teams" to
```python
from txtai import Agent, LLM
llm = LLM("hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4")
llm = LLM("Qwen/Qwen3-4B-Instruct-2507")
websearcher = Agent(
model=llm,
@@ -133,15 +135,14 @@ This provides another level of intelligence to the process. Instead of just a si
```python
agent("""
Work with your team and build a comprehensive report on fundamental
concepts about Signal Processing.
Research fundamental concepts about Signal Processing and build a comprehensive report.
Write the output in Markdown.
""")
```
# More examples
See the link below to learn more.
Check out this [Agent Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/agent_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
@@ -150,3 +151,6 @@ See the link below to learn more.
| [Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) | Agents that iteratively solve problems as they see fit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |
| [Analyzing LinkedIn Company Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) | Exploring how to improve social media engagement with AI | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) |
| [Parsing the stars with txtai](https://github.com/neuml/txtai/blob/master/examples/72_Parsing_the_stars_with_txtai.ipynb) | Explore an astronomical knowledge graph of known stars, planets, galaxies | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/72_Parsing_the_stars_with_txtai.ipynb) |
| [Agentic College Search](https://github.com/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) | Identify list of strong engineering colleges | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) |
| [TxtAI got skills](https://github.com/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) | Integrate skill.md files with your agent | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) |
| [Agent Tools](https://github.com/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) [▶️](https://www.youtube.com/watch?v=RDNaFXQy3GQ) | Learn about the txtai agent toolkit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) |
+11 -2
View File
@@ -33,7 +33,16 @@ Path to save and load the embeddings index. Each API instance can only access a
writable: boolean
```
Determines if the input embeddings index is writable (true) or read-only (false). This allows serving a read-only index.
Sets this embeddings index as writable (true) or read-only (false). This allows serving a read-only index. Defaults to read-only.
### reindex
```yaml
reindex: boolean
```
Enables re-indexing for this embeddings index (defaults to disabled).
Re-indexing accepts new configuration and should only be enabled when the configuration comes from trusted sources.
### cloud
[Cloud storage settings](../../embeddings/configuration/cloud) can be set under a `cloud` top level configuration group.
@@ -51,7 +60,7 @@ agent:
- websearch
llm:
path: hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4
path: Qwen/Qwen3-4B-Instruct-2507
```
## Pipeline
+14 -1
View File
@@ -5,9 +5,22 @@ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction)
The API can be configured to handle MCP requests. All enabled endpoints set in the API configuration are automatically added as MCP tools.
```yaml
mcp: True
mcp: boolean|dict
```
When `mcp` is a boolean, default arguments are used. When `mcp` is a dictionary it supports the following options.
```yaml
mcp:
clientargs: http client options (dict)
mcpargs: FastApiMCP options (dict)
```
See the following links for details on the options.
- [HTTP Client Arguments](https://www.python-httpx.org/api/#asyncclient)
- [FastApiMCP Arguments](https://github.com/tadata-org/fastapi_mcp/blob/main/fastapi_mcp/server.py#L22)
Once this configuration option is added, a new route is added to the application `/mcp`.
The [Model Context Protocol Inspector tool](https://www.npmjs.com/package/@modelcontextprotocol/inspector) is a quick way to explore how the MCP tools are exported through this interface.
+43 -2
View File
@@ -6,9 +6,9 @@ The default implementation of an API service runs via HTTP and is fully open. If
The default API service command starts a Uvicorn server as a HTTP service on port 8000. To run a HTTPS service, consider the following options.
- [TLS Proxy Server](https://fastapi.tiangolo.com/deployment/https/). *Recommended choice*. With this configuration, the txtai API service runs as a HTTP service only accessible on the localhost/local network. The proxy server handles all encryption and redirects requests to local services. See this [example configuration](https://www.uvicorn.org/deployment/#running-behind-nginx) for more.
- [TLS Proxy Server](https://fastapi.tiangolo.com/deployment/https/). *Recommended choice*. With this configuration, the txtai API service runs as a HTTP service only accessible on the localhost/local network. The proxy server handles all encryption and redirects requests to local services. See this [example configuration](https://www.uvicorn.dev/deployment/#running-behind-nginx) for more.
- [Uvicorn SSL Certificate](https://www.uvicorn.org/deployment/). Another option is setting the SSL certificate on the Uvicorn service. This works in simple situations but gets complex when hosting multiple txtai or other related services.
- [Uvicorn SSL Certificate](https://www.uvicorn.dev/deployment/). Another option is setting the SSL certificate on the Uvicorn service. This works in simple situations but gets complex when hosting multiple txtai or other related services.
## Authorization
@@ -31,3 +31,44 @@ curl \
It's important to note that HTTPS **must** be enabled using one of the methods mentioned above. Otherwise, tokens will be exchanged as clear text.
Authentication and Authorization can be fully customized. See the [dependencies](../customization#dependencies) section for more.
## Safe Open
Many components in txtai work with local files and have no restrictions on what files and urls can be accessed. The [textractor pipeline](../../pipeline/data/textractor) and [retrieve](../../workflow/task/retrieve) tasks both have a built-in option called `safeopen` which is enabled by default when running the API and applications. It enforces the following rules:
- Local files must be in the safeopen directory (defaults to temp dir)
- URLs must be public URLs (also has checks for redirects and DNS rebind attempts)
The following workflow only allows accessing files stored in a specific directory along with public urls.
```yaml
workflow:
textract:
tasks:
- action: textractor
```
A number of of pipelines support reading local files. For these it's recommended to wrap those pipelines as workflows with a `retrieve` task. Note that pipelines can be created in-line and don't need to be exposed via the API.
```yaml
workflow:
caption:
tasks:
- task: retrieve
action: caption
```
Additionally, internal pipelines can be created but not exposed via the API.
```yaml
routes:
caption: False
caption:
workflow:
caption:
tasks:
- task: retrieve
action: caption
```
+2 -2
View File
@@ -30,8 +30,8 @@ Examples build commands below.
# Get Dockerfile
wget https://raw.githubusercontent.com/neuml/txtai/master/docker/base/Dockerfile
# Build Ubuntu 22.04 image running Python 3.10
docker build -t txtai --build-arg BASE_IMAGE=ubuntu:22.04 --build-arg PYTHON_VERSION=3.10 .
# Build Ubuntu 22.04 image running Python 3.11
docker build -t txtai --build-arg BASE_IMAGE=ubuntu:22.04 --build-arg PYTHON_VERSION=3.11 .
# Build image with GPU support
docker build -t txtai --build-arg GPU=1 .
+54 -7
View File
@@ -4,7 +4,7 @@ Approximate Nearest Neighbor (ANN) index configuration for storing vector embedd
## backend
```yaml
backend: faiss|hnsw|annoy|ggml|numpy|torch|pgvector|sqlite|custom
backend: faiss|hnsw|annoy|ggml|milvus|numpy|rabitq|torch|turbovec|zvec|pgvector|sqlite|custom
```
Sets the ANN backend. Defaults to `faiss`. Additional backends are available via the [ann](../../../install/#ann) extras package. Set custom backends via setting this parameter to the fully resolvable class string.
@@ -74,9 +74,14 @@ The [GGML](https://github.com/ggml-org/ggml) backend is a k-nearest neighbors ba
[See this](https://github.com/ggml-org/ggml/blob/master/include/ggml.h#L379) for a list of quantization types.
### numpy
### milvus
The NumPy backend is a k-nearest neighbors backend. It's designed for simplicity and works well with smaller datasets that fit into memory.
```yaml
milvus:
m: number of HNSW links per element (int) - defaults to 50
```
### numpy
```yaml
numpy:
@@ -84,12 +89,30 @@ numpy:
defaults to NumPy array storage
```
The NumPy backend is a k-nearest neighbors backend. It's designed for simplicity and works well with smaller datasets that fit into memory.
### rabitq
```yaml
rabitq:
mode: index mode (ivf or hnsw) - defaults to "ivf"
nbits: number of quantization bits per dimension (int) - defaults to 1,
supports 1 to 9 in both modes, ivf mode also supports 32 which
keeps raw vectors for reranking
clusters: number of IVF clusters (int) - defaults to
max(1, min(round(4 * sqrt(embeddings count)), embeddings count))
nprobe: search probe setting for ivf mode (int) - defaults to
max(1, round(num_clusters/16))
m: M param for hnsw mode (int) - defaults to 16
efconstruction: ef_construction param for hnsw mode (int) - defaults to 200
efsearch: ef search param for hnsw mode (int) - defaults to None and not set
randomseed: random-seed param for hnsw mode (int) - defaults to 100
```
The [rabitq](https://github.com/VectorDB-NTU/RaBitQ-Library) backend is a quantized index powered by the [RaBitQ algorithm](https://doi.org/10.1145/3725413). It supports ivf and hnsw search modes. Vectors are stored with 1-bit quantization by default. More bits increase accuracy at the cost of memory. The index is stored as a single file and no vectors are kept outside of it. With nbits set to 32, the vectors are stored in the index for reranking. The ivf mode supports upserts and deletes. Deleted rows keep their storage. Rows added after the first index are assigned to the clusters trained when the index was built, so recall can drop if the new data differs from the original data. Rebuild the index to train new clusters. Note that hnsw indexes can not be modified after creation, upserts/deletes and other modifications are not supported.
### torch
The Torch backend is a k-nearest neighbors backend like NumPy. It supports GPU-enabled operations. It also has support for quantization which enables fitting larger arrays into GPU memory.
When quantization is enabled, vectors are _always_ stored in safetensors. _Note that macOS support for quantization is limited._
```yaml
torch:
safetensors: stores vectors using the safetensors format - defaults
@@ -99,6 +122,30 @@ torch:
blocksize: quantization block size parameter
```
The Torch backend is a k-nearest neighbors backend like NumPy. It supports GPU-enabled operations. It also has support for quantization which enables fitting larger arrays into GPU memory.
When quantization is enabled, vectors are _always_ stored in safetensors. _Note that macOS support for quantization is limited._
### turbovec
```yaml
turbovec:
bitwidth: number of bits to store each vector dimension as. Supports 2, 3 or 4.
```
The [turbovec](https://github.com/RyanCodrai/turbovec) backend is a k-nearest neighbors backend powered by the [TurboQuant algorithm](https://arxiv.org/abs/2504.19874).
### zvec
```yaml
zvec:
efconstruction: ef_construction param for HnswIndexParam (int) - defaults to 200
m: number of HNSW links per element (int) - defaults to 50
efsearch: ef search param for HnswQueryParam (int) - defaults to 300
```
The [zvec](https://github.com/alibaba/zvec) backend is an embedded, path-based vector index.
### pgvector
```yaml
pgvector:
+15 -2
View File
@@ -50,14 +50,27 @@ Object encoding options are:
functions: list
```
List of functions with user-defined SQL functions, only used when [content](#content) is enabled. Each list element must be one of the following:
List of functions with user-defined SQL functions. Each list element must be one of the following:
- function
- callable object
- dict with fields for name, argcount and function
- dict with fields for name, argcount, function and deterministic
[An example can be found here](../../query#custom-sql-functions).
## expressions
```yaml
expressions: list
```
List of expression shortcuts. Each list element must be a dict with the following fields.
- `name`: name of the expression
- `expression`: SQL expression, defaults to `name` when empty
- `index`: if this expression should have a database index, defaults to False when not provided
The expression can be a json data column, sql function or anything that can be run as a SQL snippet.
## query
```yaml
query:
+5
View File
@@ -66,13 +66,18 @@ Sets the auto id generation method. When this is not set, an autogenerated numer
columns:
text: name of the text column
object: name of the object column
store: limit json data fields to this list of columns
```
Sets the `text` and `object` column names. Defaults to `text` and `object` if not provided.
`store` sets a list of columns to store in the JSON data field. When this isn't provided, all columns are stored (default). When `store` is set to `None`, no JSON columns are stored. This is useful is a field is only needed at indexing time but not search time.
## format
```yaml
format: json|pickle
```
Sets the configuration storage format. Defaults to `json`.
Note that `pickle` configuration is deprecated and will raise an error with the default settings. Its only kept for reading legacy indexes and requires setting the `ALLOW_PICKLE` environment variable. Only enable for local and/or trusted sources.
+50 -6
View File
@@ -31,25 +31,30 @@ path: sparse vector model path
vectormethod: vector embeddings method
vectornormalize: enable vector embeddings normalization (boolean)
gpu: boolean|int|string|device
normalize: enable score normalization (boolean | float)
normalize: enable score normalization (boolean|float|string|dict)
batch: Sets the transform batch size
encodebatch: Sets the encode batch size
vectors: additional model init args
encodeargs: additional encode() args
backend: ivfsparse|pgsparse
backend: ivfsparse|pgsparse|zvecsparse
```
Sparse vector scoring options. The sparse scoring instance combines a sparse vector model with a sparse approximate nearest neighbor index (ANN). This method supports both vector normalization and score normalization.
Vector normalization normalizes all vectors to have a magnitude of 1. By extension, all generated scores will be 0 to 1.
Score normalization scales output scores by a scale factor. When `normalize` is set to `True` it uses a default scale factor. If `normalize` is an integer, then that is used as the scale factor. This scales the scores from 0 to 1.
Score normalization scales the output between 0 and 1. This setting supports:
- `True` for default scale normalization
- `float` normalize using this as the scale factor
- `"bayes"` for Bayesian normalization using dynamic candidate score statistics
- `{method: "bayes", alpha: 1.0, beta: null}` for Bayesian normalization with optional custom parameters
#### ivfsparse
```yaml
ivfsparse:
sample: percent of data to use for model training (0.0 - 1.0)
nfeatures: top n features to use for model training (int)
nfeatures: top n features to use for model training, defaults to all features (int)
nlist: desired number of clusters (int)
nprobe: search probe setting (int)
minpoints: minimum number of points for a cluster (int)
@@ -61,6 +66,16 @@ Inverted file (IVF) index with flat vector file storage and sparse array support
Sparse ANN backed by Postgres. Supports same options as the [pgvector](../ann/#pgvector) ANN.
#### zvecsparse
```yaml
zvecsparse:
efconstruction: ef_construction param for HnswIndexParam (int) - defaults to 200
m: number of HNSW links per element (int) - defaults to 50
efsearch: ef search param for HnswQueryParam (int) - defaults to 300
```
Sparse ANN backed by [zvec](https://github.com/alibaba/zvec). Stores sparse vectors in an embedded, path-based vector index. Requires the [ann](../../../install/#ann) extras package.
## terms
```yaml
terms: boolean|dict
@@ -76,9 +91,38 @@ Supports a `dict` with the parameters `cachelimit` and `cutoff`.
When `terms` is set to `True`, default parameters are used for the `cachelimit` and `cutoff`. Normally, these defaults are sufficient.
### Wildcard queries
Keyword queries containing `*` expand matching terms using SQL `LIKE`. Within these
expressions, `%` matches any sequence and `_` matches one character. To match a literal
percent sign, underscore or backslash, use `\%`, `\_` or `\\`, respectively.
For example, `report\_*` matches `report_2026`, while `report_*` also matches `reportX2026`.
Use a tokenizer that preserves these characters, such as `tokenizer: {whitespace: true}`,
or pass pre-tokenized query terms. Queries without `*` retain exact-term matching.
## normalize
```yaml
normalize: boolean
normalize: boolean|str|dict
```
Enables normalized scoring (ranging from 0 to 1). When enabled, statistics from the index will be used to calculate normalized scores.
Enables normalized scoring (ranging from 0 to 1). This setting supports:
- `True` for standard score normalization
- `"bayes"` | `"bb25"` for Bayesian normalization using dynamic candidate score statistics
- `{method: "bayes", alpha: 1.0, beta: null}` for Bayesian normalization with optional custom parameters
When standard normalization is enabled, statistics from the index are used to calculate normalized scores.
When Bayesian/BB25 normalization is enabled, it uses positive-score candidates, dynamic `beta=median(scores)`, adaptive
`alpha_eff=alpha/std(scores)` and a sigmoid transform (likelihood-only variant with flat prior) to map scores to `[0, 1]`.
Bayesian normalization references:
- [https://github.com/instructkr/bb25](https://github.com/instructkr/bb25)
- [https://github.com/cognica-io/bayesian-bm25](https://github.com/cognica-io/bayesian-bm25)
## tokenizer
```yaml
tokenizer: dict
```
Set tokenization rules. Passes these arguments to the underlying [Tokenization pipeline](../../../pipeline/data/tokenizer#txtai.pipeline.Tokenizer.__init__).
+65 -6
View File
@@ -12,7 +12,8 @@ Sets the path for a vectors model. When using a transformers/sentence-transforme
## method
```yaml
method: transformers|sentence-transformers|llama.cpp|litellm|model2vec|external|words
method: transformers|sentence-transformers|llama.cpp|litellm|model2vec|external|
words
```
Embeddings method to use. If the method is not provided, it is inferred using the `path`.
@@ -24,11 +25,12 @@ Embeddings method to use. If the method is not provided, it is inferred using th
Builds embeddings using a transformers model. While this can be any transformers model, it works best with
[models trained](https://huggingface.co/models?pipeline_tag=sentence-similarity) to build embeddings.
`mean`, `cls` and `late` pooling are supported and automatically inferred from the model. The pooling method can be overwritten by changing the method
from `transformers` to `meanpooling`, `clspooling` or `latepooling` respectively.
`mean`, `cls`, `last`, `late` and `max` pooling are supported and automatically inferred from the model. The pooling method can be overwritten by changing the method from `transformers` to `meanpooling`, `clspooling`, `lastpooling`, `latepooling` or `maxpooling` respectively.
Setting `maxlength` to `True` enables truncating inputs to the `max_seq_length`. Setting `maxlength` to an integer will truncate inputs to that value. When omitted (default), the `maxlength` will be set to either the model or tokenizer maxlength.
Supports loading ONNX models directly. [See this section for more](../../../examples/#model-training).
### sentence-transformers
Same as transformers but loads models with the [sentence-transformers](https://github.com/UKPLab/sentence-transformers) library.
@@ -65,7 +67,9 @@ Embeddings are created via an external model or API. Requires setting the [trans
transform: function
```
When method is `external`, this function transforms input content into embeddings. The input to this function is a list of data. This method must return either a numpy array or list of numpy arrays.
When method is `external`, this function transforms input content into embeddings. The input to this function is a list of data. This method must return either a numpy array, list of numpy arrays or list of float arrays.
Note that this method is deprecated and will raise an error with the default settings. Adding a custom `Vectors` implementation is a cleaner approach. The `ALLOW_RESOLVE_TRANSFORM` environment variable must be set to enable. Only enable for trusted and/or reviewed code.
## gpu
```yaml
@@ -104,7 +108,7 @@ quantize: int|boolean
Enables scalar vector quantization at the specified precision. Supports 1-bit through 8-bit quantization. Scalar quantization transforms continuous floating point values to discrete unsigned integers. The `faiss`, `pgvector`, `numpy` and `torch` ANN backends support storing these vectors.
This parameter supports booleans for backwards compatability. When set to true/false, this flag sets [faiss.quantize](../ann/#faiss).
This parameter supports booleans for backwards compatibility. When set to true/false, this flag sets [faiss.quantize](../ann/#faiss).
In addition to vector-level quantization, some ANN backends have the ability to quantize vectors at the storage layer. See the [ANN](../ann) configuration options for more.
@@ -117,7 +121,7 @@ instructions:
Instruction-based models use prefixes to modify how embeddings are computed. This is especially useful with asymmetric search, which is when the query and indexed data are of vastly different lengths. In other words, short queries with long documents.
[E5-base](https://huggingface.co/intfloat/e5-base) is an example of a model that accepts instructions. It takes `query: ` and `passage: ` prefixes and uses those to generate embeddings that work well for asymmetric search.
`txtai` automatically loads prompts stored in `config_sentence_transformers.json` except if this parameter is set. For some older models such as [E5-base](https://huggingface.co/intfloat/e5-base), instructions still need to be provided via this parameter.
## models
```yaml
@@ -139,3 +143,58 @@ vectors: dict
```
Passes these additional parameters to the underlying vector model.
### center
```yaml
center: boolean | dict
```
Centers normalized late-interaction token vectors and normalizes them again before MUVERA or LEMUR encoding. Centering is applied to
both query and document vectors. `true` uses batch scope and `false` disables centering. An explicit setting always takes precedence.
When omitted, a LEMUR artifact with a stored collection mean uses collection scope. Other LEMUR artifacts and late-interaction models
default to batch scope only when they load more than one `torch.nn.Linear` layer; models with zero or one loaded linear layer keep their
previous output.
Dictionary configuration supports the following scopes:
```yaml
center:
scope: document | batch | collection
```
`document` subtracts the mean of each document or query independently. `batch` subtracts the mean of all real token rows in the current
model batch. Explicit `collection` scope requires a caller-provided, one-dimensional mean vector through either `mean` (an array-like
value) or `path` (a safetensors file containing a `center.mean` tensor), but not both. LEMUR artifacts can provide this mean
automatically. Zero-padding rows are never centered and remain zero.
### muvera
```yaml
muvera:
repetitions: defaults 20
hashes: defaults to 5
projection: defaults 16
```
Settings to control the size of MUVERA fixed dimensional outputs. Default is 20 * 2^5 * 16 = 10,240 dimensions.
Set `muvera` to `false` to disable it or `true` to use the default settings. `false` only makes sense when the multi-vector output
is consumed directly, for example through `PoolingFactory`. Embeddings vectors require `muvera` or `lemur`.
### lemur
```yaml
lemur:
path: local artifact directory or Hugging Face Hub path
```
Loads a trained [LEMUR](../../../pipeline/train/lemur) fixed dimensional encoder. LEMUR artifacts are corpus-specific and must be
created with `LemurTrainer` before configuring an embeddings index. A bare string is treated as the artifact path. Query vectors are
summed learned features and document vectors are ordinary least squares weights over the artifact's stored token sample. Each artifact
contains `config.json` and `model.safetensors`; newly trained artifacts also store the collection token mean as `lemur.center`. Loading that mean automatically
selects collection centering unless `center` is explicitly configured. Artifacts without `lemur.center` retain the previous default.
The Safetensors file contains inference state only. See the trainer page for score filtering and Faiss exact/IVF search behavior.
### trust_remote_code
```yaml
trust_remote_code: boolean
```
Parameter for trusting the code from Hugging Face models with custom implementations.
+2
View File
@@ -23,6 +23,8 @@ As mentioned above, computed vectors are stored in an ANN. There are various ind
Embeddings indexes can optionally [store content](../configuration/database#content). When this is enabled, the input content is saved in a database alongside the computed vectors. This enables filtering on additional fields and content retrieval.
The columns used for text, object and JSON data storage are set via [column configuration](../configuration/general#columns).
## Index vs Upsert
Data is loaded into an index with either an [index](../methods#txtai.embeddings.base.Embeddings.index) or [upsert](../methods#txtai.embeddings.base.Embeddings.upsert) call.
+57 -6
View File
@@ -54,6 +54,8 @@ The number of candidates should be larger than the desired number of results whe
- For a single query filter clause, the default is the query limit
- With multiple filtering clauses, the default is 10x the query limit
When a query orders results by score, its `offset` adds to the query limit.
The index name is only applicable when [subindexes](../configuration/general/#indexes) are enabled. This specifies the index to use for the query.
Weights sets the hybrid score weights when an index has both a sparse and dense index.
@@ -132,8 +134,11 @@ embeddings = Embeddings(content=True, objects=True)
request = open("demo.gif", "rb")
# Insert record
embeddings.index([("txtai", {"text": "txtai executes machine-learning workflows.",
"object": request.read()})])
embeddings.index([(
"txtai",
{"text": "txtai executes machine-learning workflows.",
"object": request.read()}
)])
# Query txtai and get associated object
query = "SELECT object FROM txtai WHERE similar('machine learning') LIMIT 1"
@@ -169,6 +174,26 @@ LIMIT 1
""")
```
## Expressions
Expression shortcuts expand into more complex SQL snippets. This is useful for making SQL queries more concise. Indexing is also available on expressions as a performance improvement.
The following example indexes a json extraction field (`filepath`) and the length of each field.
```python
# Create embeddings index
embeddings = Embeddings(
path="sentence-transformers/nli-mpnet-base-v2",
content=True,
expressions=[
{"name": "filepath", "index": True},
{"name": "textlength", "expression": "length(text)", "index": True}
]
)
embeddings.search("SELECT textlength, filepath FROM txtai LIMIT 1")
```
## Query translation
Natural language queries with filters can be converted to txtai-compatible SQL statements with query translation. For example:
@@ -192,7 +217,9 @@ When an embeddings database has both a sparse and dense index, both indexes will
```python
embeddings.search("query", weights=0.5)
embeddings.search("SELECT id, text, score FROM txtai WHERE similar('query', 0.5)")
embeddings.search(
"SELECT id, text, score FROM txtai WHERE similar('query', 0.5)"
)
```
## Graph search
@@ -203,11 +230,20 @@ Additionally, standard embeddings searches can be returned as graphs.
```python
# Find all paths between id: 0 and id: 5 between 1 and 3 hops away
embeddings.graph.search("""
embeddings.search("""
MATCH P=({id: 0})-[*1..3]->({id: 5})
RETURN P
""")
# Find related nodes for query matches
embeddings.search("""
MATCH P=(A)-[]->(B)
WHERE SIMILAR(A, "query")
RETURN B
ORDER BY A.score DESC
LIMIT 10
""")
# Standard embeddings search as graph
embeddings.search("query", graph=True)
```
@@ -217,13 +253,28 @@ embeddings.search("query", graph=True)
Subindexes can be queried as follows:
```python
# Build index with subindexes
embeddings = Embeddings(
content=True,
defaults=False,
indexes={
"keyword": {
"keyword": True
},
"dense":{
"dense": True
}
}
)
embeddings.index(stream())
# Query with index parameter
embeddings.search("query", index="subindex1")
embeddings.search("query", index="keyword")
# Specify with SQL
embeddings.search("""
SELECT id, text, score FROM txtai
WHERE similar('query', 'subindex1')
WHERE similar('query', 'keyword')
""")
```
+9 -2
View File
@@ -31,7 +31,7 @@ Autonomous agents, retrieval augmented generation (RAG), chat with your data, pi
|:----------|:-------------|------:|
| [Prompt-driven search with LLMs](https://github.com/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) | Embeddings-guided and Prompt-driven search with Large Language Models (LLMs) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) |
| [Prompt templates and task chains](https://github.com/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) | Build model prompts and connect tasks together with workflows | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) [▶️](https://www.youtube.com/watch?v=t_OeAc8NVfQ) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Integrate LLM frameworks](https://github.com/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) | Integrate llama.cpp, LiteLLM and custom generation frameworks | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) |
| [Generate knowledge with Semantic Graphs and RAG](https://github.com/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) | Knowledge exploration and discovery with Semantic Graphs and RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) |
| [Build knowledge graphs with LLMs](https://github.com/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) | Build knowledge graphs with LLM-driven entity extraction | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) |
@@ -48,6 +48,11 @@ Autonomous agents, retrieval augmented generation (RAG), chat with your data, pi
| [Chunking your data for RAG](https://github.com/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) | Extract, chunk and index content for effective retrieval | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) |
| [Medical RAG Research with txtai](https://github.com/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) | Analyze PubMed article metadata with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) |
| [GraphRAG with Wikipedia and GPT OSS](https://github.com/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) | Deep graph search powered RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) |
| [RAG is more than Vector Search](https://github.com/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) | Context retrieval via Web, SQL and other sources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) |
| [OpenCode as a txtai LLM](https://github.com/neuml/txtai/blob/master/examples/81_OpenCode_as_a_txtai_LLM.ipynb) | Integrate OpenCode with the txtai ecosystem | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/81_OpenCode_as_a_txtai_LLM.ipynb) |
| [Agentic College Search](https://github.com/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) | Identify a list of strong engineering colleges | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) |
| [TxtAI got skills](https://github.com/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) | Integrate skill.md files with your agent | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) |
| [Agent Tools](https://github.com/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) [▶️](https://www.youtube.com/watch?v=RDNaFXQy3GQ) | Learn about the txtai agent toolkit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) |
## Pipelines
@@ -85,7 +90,7 @@ Efficiently process data at scale.
## Model Training
Train NLP models.
Train, distill, fine-tune and export models.
| Notebook | Description | |
|:----------|:-------------|------:|
@@ -93,6 +98,8 @@ Train NLP models.
| [Train without labels](https://github.com/neuml/txtai/blob/master/examples/17_Train_without_labels.ipynb) | Use zero-shot classifiers to train new models | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/17_Train_without_labels.ipynb) |
| [Train a QA model](https://github.com/neuml/txtai/blob/master/examples/19_Train_a_QA_model.ipynb) | Build and fine-tune question-answering models | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/19_Train_a_QA_model.ipynb) |
| [Train a language model from scratch](https://github.com/neuml/txtai/blob/master/examples/41_Train_a_language_model_from_scratch.ipynb) | Build new language models | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/41_Train_a_language_model_from_scratch.ipynb) |
| [Distilling Knowledge into Tiny LLMs](https://github.com/neuml/txtai/blob/master/examples/80_Distilling_Knowledge_into_Tiny_LLMs.ipynb) [▶️](https://www.youtube.com/watch?v=Ol560ktgkf0) | Finetune tiny LLMs to enable inference using less resources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/80_Distilling_Knowledge_into_Tiny_LLMs.ipynb) |
| [Progressive Distillation](https://github.com/neuml/txtai/blob/master/examples/85_Progressive_Distillation.ipynb) | Incrementally compress knowledge from a series of teachers | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/85_Progressive_Distillation.ipynb) |
| [Export and run models with ONNX](https://github.com/neuml/txtai/blob/master/examples/18_Export_and_run_models_with_ONNX.ipynb) | Export models with ONNX, run natively in JavaScript, Java and Rust | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/18_Export_and_run_models_with_ONNX.ipynb) |
| [Export and run other machine learning models](https://github.com/neuml/txtai/blob/master/examples/21_Export_and_run_other_machine_learning_models.ipynb) | Export and run models from scikit-learn, PyTorch and more | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/21_Export_and_run_other_machine_learning_models.ipynb) |
+6 -5
View File
@@ -68,11 +68,11 @@ import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from txtai import LLM
# Load Phi 3.5-mini
path = "microsoft/Phi-3.5-mini-instruct"
# Load Qwen3 0.6B
path = "Qwen/Qwen3-0.6B"
model = AutoModelForCausalLM.from_pretrained(
path,
torch_dtype=torch.bfloat16,
dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained(path)
@@ -105,11 +105,12 @@ __Solution__
Set the following environment parameters.
- OpenMP threading is handled internally on macOS platforms but it can be disabled via `export OMP_NUM_THREADS=1`
- Disable OpenMP multithreading via `export OMP_NUM_THREADS=1`
- Workaround `OMP: Error #15` errors via `export KMP_DUPLICATE_LIB_OK=TRUE`
- Disable PyTorch MPS device via `export PYTORCH_MPS_DISABLE=1`
- Disable llama.cpp metal via `export LLAMA_NO_METAL=1`
For more details, refer to [this issue on GitHub](https://github.com/kyamagu/faiss-wheels/issues/100).
For more details, refer to [this issue on GitHub](https://github.com/kyamagu/faiss-wheels/issues/73).
----------
+1
View File
@@ -4,6 +4,7 @@
![further](images/further-dark.png#only-dark)
- [Introducing txtai, the all-in-one AI framework](https://medium.com/neuml/introducing-txtai-the-all-in-one-ai-framework-0660ecfc39d7)
- [txtai: An All-in-One AI Framework for Semantic Search and LLM Workflows](https://github.com/neuml/papers/blob/master/txtai/txtai.pdf)
- [Tutorial series on Hashnode](https://neuml.hashnode.dev/series/txtai-tutorial) | [dev.to](https://dev.to/neuml/tutorial-series-on-txtai-ibg)
- [What's new in txtai 9.0](https://medium.com/neuml/whats-new-in-txtai-9-0-d522bb150afa) | [8.0](https://medium.com/neuml/whats-new-in-txtai-8-0-2d7d0ab4506b) | [7.0](https://medium.com/neuml/whats-new-in-txtai-7-0-855ad6a55440) | [6.0](https://medium.com/neuml/whats-new-in-txtai-6-0-7d93eeedf804) | [5.0](https://medium.com/neuml/whats-new-in-txtai-5-0-e5c75a13b101) | [4.0](https://medium.com/neuml/whats-new-in-txtai-4-0-bbc3a65c3d1c)
- [Getting started with semantic search](https://medium.com/neuml/getting-started-with-semantic-search-a9fd9d8a48cf) | [workflows](https://medium.com/neuml/getting-started-with-semantic-workflows-2fefda6165d9) | [rag](https://medium.com/neuml/getting-started-with-rag-9a0cca75f748)
+6 -2
View File
@@ -51,6 +51,10 @@ Summary of txtai features:
- 🔋 Batteries included with defaults to get up and running fast
- ☁️ Run local or scale out with container orchestration
txtai is built with Python 3.10+, [Hugging Face Transformers](https://github.com/huggingface/transformers), [Sentence Transformers](https://github.com/UKPLab/sentence-transformers) and [FastAPI](https://github.com/tiangolo/fastapi). txtai is open-source under an Apache 2.0 license.
txtai is built with Python 3.11+, [Hugging Face Transformers](https://github.com/huggingface/transformers), [Sentence Transformers](https://github.com/UKPLab/sentence-transformers) and [FastAPI](https://github.com/tiangolo/fastapi). txtai is open-source under an Apache 2.0 license.
*Interested in an easy and secure way to run hosted txtai applications? Then join the [txtai.cloud](https://txtai.cloud) preview to learn more.*
!!! note
[NeuML](https://neuml.com) is the company behind txtai and we provide AI consulting services around our stack. [Schedule a meeting](https://cal.com/neuml/intro) or [send a message](mailto:[email protected]) to learn more.
We're also building an easy and secure way to run hosted txtai applications with [txtai.cloud](https://txtai.cloud).
+23 -3
View File
@@ -9,7 +9,7 @@ The easiest way to install is via pip and PyPI
pip install txtai
```
Python 3.10+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.
Python 3.11+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.
## Optional dependencies
@@ -130,7 +130,11 @@ Additional environment specific prerequisites are below.
### Linux
The AudioStream and Microphone pipelines require the [PortAudio](https://python-sounddevice.readthedocs.io/en/0.5.0/installation.html) system library. The Transcription pipeline requires the [SoundFile](https://github.com/bastibe/python-soundfile#installation) system library.
The AudioStream and Microphone pipelines require the [PortAudio](https://python-sounddevice.readthedocs.io/en/0.5.0/installation.html) system library.
The Transcription pipeline requires the [SoundFile](https://github.com/bastibe/python-soundfile#installation) system library.
The LiteRT LLM pipeline requires libegl1, libgles2 and libvulkan1.
### macOS
@@ -146,7 +150,7 @@ The [txtai build workflow](https://github.com/neuml/txtai/blob/master/.github/wo
## CPU-only
The default install adds PyTorch with GPU support. There are a number of dependencies that come with that. When running in a CPU-only environment or using Embeddings/LLM models without PyTorch (i.e. llama.cpp or API services), the CPU-only PyTorch package can be installed with txtai as follows.
The default install adds PyTorch with GPU support. There are a number of dependencies that come with that. When running in a CPU-only environment, the CPU-only PyTorch package can be installed with txtai as follows.
```
pip install txtai torch==[version]+cpu \
@@ -173,6 +177,22 @@ A [community-supported txtai package](https://anaconda.org/conda-forge/txtai) is
conda install -c conda-forge txtai
```
## Minimal install
A lightweight zero dependency minimal install package is available. This is helpful if the default libraries are too heavy or there are no plans to use them.
All the same extras mentioned above are available in this version of the package.
```
# Lightweight minimal install
pip install txtai_minimal
# Same as standard `txtai` install
pip install txtai_minimal[default]
```
Note that in order to use the `Embeddings` or `LLM` interface without `torch` requires either `llama.cpp`, `litellm` or `litert`.
## Run with containers
Docker images are available for txtai. [See this section](../cloud) for more information on container-based installs.
+4 -5
View File
@@ -8,9 +8,9 @@ See the table below for the current recommended models. These models all allow c
| ---------------------------------------------------- | ------------------------------------------------------------------------ |
| [Embeddings](../embeddings) | [all-MiniLM-L6-v2](https://hf.co/sentence-transformers/all-MiniLM-L6-v2) |
| [Image Captions](./pipeline/image/caption.md) | [BLIP](https://hf.co/Salesforce/blip-image-captioning-base) |
| [Labels - Zero Shot](./pipeline/text/labels.md) | [BART-Large-MNLI](https://hf.co/facebook/bart-large) |
| [Labels - Zero Shot](./pipeline/text/labels.md) | [DeBERTa v3 Zeroshot](https://hf.co/MoritzLaurer/deberta-v3-base-zeroshot-v2.0-c) |
| [Labels - Fixed](./pipeline/text/labels.md) | Fine-tune with [training pipeline](./pipeline/train/trainer.md) |
| [Large Language Model (LLM)](./pipeline/text/llm.md) | [Llama 3.1 Instruct](https://hf.co/meta-llama/Llama-3.1-8B-Instruct) |
| [Large Language Model (LLM)](./pipeline/text/llm.md) | [Gemma 4 31B](https://hf.co/google/gemma-4-31B) |
| [Summarization](./pipeline/text/summary.md) | [DistilBART](https://hf.co/sshleifer/distilbart-cnn-12-6) |
| [Text-to-Speech](./pipeline/audio/texttospeech.md) | [ESPnet JETS](https://hf.co/NeuML/ljspeech-jets-onnx) |
| [Transcription](./pipeline/audio/transcription.md) | [Whisper](https://hf.co/openai/whisper-base) |
@@ -22,6 +22,5 @@ See the following links to learn more.
- [Hugging Face Tasks](https://hf.co/tasks)
- [Hugging Face Model Hub](https://hf.co/models)
- [MTEB Leaderboard](https://hf.co/spaces/mteb/leaderboard)
- [LMSYS LLM Leaderboard](https://chat.lmsys.org/?leaderboard)
- [Open LLM Leaderboard](https://hf.co/spaces/HuggingFaceH4/open_llm_leaderboard)
- [Embeddings Leaderboard](https://hf.co/spaces/mteb/leaderboard)
- [LLM Leaderboard](https://hf.co/spaces/lmarena-ai/arena-leaderboard)
+3 -3
View File
@@ -88,7 +88,7 @@ with mlflow.start_run():
# Create RAG pipeline
rag = RAG(
wiki,
"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4",
"openai/gpt-oss-20b",
system="You are a friendly assistant. You answer questions from users.",
template=template,
context=10
@@ -155,8 +155,8 @@ embeddings.load(provider="huggingface-hub", container="neuml/txtai-astronomy")
agent = Agent(
tools=[search],
llm="hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4",
max_iterations=10,
llm="Qwen/Qwen3-4B-Instruct-2507",
max_steps=10,
)
researcher = """
+6
View File
@@ -17,6 +17,12 @@ Apache Tika requires [Java](https://en.wikipedia.org/wiki/Java_(programming_lang
See [this link](https://github.com/DS4SD/docling?tab=readme-ov-file#features) for a list of supported document formats.
## LiteParse
[LiteParse](https://github.com/run-llama/liteparse) is a fast, helpful, and open-source document parser. It supports PDF out of the box with additional format support via third-party packages.
See [this link](https://github.com/run-llama/liteparse#multi-format-input-support) for more.
## Example
The following shows a simple example using this pipeline.
+2
View File
@@ -16,6 +16,8 @@ The [backend](../filetohtml/#txtai.pipeline.FileToHTML.__init__) parameter sets
See the [FiletoHTML](../filetohtml) and [HTMLToMarkdown](../htmltomd) pipelines to learn more on the dependencies necessary for each of those pipelines.
Note that the default parameters enable access to all local files and all URLs. The `safeopen` parameter limits this to only files in a specified directory (defaults to temp directory) and public URLs. When running the textractor pipeline through an Application or via the API, `safeopen` defaults to True. It can be disabled if desired via configuration.
## Example
The following shows a simple example using this pipeline.
+82
View File
@@ -0,0 +1,82 @@
# Tokenizer
![pipeline](../../images/pipeline.png#only-light)
![pipeline](../../images/pipeline-dark.png#only-dark)
The Tokenizer pipeline splits text into tokens. This is primarily used for keyword / term indexing.
_Note: Transformers-based models have their own tokenizers and this pipeline isn't designed for working with Transformers models._
## Example
The following shows a simple example using this pipeline.
```python
from txtai.pipeline import Tokenizer
# Create and run pipeline
tokenizer = Tokenizer()
tokenizer("text to tokenize")
# Whitespace tokenization
tokenizer = Tokenizer(whitespace=True)
tokenizer("text to tokenize")
# Tokenize using a regular expression
tokenizer = Tokenizer(regexp=r"\w{5,}")
tokenizer("text to tokenize")
# Tokenize into trigrams like pg_trgm
tokenizer = Tokenizer(ngrams={
"ngrams": 3, "lpad": " ", "rpad": " ", "unique": True
})
tokenize("text to tokenize")
# Tokenize into edge ngrams
tokenizer = Tokenizer(ngrams={"nmin": 2, "nmax": 5, "edge": True})
tokenizer("text to tokenize")
```
## Configuration-driven example
Pipelines are run with Python or configuration. Pipelines can be instantiated in [configuration](../../../api/configuration/#pipeline) using the lower case name of the pipeline. Configuration-driven pipelines are run with [workflows](../../../workflow/#configuration-driven-example) or the [API](../../../api#local-instance).
### config.yml
```yaml
# Create pipeline using lower case class name
tokenizer:
# Run pipeline with workflow
workflow:
tokenizer:
tasks:
- action: tokenizer
```
### Run with Workflows
```python
from txtai import Application
# Create and run pipeline with workflow
app = Application("config.yml")
list(app.workflow("tokenizer", ["text to tokenize"]))
```
### Run with API
```bash
CONFIG=config.yml uvicorn "txtai.api:app" &
curl \
-X POST "http://localhost:8000/workflow" \
-H "Content-Type: application/json" \
-d '{"name":"tokenizer", "elements":["text"]}'
```
## Methods
Python documentation for the pipeline.
### ::: txtai.pipeline.Tokenizer.__init__
### ::: txtai.pipeline.Tokenizer.__call__
+62
View File
@@ -0,0 +1,62 @@
# URL Retrieve
![pipeline](../../images/pipeline.png#only-light)
![pipeline](../../images/pipeline-dark.png#only-dark)
The URL Retrieve pipeline retrieves content from a HTTP(s) URL.
## Example
The following shows a simple example using this pipeline.
```python
from txtai.pipeline import URLRetrieve
# Create and run pipeline
urlretrieve = URLRetrieve()
urlretrieve("https://github.com/neuml/txtai")
```
## Configuration-driven example
Pipelines are run with Python or configuration. Pipelines can be instantiated in [configuration](../../../api/configuration/#pipeline) using the lower case name of the pipeline. Configuration-driven pipelines are run with [workflows](../../../workflow/#configuration-driven-example) or the [API](../../../api#local-instance).
### config.yml
```yaml
# Create pipeline using lower case class name
urlretrieve:
# Run pipeline with workflow
workflow:
retrieve:
tasks:
- action: urlretrieve
```
### Run with Workflows
```python
from txtai import Application
# Create and run pipeline with workflow
app = Application("config.yml")
list(app.workflow("urlretrieve", ["https://github.com/neuml/txtai"]))
```
### Run with API
```bash
CONFIG=config.yml uvicorn "txtai.api:app" &
curl \
-X POST "http://localhost:8000/workflow" \
-H "Content-Type: application/json" \
-d '{"name":"retrieve", "elements":["http://github.com/neuml/txtai"]}'
```
## Methods
Python documentation for the pipeline.
### ::: txtai.pipeline.URLRetrieve.__init__
### ::: txtai.pipeline.URLRetrieve.__call__
+2
View File
@@ -26,6 +26,8 @@ The `LLM` and `RAG` pipelines also have integrations for [llama.cpp](https://git
- [Segmentation](data/segmentation)
- [Tabular](data/tabular)
- [Text extraction](data/textractor)
- [Tokenizer](data/tokenizer)
- [URLRetrieve](data/urlretrieve)
- Image
- [Caption](image/caption)
- [Image Hash](image/imagehash)
@@ -29,8 +29,8 @@ llm(
"""
)
# Instruction tuned models typically require string prompts to
# follow a specific chat template set by the model
# Prompts with chat templating can be directly passed
# The template format varies by model
llm(
"""
<|im_start|>system
@@ -47,41 +47,70 @@ llm([
{"role": "user", "content": "Answer the following question..."}
])
# Set the default role to user and string inputs are converted to chat messages
# When there is no system prompt passed to instruction tuned models
# the default role is inferred `defaultrole="auto"`
llm("Answer the following question...")
# To always generate chat messages for string inputs
llm("Answer the following question...", defaultrole="user")
# To never generate chat messages for string inputs
llm("Answer the following question...", defaultrole="prompt")
```
The LLM pipeline automatically detects the underlying LLM framework. This can also be manually set.
The LLM pipeline automatically detects the underlying LLM framework. This can also be manually set. The following methods are supported.
[Hugging Face Transformers](https://github.com/huggingface/transformers), [llama.cpp](https://github.com/abetlen/llama-cpp-python) and [hosted API models via LiteLLM](https://github.com/BerriAI/litellm) are all supported by this pipeline.
- [Hugging Face Transformers](https://github.com/huggingface/transformers)
- [llama.cpp](https://github.com/abetlen/llama-cpp-python)
- [LLM APIs via LiteLLM](https://github.com/BerriAI/litellm)
- [LiteRT-LM](https://ai.google.dev/edge/litert-lm)
- [OpenCode server](https://github.com/anomalyco/opencode)
See the [LiteLLM documentation](https://litellm.vercel.app/docs/providers) for the options available with LiteLLM models. llama.cpp models support both local and remote GGUF paths on the HF Hub.
`llama.cpp` and `LiteRT-LM` support both local and remote file paths on the HF Hub.
See the [LiteLLM documentation](https://litellm.vercel.app/docs/providers) for the options available with LiteLLM models.
See the [OpenCode documentation](https://opencode.ai/docs/server/) for more on how to integrate the LLM pipeline with a running OpenCode instance.
```python
from txtai import LLM
# Transformers
llm = LLM("meta-llama/Meta-Llama-3.1-8B-Instruct")
llm = LLM("meta-llama/Meta-Llama-3.1-8B-Instruct", method="transformers")
llm = LLM("openai/gpt-oss-20b")
llm = LLM("openai/gpt-oss-20b", method="transformers")
# llama.cpp
llm = LLM("microsoft/Phi-3-mini-4k-instruct-gguf/Phi-3-mini-4k-instruct-q4.gguf")
llm = LLM("microsoft/Phi-3-mini-4k-instruct-gguf/Phi-3-mini-4k-instruct-q4.gguf",
llm = LLM("unsloth/gpt-oss-20b-GGUF/gpt-oss-20b-Q4_K_M.gguf")
llm = LLM("unsloth/gpt-oss-20b-GGUF/gpt-oss-20b-Q4_K_M.gguf",
method="llama.cpp")
# LiteLLM
llm = LLM("ollama/llama3.1")
llm = LLM("ollama/llama3.1", method="litellm")
llm = LLM("ollama/gpt-oss")
llm = LLM("ollama/gpt-oss", method="litellm")
# LiteRT-LM
llm = LLM(
"litert-community/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm"
)
llm = LLM(
"litert-community/gemma-4-E2B-it-litert-lm/gemma-4-E2B-it.litertlm",
method="litert"
)
# Custom Ollama endpoint
llm = LLM("ollama/llama3.1", api_base="http://localhost:11434")
llm = LLM("ollama/gpt-oss", api_base="http://localhost:11434")
# Custom OpenAI-compatible endpoint
llm = LLM("openai/llama3.1", api_base="http://localhost:4000")
llm = LLM("openai/gpt-oss", api_base="http://localhost:4000")
# LLM APIs - must also set API key via environment variable
llm = LLM("gpt-4o")
llm = LLM("claude-3-5-sonnet-20240620")
llm = LLM("gpt-5.2")
llm = LLM("claude-opus-4-5-20251101")
llm = LLM("gemini/gemini-3-pro-preview")
# Local OpenCode server started via `opencode serve`
llm = LLM("opencode")
llm = LLM("opencode/big-pickle", url="http://localhost:4000")
```
Models can be externally loaded and passed to pipelines. This is useful for models that are not yet supported by Transformers and/or need special initialization.
@@ -92,11 +121,11 @@ import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from txtai import LLM
# Load Phi 3.5-mini
path = "microsoft/Phi-3.5-mini-instruct"
# Load Qwen3 0.6B
path = "Qwen/Qwen3-0.6B"
model = AutoModelForCausalLM.from_pretrained(
path,
torch_dtype=torch.bfloat16,
dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained(path)
@@ -109,7 +138,7 @@ See the links below for more detailed examples.
|:----------|:-------------|------:|
| [Prompt-driven search with LLMs](https://github.com/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) | Embeddings-guided and Prompt-driven search with Large Language Models (LLMs) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) |
| [Prompt templates and task chains](https://github.com/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) | Build model prompts and connect tasks together with workflows | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) [▶️](https://www.youtube.com/watch?v=t_OeAc8NVfQ) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Integrate LLM frameworks](https://github.com/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) | Integrate llama.cpp, LiteLLM and custom generation frameworks | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) |
| [Generate knowledge with Semantic Graphs and RAG](https://github.com/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) | Knowledge exploration and discovery with Semantic Graphs and RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) |
| [Build knowledge graphs with LLMs](https://github.com/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) | Build knowledge graphs with LLM-driven entity extraction | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) |
@@ -118,7 +147,6 @@ See the links below for more detailed examples.
| [RAG with llama.cpp and external API services](https://github.com/neuml/txtai/blob/master/examples/62_RAG_with_llama_cpp_and_external_API_services.ipynb) | RAG with additional vector and LLM frameworks | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/62_RAG_with_llama_cpp_and_external_API_services.ipynb) |
| [How RAG with txtai works](https://github.com/neuml/txtai/blob/master/examples/63_How_RAG_with_txtai_works.ipynb) | Create RAG processes, API services and Docker instances | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/63_How_RAG_with_txtai_works.ipynb) |
| [Speech to Speech RAG](https://github.com/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) [▶️](https://www.youtube.com/watch?v=tH8QWwkVMKA) | Full cycle speech to speech workflow with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) |
| [Generative Audio](https://github.com/neuml/txtai/blob/master/examples/66_Generative_Audio.ipynb) | Storytelling with generative audio workflows | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/66_Generative_Audio.ipynb) |
| [Analyzing Hugging Face Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) | Explore a rich dataset with Graph Analysis and Agents | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) |
| [Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) | Agents that iteratively solve problems as they see fit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |
| [Getting started with LLM APIs](https://github.com/neuml/txtai/blob/master/examples/70_Getting_started_with_LLM_APIs.ipynb) | Generate embeddings and run LLMs with OpenAI, Claude, Gemini, Bedrock and more | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/70_Getting_started_with_LLM_APIs.ipynb) |
@@ -127,6 +155,11 @@ See the links below for more detailed examples.
| [Chunking your data for RAG](https://github.com/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) | Extract, chunk and index content for effective retrieval | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) |
| [Medical RAG Research with txtai](https://github.com/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) | Analyze PubMed article metadata with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) |
| [GraphRAG with Wikipedia and GPT OSS](https://github.com/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) | Deep graph search powered RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) |
| [RAG is more than Vector Search](https://github.com/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) | Context retrieval via Web, SQL and other sources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) |
| [OpenCode as a txtai LLM](https://github.com/neuml/txtai/blob/master/examples/81_OpenCode_as_a_txtai_LLM.ipynb) | Integrate OpenCode with the txtai ecosystem | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/81_OpenCode_as_a_txtai_LLM.ipynb) |
| [Agentic College Search](https://github.com/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) | Identify a list of strong engineering colleges | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/82_Agentic_College_Search.ipynb) |
| [TxtAI got skills](https://github.com/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) | Integrate skill.md files with your agent | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) |
| [Agent Tools](https://github.com/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) [▶️](https://www.youtube.com/watch?v=RDNaFXQy3GQ) | Learn about the txtai agent toolkit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) |
## Configuration-driven example
@@ -148,8 +181,8 @@ Similar to the Python example above, the underlying [Hugging Face pipeline param
```yaml
llm:
path: microsoft/Phi-3.5-mini-instruct
torch_dtype: torch.bfloat16
path: Qwen/Qwen3-0.6B
dtype: torch.bfloat16
```
### Run with Workflows
@@ -30,8 +30,8 @@ data = [
embeddings = Embeddings(content=True)
embeddings.index(data)
# Create and run pipeline
rag = RAG(embeddings, "google/flan-t5-base", template="""
# Create the RAG pipeline
rag = RAG(embeddings, "Qwen/Qwen3-0.6B", template="""
Answer the following question using the provided context.
Question:
@@ -41,11 +41,12 @@ rag = RAG(embeddings, "google/flan-t5-base", template="""
{context}
""")
# Run RAG pipeline
rag("What was won?")
# Instruction tuned models typically require string prompts to
# follow a specific chat template set by the model
rag = RAG(embeddings, "meta-llama/Meta-Llama-3.1-8B-Instruct", template="""
# Prompts with chat templating can be directly passed
# The template format varies by model
rag = RAG(embeddings, "Qwen/Qwen3-0.6B", template="""
<|im_start|>system
You are a friendly assistant.<|im_end|>
<|im_start|>user
@@ -65,7 +66,7 @@ rag("What was won?")
# system prompt is provided
rag = RAG(
embeddings,
"meta-llama/Meta-Llama-3.1-8B-Instruct",
"openai/gpt-oss-20b",
system="You are a friendly assistant",
template="""
Answer the following question using the provided context.
@@ -79,49 +80,32 @@ rag = RAG(
rag("What was won?")
# LLM options can be passed as additional arguments
rag = RAG(embeddings, "meta-llama/Meta-Llama-3.1-8B-Instruct", template="""
Answer the following question using the provided context.
Question:
{question}
Context:
{context}
""")
# Set the default role to user and string inputs are converted to chat messages
rag("What was won?", defaultrole="user")
# - Streaming RAG response with `stream=True`
# - String inputs are always converted to user messages with `defaultrole="user"`
# - Thinking text is removed with `stripthink=True`
rag("What was won?", stream=True, defaultrole="user", stripThink=True)
```
See the [Embeddings](../../../embeddings) and [LLM](../llm) pages for additional configuration options.
See the links below for more detailed examples.
Check out this [RAG Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/rag_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Prompt-driven search with LLMs](https://github.com/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) | Embeddings-guided and Prompt-driven search with Large Language Models (LLMs) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/42_Prompt_driven_search_with_LLMs.ipynb) |
| [Prompt templates and task chains](https://github.com/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) | Build model prompts and connect tasks together with workflows | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) [▶️](https://www.youtube.com/watch?v=t_OeAc8NVfQ) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Integrate LLM frameworks](https://github.com/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) | Integrate llama.cpp, LiteLLM and custom generation frameworks | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) |
| [Generate knowledge with Semantic Graphs and RAG](https://github.com/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) | Knowledge exploration and discovery with Semantic Graphs and RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/55_Generate_knowledge_with_Semantic_Graphs_and_RAG.ipynb) |
| [Build knowledge graphs with LLMs](https://github.com/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) | Build knowledge graphs with LLM-driven entity extraction | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) |
| [Advanced RAG with graph path traversal](https://github.com/neuml/txtai/blob/master/examples/58_Advanced_RAG_with_graph_path_traversal.ipynb) | Graph path traversal to collect complex sets of data for advanced RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/58_Advanced_RAG_with_graph_path_traversal.ipynb) |
| [Advanced RAG with guided generation](https://github.com/neuml/txtai/blob/master/examples/60_Advanced_RAG_with_guided_generation.ipynb) | Retrieval Augmented and Guided Generation | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/60_Advanced_RAG_with_guided_generation.ipynb) |
| [RAG with llama.cpp and external API services](https://github.com/neuml/txtai/blob/master/examples/62_RAG_with_llama_cpp_and_external_API_services.ipynb) | RAG with additional vector and LLM frameworks | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/62_RAG_with_llama_cpp_and_external_API_services.ipynb) |
| [How RAG with txtai works](https://github.com/neuml/txtai/blob/master/examples/63_How_RAG_with_txtai_works.ipynb) | Create RAG processes, API services and Docker instances | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/63_How_RAG_with_txtai_works.ipynb) |
| [Speech to Speech RAG](https://github.com/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) [▶️](https://www.youtube.com/watch?v=tH8QWwkVMKA) | Full cycle speech to speech workflow with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) |
| [Generative Audio](https://github.com/neuml/txtai/blob/master/examples/66_Generative_Audio.ipynb) | Storytelling with generative audio workflows | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/66_Generative_Audio.ipynb) |
| [Analyzing Hugging Face Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) | Explore a rich dataset with Graph Analysis and Agents | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) |
| [Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) | Agents that iteratively solve problems as they see fit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |
| [Getting started with LLM APIs](https://github.com/neuml/txtai/blob/master/examples/70_Getting_started_with_LLM_APIs.ipynb) | Generate embeddings and run LLMs with OpenAI, Claude, Gemini, Bedrock and more | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/70_Getting_started_with_LLM_APIs.ipynb) |
| [Analyzing LinkedIn Company Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) | Exploring how to improve social media engagement with AI | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) |
| [Extractive QA with txtai](https://github.com/neuml/txtai/blob/master/examples/05_Extractive_QA_with_txtai.ipynb) | Introduction to extractive question-answering with txtai | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/05_Extractive_QA_with_txtai.ipynb) |
| [Extractive QA with Elasticsearch](https://github.com/neuml/txtai/blob/master/examples/06_Extractive_QA_with_Elasticsearch.ipynb) | Run extractive question-answering queries with Elasticsearch | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/06_Extractive_QA_with_Elasticsearch.ipynb) |
| [Extractive QA to build structured data](https://github.com/neuml/txtai/blob/master/examples/20_Extractive_QA_to_build_structured_data.ipynb) | Build structured datasets using extractive question-answering | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/20_Extractive_QA_to_build_structured_data.ipynb) |
| [Parsing the stars with txtai](https://github.com/neuml/txtai/blob/master/examples/72_Parsing_the_stars_with_txtai.ipynb) | Explore an astronomical knowledge graph of known stars, planets, galaxies | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/72_Parsing_the_stars_with_txtai.ipynb) |
| [Chunking your data for RAG](https://github.com/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) | Extract, chunk and index content for effective retrieval | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) |
| [Medical RAG Research with txtai](https://github.com/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) | Analyze PubMed article metadata with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/75_Medical_RAG_Research_with_txtai.ipynb) |
| [GraphRAG with Wikipedia and GPT OSS](https://github.com/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) | Deep graph search powered RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) |
| [RAG is more than Vector Search](https://github.com/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) | Context retrieval via Web, SQL and other sources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) |
## Configuration-driven example
@@ -137,7 +121,7 @@ embeddings:
content: True
rag:
path: google/flan-t5-base
path: Qwen/Qwen3-0.6B
template: |
Answer the following question using the provided context.
+98
View File
@@ -0,0 +1,98 @@
# LemurTrainer
![pipeline](../../images/pipeline.png#only-light)
![pipeline](../../images/pipeline-dark.png#only-dark)
Trains a LEMUR fixed dimensional encoder for a late interaction model and corpus. Training is a separate pipeline step; the saved
artifact is then loaded through the embeddings `vectors.lemur` configuration.
`LemurTrainer` owns training-data construction, feature-model setup, epoch training and validation-based selection. The loaded LEMUR
pooler remains responsible for query-feature and document-weight encoding.
## Example
```python
from txtai.pipeline import LemurTrainer
corpus = [
"First document",
"Second document",
"Third document",
]
trainer = LemurTrainer()
trainer(
"colbert-ir/colbertv2.0",
corpus,
"lemur-model",
epochs=100,
validationsplit=0.1,
)
```
`epochs` is required so the training mode is explicit. Use `epochs=100` for the quality-oriented MLP setting. This can take hours on
a CPU. Use `epochs=0` to select deterministic random ELM features as a lower-cost fallback.
The learn distribution defaults to `learncategory="query"`. Target documents are always encoded with the data encoder, so the
default encodes selected corpus texts once as data and once as queries. Set `learncategory="data"` to reuse the data encodings, or
pass a separate iterable of texts with `learn`.
When `vectors.center` is omitted, the trainer encodes the corpus without centering, computes one mean over all corpus token rows and
uses that mean to center both data and learn vectors before fitting. The collection mean is stored in the LEMUR artifact. An explicit
`vectors.center` setting keeps its configured behavior and does not store an automatic collection mean.
Set `corpussubsetsize` to a positive integer to sample that many raw corpus texts under `seed` before either encoding pass. The
default is `None`, which uses every corpus text. `trainsubsetsize` and `learnsubsetsize` apply later, after token vectors have already
been created. `corpussubsetsize` applies to `data`; a separate `learn` iterable remains caller-sized.
For trained MLP features, set `validationsplit` to a fraction greater than zero and less than one to retain the epoch with the lowest
held-out loss. The default is `0.0`, which preserves training-loss selection. The selected one-based epoch, loss and metric are
available as `selectedepoch`, `selectedloss` and `selectionmetric` on the fitted or reloaded encoder.
MLP training displays a `tqdm` progress bar on an interactive terminal, including percent complete and the current validation loss
when `validationsplit` is enabled (or training loss otherwise). Progress output is disabled for non-interactive runs.
The artifact contains `config.json` and `model.safetensors`. It stores the inference feature model, output-normalization statistics,
token sample needed to encode documents added after training and, by default, the collection token mean. The training-only output
readout is not saved.
Load the artifact in an embeddings configuration.
```yaml
embeddings:
path: colbert-ir/colbertv2.0
vectors:
lemur:
path: lemur-model
```
## Search behavior
Loading a LEMUR artifact with a stored collection mean automatically centers both query and document token vectors with that mean.
This keeps training and search on the same representation and makes fixed vectors independent of indexing or query batch size. An
explicit `vectors.center` setting takes precedence. Older artifacts without a stored mean use the standard late-pooling fallback:
batch centering for models with multiple linear layers and no centering for models with zero or one linear layer.
LEMUR approximates standardized MaxSim targets, so useful ranking scores can be negative. txtai's dense vector path L2-normalizes the
fixed vectors and removes results with scores less than or equal to zero. This can change ordering and return fewer than the requested
number of candidates compared with raw maximum inner-product search.
The Faiss backend uses exact `IDMap,Flat` search through 5,000 rows and switches to an IVF index above that threshold. In the measured
scifact run, default IVF reduced LEMUR NDCG@10 by 43% relative to exact search, compared with 25% for MUVERA. For LEMUR corpora above
5,000 rows, either pin `faiss.components` to an exact index or tune the IVF settings for the corpus. The exact configuration is:
```yaml
embeddings:
path: colbert-ir/colbertv2.0
vectors:
lemur:
path: lemur-model
faiss:
components: IDMap,Flat
```
## Methods
Python documentation for the pipeline.
### ::: txtai.pipeline.LemurTrainer.__call__
+14
View File
@@ -98,6 +98,20 @@ See the following PEFT documentation links for more information.
- [Quantization](https://huggingface.co/docs/peft/developer_guides/quantization)
- [LoRA](https://huggingface.co/docs/peft/developer_guides/lora)
## Merge
An important parameter for `language-generation` and `language-modeling` tasks is `merge` or the packing of data into chunks.
It supports the following options.
- `concat` (default) - text is split into chunks up to maxlength, data can be split across multiple chunks
- `pack` - text is split into chunks up to maxlength, data guaranteed to be in same chunk, chunks can be smaller than maxlength
- `None` - disables merging
Merging helps reduce training time as data can be processed efficiently without padding. `concat` maximizes this as it guarantees each chunk will be up to maxlength size. `pack` is a middle ground where data is combined but records are preserved.
For general language modeling tasks like masked language modeling, `concat` is the best choice. For instruction/prompt fine-tuning, `pack` or None are the better choices as it guarantees complex logic is not split across chunks.
## Methods
Python documentation for the pipeline.
+1 -1
View File
@@ -7,7 +7,7 @@ The following applications are powered by txtai.
| Application | Description |
|:------------ |:-------------|
| [rag](https://github.com/neuml/rag) | Retrieval Augmented Generation (RAG) application |
| [ragdata](https://github.com/neuml/ragdata) | Build knowledge bases for RAG |
| [ncoder](https://github.com/neuml/ncoder) | Open-Source AI coding agent |
| [paperai](https://github.com/neuml/paperai) | AI for medical and scientific papers |
| [annotateai](https://github.com/neuml/annotateai) | Automatically annotate papers with LLMs |
+10 -7
View File
@@ -1,6 +1,6 @@
# Use Cases
The following sections introduce common txtai use cases. A comprehensive set of over 60 [example notebooks and applications](../examples) are also available.
The following sections introduce common txtai use cases. A comprehensive set of over 70 [example notebooks and applications](../examples) are also available.
## Semantic Search
@@ -42,14 +42,15 @@ Agents connect embeddings, pipelines, workflows and other agents together to aut
![agent](images/agent.png)
txtai agents are built on top of the [smolagents](https://github.com/huggingface/smolagents) framework. This supports all LLMs txtai supports (Hugging Face, llama.cpp, OpenAI / Claude / AWS Bedrock via LiteLLM).
txtai agents are built on top of the [smolagents](https://github.com/huggingface/smolagents) framework. This supports all LLMs txtai supports (Hugging Face, llama.cpp, OpenAI / Claude / AWS Bedrock via LiteLLM). Agent prompting with [`agents.md`](https://github.com/agentsmd/agents.md) and [`skill.md`](https://agentskills.io/specification) are also supported.
See the link below to learn more.
Check out this [Agent Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/agent_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Analyzing Hugging Face Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) | Explore a rich dataset with Graph Analysis and Agents | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) |
| [Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) | Agents that iteratively solve problems as they see fit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |
| [TxtAI got skills](https://github.com/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) | Integrate skill.md files with your agent | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/83_TxtAI_got_skills.ipynb) |
| [Agent Tools](https://github.com/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) [▶️](https://www.youtube.com/watch?v=RDNaFXQy3GQ) | Learn about the txtai agent toolkit | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/84_Agent_Tools.ipynb) |
| [Analyzing LinkedIn Company Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) | Exploring how to improve social media engagement with AI | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) |
### Retrieval augmented generation
@@ -59,12 +60,12 @@ Retrieval augmented generation (RAG) reduces the risk of LLM hallucinations by c
![rag](images/rag.png#gh-light-mode-only)
![rag](images/rag-dark.png#gh-dark-mode-only)
A novel feature of txtai is that it can provide both an answer and source citation.
Check out this [RAG Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/rag_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [Chunking your data for RAG](https://github.com/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) | Extract, chunk and index content for effective retrieval | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/73_Chunking_your_data_for_RAG.ipynb) |
| [Build RAG pipelines with txtai](https://github.com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) [▶️](https://www.youtube.com/watch?v=t_OeAc8NVfQ) | Guide on retrieval augmented generation including how to create citations | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |
| [RAG is more than Vector Search](https://github.com/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) | Context retrieval via Web, SQL and other sources | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/79_RAG_is_more_than_Vector_Search.ipynb) |
| [GraphRAG with Wikipedia and GPT OSS](https://github.com/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) | Deep graph search powered RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/77_GraphRAG_with_Wikipedia_and_GPT_OSS.ipynb) |
| [Speech to Speech RAG](https://github.com/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) [▶️](https://www.youtube.com/watch?v=tH8QWwkVMKA) | Full cycle speech to speech workflow with RAG | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) |
@@ -77,6 +78,8 @@ Language model workflows, also known as semantic workflows, connect language mod
While LLMs are powerful, there are plenty of smaller, more specialized models that work better and faster for specific tasks. This includes models for extractive question-answering, automatic summarization, text-to-speech, transcription and translation.
Check out this [Workflow Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/workflow_quickstart.py). Additional examples are listed below.
| Notebook | Description | |
|:----------|:-------------|------:|
| [Run pipeline workflows](https://github.com/neuml/txtai/blob/master/examples/14_Run_pipeline_workflows.ipynb) [▶️](https://www.youtube.com/watch?v=UBMPDCn1gEU) | Simple yet powerful constructs to efficiently process data | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuml/txtai/blob/master/examples/14_Run_pipeline_workflows.ipynb) |
+3 -3
View File
@@ -133,7 +133,7 @@ Workflows can connect multiple LLM prompting tasks together.
```yaml
llm:
path: google/flan-t5-xl
path: openai/gpt-oss-20b
workflow:
llm:
@@ -168,7 +168,7 @@ Any txtai pipeline/workflow task can be connected in workflows with LLMs.
```yaml
llm:
path: google/flan-t5-xl
path: openai/gpt-oss-20b
translation:
@@ -202,4 +202,4 @@ Workflows are callable objects. Workflows take an input of iterable data element
## More examples
See [this link](../examples/#workflows) for a full list of workflow examples.
Check out this [Workflow Quickstart Example](https://github.com/neuml/txtai/blob/master/examples/workflow_quickstart.py). See [this link](../examples/#workflows) for a full list of workflow examples.
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: console
name:
tasks:
- task: console
```
## Methods
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: export
name:
tasks:
- task: export
```
## Methods
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: file
name:
tasks:
- task: file
```
## Methods
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: image
name:
tasks:
- task: image
```
## Methods
+17 -3
View File
@@ -35,12 +35,26 @@ Tasks can also be created with configuration as part of a workflow.
```yaml
workflow:
tasks:
- action: summary
name:
tasks:
- action: summary
```
::: txtai.workflow.Task.__init__
## Multi-action task inputs
A multi-action `Task` requires reusable inputs. Passing a single-pass iterator, such as a generator or the output of a `StreamTask`, raises a `ValueError` before consuming inputs or running any actions. Automatically buffering an iterator could exhaust memory, so tasks do not convert these inputs to a list.
Iterators passed to a `Workflow` remain supported: the workflow collects bounded batches before passing them to its tasks. For example:
```python
workflow = Workflow([Task([list, list])], batch=2)
list(workflow(iter([1, 2, 3]))) # [(1, 1), (2, 2), (3, 3)]
```
This batching occurs at the workflow input; it does not batch iterator outputs produced by tasks inside that workflow. Single-action tasks continue to accept iterator inputs.
## Multi-action task concurrency
The default processing mode is to run actions sequentially. Multiprocessing support is already built in at a number of levels. Any of the GPU models will maximize GPU utilization for example and even in CPU mode, concurrency is utilized. But there are still use cases for task action concurrency. For example, if the system has multiple GPUs, the task runs external sequential code, or the task has a large number of I/O tasks.
@@ -72,7 +86,7 @@ workflow = Workflow([Task(lambda x: [y * 3 for y in x], unpack=False, column=0)]
list(workflow([(2, 8)]))
```
For the example input tuple of (2, 2), the workflow will only select the first element (2) and run the task against that element.
For the example input tuple of (2, 8), the workflow will only select the first element (2) and run the task against that element.
```python
workflow = Workflow([Task([lambda x: [y * 3 for y in x],
+4 -3
View File
@@ -22,9 +22,10 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: retrieve
directory: /tmp
name:
tasks:
- task: retrieve
directory: /tmp
```
## Methods
+4 -3
View File
@@ -22,9 +22,10 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: service
url: https://service.url/action
name:
tasks:
- task: service
url: https://service.url/action
```
## Methods
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: storage
name:
tasks:
- task: storage
```
## Methods
+4 -3
View File
@@ -23,9 +23,10 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: template
template: This is a {text} task
name:
tasks:
- task: template
template: This is a {text} task
```
## Methods
+3 -2
View File
@@ -22,8 +22,9 @@ This task can also be created with workflow configuration.
```yaml
workflow:
tasks:
- task: url
name:
tasks:
- task: url
```
## Methods
File diff suppressed because one or more lines are too long
+197 -198
View File
@@ -1,28 +1,4 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.7.6",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
},
"colab": {
"provenance": []
}
},
"cells": [
{
"cell_type": "markdown",
@@ -61,44 +37,59 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5",
"_cell_guid": "b1076dfc-b9ad-4769-8c92-a6c4dae69d19",
"trusted": true,
"_kg_hide-output": true,
"id": "24q-1n5i6XzQ"
"_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5",
"id": "24q-1n5i6XzQ",
"trusted": true
},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline]"
],
"execution_count": null,
"outputs": []
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0p3WCDniUths"
},
"source": [
"# Create index\n",
"Let's first recap how to create an index. We'll use the classic txtai example.\n"
],
"metadata": {
"id": "0p3WCDniUths"
}
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"_uuid": "d629ff2d2480ee46fbb7e2d37f6b5fab8052498a",
"_cell_guid": "79c7e3d0-c299-4dcb-8224-4455121ee9b0",
"trusted": true,
"id": "2j_CFGDR6Xzp",
"_uuid": "d629ff2d2480ee46fbb7e2d37f6b5fab8052498a",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "e65238c5-d67f-4fe4-9cbf-c88b0ff3a8bb"
"id": "2j_CFGDR6Xzp",
"outputId": "e65238c5-d67f-4fe4-9cbf-c88b0ff3a8bb",
"trusted": true
},
"outputs": [
{
"data": {
"text/plain": [
"[{'id': '4',\n",
" 'text': 'Maine man wins $1M from $25 lottery ticket',\n",
" 'score': 0.08329025655984879}]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from txtai.embeddings import Embeddings\n",
"from txtai import Embeddings\n",
"\n",
"data = [\"US tops 5 million confirmed virus cases\",\n",
" \"Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg\",\n",
@@ -108,65 +99,29 @@
" \"Make huge profits without work, earn up to $100,000 a day\"]\n",
"\n",
"# Create embeddings index with content enabled. The default behavior is to only store indexed vectors.\n",
"embeddings = Embeddings({\"path\": \"sentence-transformers/nli-mpnet-base-v2\", \"content\": True})\n",
"embeddings = Embeddings(path=\"sentence-transformers/nli-mpnet-base-v2\", content=True)\n",
"\n",
"# Create an index for the list of text\n",
"embeddings.index([(uid, text, None) for uid, text in enumerate(data)])\n",
"embeddings.index(data)\n",
"\n",
"# Run a search\n",
"embeddings.search(\"feel good story\", 1)"
],
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine man wins $1M from $25 lottery ticket'}]"
]
},
"metadata": {},
"execution_count": 30
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QTee7YMNDD4R"
},
"source": [
"# Query translation models\n",
"\n",
"Next we'll explore how query translation models work with examples. "
],
"metadata": {
"id": "QTee7YMNDD4R"
}
]
},
{
"cell_type": "code",
"source": [
"from txtai.pipeline import Sequences\n",
"\n",
"sequences = Sequences(\"NeuML/t5-small-txtsql\")\n",
"\n",
"queries = [\n",
" \"feel good story\",\n",
" \"feel good story since yesterday\",\n",
" \"feel good story with lottery in text\",\n",
" \"how many feel good story\",\n",
" \"feel good story translated to fr\",\n",
" \"feel good story summarized\"\n",
"]\n",
"\n",
"# Prefix to pass to T5 model\n",
"prefix = \"translate English to SQL: \"\n",
"\n",
"for query in queries:\n",
" print(f\"Input: {query}\")\n",
" print(f\"SQL: {sequences(query, prefix)}\")\n",
" print()\n"
],
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -174,11 +129,10 @@
"id": "04iOgP_ojSfK",
"outputId": "41e73130-75e6-4ae9-b690-685972a13565"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"Input: feel good story\n",
"SQL: select id, text, score from txtai where similar('feel good story')\n",
@@ -186,8 +140,8 @@
"Input: feel good story since yesterday\n",
"SQL: select id, text, score from txtai where similar('feel good story') and entry >= date('now', '-1 day')\n",
"\n",
"Input: feel good story with lottery in text\n",
"SQL: select id, text, score from txtai where similar('feel good story') and text like '% lottery%'\n",
"Input: feel good story with 'lottery' in text\n",
"SQL: select id, text, score from txtai where similar('feel good story') and text like '%lottery%'\n",
"\n",
"Input: how many feel good story\n",
"SQL: select count(*) from txtai where similar('feel good story')\n",
@@ -200,32 +154,73 @@
"\n"
]
}
],
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(\"NeuML/t5-small-txtsql\", template=\"translate English to SQL: {text}\")\n",
"\n",
"queries = [\n",
" \"feel good story\",\n",
" \"feel good story since yesterday\",\n",
" \"feel good story with 'lottery' in text\",\n",
" \"how many feel good story\",\n",
" \"feel good story translated to fr\",\n",
" \"feel good story summarized\"\n",
"]\n",
"\n",
"for query in queries:\n",
" print(f\"Input: {query}\")\n",
" print(f\"SQL: {llm(query)}\")\n",
" print()\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rAnEMaiWlOXm"
},
"source": [
"Looking at the query translations above gives an idea on how this model works.\n",
"\n",
"[t5-small-txtsql](https://huggingface.co/NeuML/t5-small-txtsql) is the default model. Custom domain query syntax languages can be created using this same methodology, including for other languages. Natural language can be translated to functions, query clauses, column selection and more!"
],
"metadata": {
"id": "rAnEMaiWlOXm"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "P9hOcgNfjSyL"
},
"source": [
"# Natural language filtering\n",
"\n",
"Now it's time for this in action! Let's first initialize the embeddings index with the appropriate settings."
],
"metadata": {
"id": "P9hOcgNfjSyL"
}
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "L2DDJrd0RAaN",
"outputId": "c60bfc29-187b-4926-8656-04063b2ca85c"
},
"outputs": [
{
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329025655984879,\n",
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket'}"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from txtai.pipeline import Translation\n",
"\n",
@@ -235,56 +230,34 @@
"translation = Translation()\n",
"\n",
"# Create embeddings index with content enabled. The default behavior is to only store indexed vectors.\n",
"embeddings = Embeddings({\"path\": \"sentence-transformers/nli-mpnet-base-v2\",\n",
" \"content\": True,\n",
" \"query\": {\"path\": \"NeuML/t5-small-txtsql\"},\n",
" \"functions\": [translate]})\n",
"embeddings = Embeddings(\n",
" path=\"sentence-transformers/nli-mpnet-base-v2\",\n",
" content=True,\n",
" query={\"path\": \"NeuML/t5-small-txtsql\"},\n",
" functions=[translate]\n",
")\n",
"\n",
"# Create an index for the list of text\n",
"embeddings.index([(uid, text, None) for uid, text in enumerate(data)])\n",
"embeddings.index(data)\n",
"\n",
"query = \"select id, score, translate(text, 'de') 'text' from txtai where similar('feel good story')\"\n",
"\n",
"# Run a search using a custom SQL function\n",
"embeddings.search(query)[0]"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "L2DDJrd0RAaN",
"outputId": "c60bfc29-187b-4926-8656-04063b2ca85c"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket'}"
]
},
"metadata": {},
"execution_count": 32
}
]
},
{
"cell_type": "markdown",
"source": [
"Note how the query model was provided as a embeddings index configuration parameter. Custom SQL functions were also added in. Let's now see if the same SQL statement can be run with a natural language query."
],
"metadata": {
"id": "MNd7QmFmnh-f"
}
},
"source": [
"Note how the query model was provided as a embeddings index configuration parameter. Custom SQL functions were also added in. Let's now see if the same SQL statement can be run with a natural language query."
]
},
{
"cell_type": "code",
"source": [
"embeddings.search(\"feel good story translated to de\")[0]"
],
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -292,36 +265,36 @@
"id": "mnGSBNMonur2",
"outputId": "dc14d898-b46f-42e6-88e0-434863cc15d6"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket'}"
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket',\n",
" 'score': 0.08329025655984879}"
]
},
"execution_count": 4,
"metadata": {},
"execution_count": 33
"output_type": "execute_result"
}
],
"source": [
"embeddings.search(\"feel good story translated to de\")[0]"
]
},
{
"cell_type": "markdown",
"source": [
"Same result. Let's try a few more."
],
"metadata": {
"id": "OnmVUK2DoZkh"
}
},
"source": [
"Same result. Let's try a few more."
]
},
{
"cell_type": "code",
"source": [
"embeddings.search(\"feel good story since yesterday\")[0]"
],
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -329,27 +302,27 @@
"id": "Js2b_M61oitg",
"outputId": "fab080cb-d082-4cf3-8314-12d23acc3c02"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine man wins $1M from $25 lottery ticket'}"
" 'text': 'Maine man wins $1M from $25 lottery ticket',\n",
" 'score': 0.08329025655984879}"
]
},
"execution_count": 5,
"metadata": {},
"execution_count": 34
"output_type": "execute_result"
}
],
"source": [
"embeddings.search(\"feel good story since yesterday\")[0]"
]
},
{
"cell_type": "code",
"source": [
"embeddings.search(\"feel good story with lottery in text\")[0]"
],
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -357,36 +330,36 @@
"id": "pcxPgriwomWv",
"outputId": "7e71dd09-7c4f-4147-ba9e-47a45c1cf90f"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine man wins $1M from $25 lottery ticket'}"
"[{'id': '4',\n",
" 'text': 'Maine man wins $1M from $25 lottery ticket',\n",
" 'score': 0.08329025655984879}]"
]
},
"execution_count": 6,
"metadata": {},
"execution_count": 35
"output_type": "execute_result"
}
],
"source": [
"embeddings.search(\"feel good story with 'lottery' in text\")"
]
},
{
"cell_type": "markdown",
"source": [
"For good measure, a couple queries with filters that return no results."
],
"metadata": {
"id": "1ob4Q_CLpGBm"
}
},
"source": [
"For good measure, a couple queries with filters that return no results."
]
},
{
"cell_type": "code",
"source": [
"embeddings.search(\"feel good story with missing in text\")"
],
"execution_count": 7,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -394,25 +367,25 @@
"id": "LMaf7JJzonAC",
"outputId": "71080bd1-2d9e-41ba-9501-2cdedaf26d6d"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 7,
"metadata": {},
"execution_count": 36
"output_type": "execute_result"
}
],
"source": [
"embeddings.search(\"feel good story with missing in text\")"
]
},
{
"cell_type": "code",
"source": [
"embeddings.search(\"feel good story with field equal 14\")"
],
"execution_count": 8,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -420,33 +393,57 @@
"id": "ADFNLhvto_0J",
"outputId": "12e08ea8-7203-4fb0-cb84-1133b5db9dc0"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 8,
"metadata": {},
"execution_count": 37
"output_type": "execute_result"
}
],
"source": [
"embeddings.search(\"feel good story with field equal 14\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mTT8nopiRdVH"
},
"source": [
"# Query translation with applications\n",
"\n",
"Of course this is all available with YAML-configured applications."
],
"metadata": {
"id": "mTT8nopiRdVH"
}
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "FZ_7G6M4RUbz",
"outputId": "b00ce1c2-8df2-4289-8d03-991174a0e74f"
},
"outputs": [
{
"data": {
"text/plain": [
"{'id': '4',\n",
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket',\n",
" 'score': 0.08329025655984879}"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"config = \"\"\"\n",
"translation:\n",
@@ -470,28 +467,6 @@
"\n",
"# Run search query\n",
"app.search(\"feel good story translated to de\")[0]"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "FZ_7G6M4RUbz",
"outputId": "b00ce1c2-8df2-4289-8d03-991174a0e74f"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"{'id': '4',\n",
" 'score': 0.08329011499881744,\n",
" 'text': 'Maine Mann gewinnt $1M von $25 Lotterie-Ticket'}"
]
},
"metadata": {},
"execution_count": 38
}
]
},
{
@@ -505,5 +480,29 @@
"This notebook introduced natural language filtering with query translation models. This powerful feature adds filtering and pipelines to natural language statements. Custom domain-specific query languages can be created to enable rich queries natively in txtai."
]
}
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+164 -307
View File
@@ -1,17 +1,4 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU",
"gpuClass": "standard"
},
"cells": [
{
"cell_type": "markdown",
@@ -44,15 +31,15 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "LPQTb25tASIG"
},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai datasets"
],
"execution_count": null,
"outputs": []
]
},
{
"cell_type": "markdown",
@@ -71,32 +58,65 @@
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "OUc9gqTyAYnm"
},
"outputs": [],
"source": [
"%%capture\n",
"\n",
"from txtai import Embeddings, RAG\n",
"\n",
"# Create embeddings model with content support\n",
"embeddings = Embeddings({\"path\": \"sentence-transformers/all-MiniLM-L6-v2\", \"content\": True})\n",
"embeddings = Embeddings(path=\"sentence-transformers/all-MiniLM-L6-v2\", content=True)\n",
"\n",
"# Create RAG instance\n",
"rag = RAG(embeddings, \"google/flan-t5-base\")"
],
"execution_count": null,
"outputs": []
"# Create the RAG pipeline\n",
"rag = RAG(embeddings, \"Qwen/Qwen3-4B-Instruct-2507\", template=\"\"\"\n",
" Answer the following question using the provided context.\n",
"\n",
" Question:\n",
" {question}\n",
"\n",
" Context:\n",
" {context}\n",
"\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "4X5z3UjnAGe7",
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4X5z3UjnAGe7",
"outputId": "cacb7e9d-471a-437d-c68d-a8b51f876413"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"---- Red Sox - Blue Jays ----\n",
"{'answer': 'The Blue Jays won the game.'}\n",
"{'answer': 'The score was 2-1 in favor of the Blue Jays.'}\n",
"\n",
"---- Phillies - Braves ----\n",
"{'answer': 'The Phillies won the game.'}\n",
"{'answer': 'The score was 5-0 in favor of the Phillies.'}\n",
"\n",
"---- Dodgers - Giants ----\n",
"{'answer': 'The Giants won the game.'}\n",
"{'answer': 'The score was Giants 5, Dodgers 4.'}\n",
"\n",
"---- Flyers - Lightning ----\n",
"{'answer': 'The Flyers won the game.'}\n",
"{'answer': 'The score was Flyers 4, Lightning 1.'}\n",
"\n"
]
}
],
"source": [
"data = [\"Giants hit 3 HRs to down Dodgers\",\n",
" \"Giants 5 Dodgers 4 final\",\n",
@@ -111,88 +131,40 @@
" \"Flyers 4 Lightning 1 final\",\n",
" \"Flyers win 4-1\"]\n",
"\n",
"def prompt(question):\n",
" return f\"\"\"\n",
" Answer the following question using the context below.\n",
" Question: {question}\n",
" Context:\n",
" \"\"\"\n",
"\n",
"questions = [\"What team won the game?\", \"What was score?\"]\n",
"\n",
"execute = lambda query: rag([(question, query, prompt(question), False) for question in questions], data)\n",
"\n",
"for query in [\"Red Sox - Blue Jays\", \"Phillies - Braves\", \"Dodgers - Giants\", \"Flyers - Lightning\"]:\n",
" print(\"----\", query, \"----\")\n",
" for answer in execute(query):\n",
" for answer in rag([f\"{query} {x}\" for x in questions], data):\n",
" print(answer)\n",
" print()"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"---- Red Sox - Blue Jays ----\n",
"('What team won the game?', 'Blue Jays')\n",
"('What was score?', '2-1')\n",
"\n",
"---- Phillies - Braves ----\n",
"('What team won the game?', 'Phillies')\n",
"('What was score?', '5-0')\n",
"\n",
"---- Dodgers - Giants ----\n",
"('What team won the game?', 'Giants')\n",
"('What was score?', '5-4')\n",
"\n",
"---- Flyers - Lightning ----\n",
"('What team won the game?', 'Flyers')\n",
"('What was score?', '4-1')\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7AnPvSeM3N1Z"
},
"source": [
"This code runs a series of questions. First it runs an embeddings filtering query to find the most relevant text. For example, `Red Sox - Blue Jays` finds text related to those teams. Then `What team won the game?` and `What was the score?` are asked.\n",
"\n",
"This logic is the same logic found in Notebook 5 - Extractive QA with txtai but uses prompt-based QA vs extractive QA. "
],
"metadata": {
"id": "7AnPvSeM3N1Z"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Aj8GoDk331cS"
},
"source": [
"# Embeddings-guided and Prompt-driven Search\n",
"\n",
"Now for the fun stuff. Let's build an embeddings index for the `ag_news` dataset (a set of news stories from the mid 2000s). Then we'll use prompts to ask questions with embeddings results as the context."
],
"metadata": {
"id": "Aj8GoDk331cS"
}
]
},
{
"cell_type": "code",
"source": [
"from datasets import load_dataset\n",
"\n",
"dataset = load_dataset(\"ag_news\", split=\"train\")\n",
"\n",
"# List of all text elements\n",
"texts = dataset[\"text\"]\n",
"\n",
"# Create an embeddings index over the dataset\n",
"embeddings = Embeddings({\"path\": \"sentence-transformers/all-MiniLM-L6-v2\", \"content\": True})\n",
"embeddings.index((x, text, None) for x, text in enumerate(texts))\n",
"\n",
"# Create RAG instance\n",
"rag = RAG(embeddings, \"google/flan-t5-large\")"
],
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -200,40 +172,41 @@
"id": "yL716oEZ43t-",
"outputId": "23f4b0e7-a60a-4e89-fb57-06966e6612f8"
},
"execution_count": null,
"outputs": []
"outputs": [
],
"source": [
"from datasets import load_dataset\n",
"\n",
"dataset = load_dataset(\"ag_news\", split=\"train\")\n",
"\n",
"# Create an embeddings index over the dataset\n",
"embeddings = Embeddings(path=\"sentence-transformers/all-MiniLM-L6-v2\", content=True)\n",
"embeddings.index(dataset[\"text\"])\n",
"\n",
"# Create RAG instance\n",
"rag = RAG(embeddings, \"Qwen/Qwen3-4B-Instruct-2507\", template=\"\"\"\n",
" Answer the following question using the provided context.\n",
"\n",
" Question:\n",
" {question}\n",
"\n",
" Context:\n",
" {context}\n",
"\"\"\", output=\"flatten\")"
]
},
{
"cell_type": "markdown",
"source": [
"Now let's run a prompt-driven search!"
],
"metadata": {
"id": "Ifl8JwLDBL7k"
}
},
"source": [
"Now let's run a prompt-driven search!"
]
},
{
"cell_type": "code",
"source": [
"def prompt(question):\n",
" return f\"\"\"Answer the following question using only the context below. Say 'no answer' when the question can't be answered.\n",
"Question: {question}\n",
"Context: \"\"\"\n",
"\n",
"def search(query, question=None):\n",
" # Default question to query if empty\n",
" if not question:\n",
" question = query\n",
"\n",
" return rag([(\"answer\", query, prompt(question), False)])[0][1]\n",
"\n",
"question = \"Who won the 2004 presidential election?\"\n",
"answer = search(question)\n",
"print(question, answer)\n",
"\n",
"nquestion = \"Who did the candidate beat?\"\n",
"print(nquestion, search(f\"{question} {answer}. {nquestion}\"))"
],
"execution_count": 22,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -241,91 +214,52 @@
"id": "5O1WBJ8153Mo",
"outputId": "ddf09da2-7d4c-4fd3-b0da-df5631bacd13"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"Who won the 2004 presidential election? George W. Bush\n",
"Who did the candidate beat? John F. Kerry\n"
"Who won the 2004 presidential election? George W. Bush won the 2004 presidential election.\n",
"Who did the candidate beat? George W. Bush beat John F. Kerry in the 2004 presidential election.\n"
]
}
],
"source": [
"question = \"Who won the 2004 presidential election?\"\n",
"answer = rag(question)\n",
"print(question, answer)\n",
"\n",
"nquestion = \"Who did the candidate beat?\"\n",
"print(nquestion, rag(f\"{question} {answer}. {nquestion}\"))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "AhViFXH_BZSo"
},
"source": [
"And there are the answers. Let's unpack how this works.\n",
"\n",
"The first thing the RAG pipeline does is run an embeddings search to find the most relevant text within the index. A context string is then built using those search results.\n",
"\n",
"After that, a prompt is generated, run and the answer printed. Let's see what a full prompt looks like."
],
"metadata": {
"id": "AhViFXH_BZSo"
}
},
{
"cell_type": "code",
"source": [
"text = prompt(question)\n",
"text += \"\\n\" + \"\\n\".join(x[\"text\"]for x in embeddings.search(question))\n",
"print(text)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "h7BsoJC3CFOq",
"outputId": "44ae0dec-4f79-4d44-88f5-585e5eae9cb2"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Answer the following question using only the context below. Say 'no answer' when the question can't be answered.\n",
"Question: Who won the 2004 presidential election?\n",
"Context: \n",
"Right- and left-click politics The 2004 presidential race ended last week in a stunning defeat for Massachusetts Senator John F. Kerry, as incumbent President George W. Bush cruised to an easy victory.\n",
"2004 Presidential Endorsements (AP) AP - Newspaper endorsements in the 2004 presidential campaign between President Bush, a Republican, and Sen. John Kerry, a Democrat.\n",
"Presidential Campaign to Nov. 2, 2004 (Reuters) Reuters - The following diary of events\\leading up to the presidential election on Nov. 2.\n"
]
}
"After that, a prompt is generated, run and the answer printed."
]
},
{
"cell_type": "markdown",
"source": [
"The prompt has the information needed to determine the answers to the questions."
],
"metadata": {
"id": "4m9XketCty3m"
}
},
{
"cell_type": "markdown",
"id": "JtDcVPdOB0Rv"
},
"source": [
"# Additional examples\n",
"\n",
"Before moving on, a couple more example questions."
],
"metadata": {
"id": "JtDcVPdOB0Rv"
}
]
},
{
"cell_type": "code",
"source": [
"question = \"Who won the World Series in 2004?\"\n",
"answer = search(question)\n",
"print(question, answer)\n",
"\n",
"nquestion = \"Who did they beat?\"\n",
"print(nquestion, search(f\"{question} {answer}. {nquestion}\"))"
],
"execution_count": 23,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -333,23 +267,28 @@
"id": "0NNLBwC-83MM",
"outputId": "4b9fabd7-baf9-4f7d-bb8b-c9c60c5101e4"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"Who won the World Series in 2004? Boston\n",
"Who did they beat? St Louis\n"
"Who won the World Series in 2004? The Boston Red Sox won the World Series in 2004.\n",
"What team did the Red Sox beat in the World Series? The Boston Red Sox beat the St. Louis Cardinals in the World Series.\n"
]
}
],
"source": [
"question = \"Who won the World Series in 2004?\"\n",
"answer = rag(question)\n",
"print(question, answer)\n",
"\n",
"nquestion = \"What team did the Red Sox beat in the World Series?\"\n",
"print(nquestion, rag(f\"{question} {answer}. {nquestion}\"))"
]
},
{
"cell_type": "code",
"source": [
"search(\"Tell me something interesting?\")"
],
"execution_count": 29,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
@@ -358,43 +297,36 @@
"id": "1P0zqkTW9cZW",
"outputId": "4f2232db-761b-464f-b47d-6695c84ffb80"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'herrings communicate by farting'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
"'An interesting fact is that herrings communicate by farting—a quirky and unusual discovery that was honored with an Ig Nobel Prize for its oddball research.'"
]
},
"execution_count": 29,
"metadata": {},
"execution_count": 8
"output_type": "execute_result"
}
],
"source": [
"rag(\"Tell me something interesting\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ygFFcwWPGI9p"
},
"source": [
"Whhaaaattt??? Is this a model hallucination?\n",
"\n",
"Let's run an embeddings query and see if that text is in the results."
],
"metadata": {
"id": "ygFFcwWPGI9p"
}
]
},
{
"cell_type": "code",
"source": [
"answer = \"herrings communicate by farting\"\n",
"for x in embeddings.search(\"Tell me something interesting?\"):\n",
" if answer in x[\"text\"]:\n",
" start = x[\"text\"].find(answer)\n",
" print(x[\"text\"][start:start + len(answer)])"
],
"execution_count": 28,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -402,143 +334,68 @@
"id": "qZPhLqSxGMbK",
"outputId": "e3b2909a-1ee8-480f-afa3-201a8e27cb08"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"herrings communicate by farting\n"
]
}
],
"source": [
"answer = \"herrings communicate by farting\"\n",
"for x in embeddings.search(\"Tell me something interesting\"):\n",
" if answer in x[\"text\"]:\n",
" start = x[\"text\"].find(answer)\n",
" print(x[\"text\"][start:start + len(answer)])"
]
},
{
"cell_type": "markdown",
"source": [
"Sure enough it is. It appears that the FLAN-T5 model has a bit of an immature sense of humor 😃"
],
"metadata": {
"id": "IpgxMc1DZcds"
}
},
{
"cell_type": "markdown",
"source": [
"# External API Integration\n",
"\n",
"In addition to support for Hugging Face models, the RAG pipeline also supports custom question-answer models. This could be a call to the OpenAI API (GPT-3), Cohere API, Hugging Face API or using langchain to manage that. All that is needed is a Callable object or a function!\n",
"\n",
"Let's see an example that uses the Hugging Face API to answer questions. We'll use the original sports dataset to demonstrate."
],
"metadata": {
"id": "7bitjzeyYOqh"
}
},
{
"cell_type": "code",
"source": [
"import requests\n",
"\n",
"data = [\"Giants hit 3 HRs to down Dodgers\",\n",
" \"Giants 5 Dodgers 4 final\",\n",
" \"Dodgers drop Game 2 against the Giants, 5-4\",\n",
" \"Blue Jays beat Red Sox final score 2-1\",\n",
" \"Red Sox lost to the Blue Jays, 2-1\",\n",
" \"Blue Jays at Red Sox is over. Score: 2-1\",\n",
" \"Phillies win over the Braves, 5-0\",\n",
" \"Phillies 5 Braves 0 final\",\n",
" \"Final: Braves lose to the Phillies in the series opener, 5-0\",\n",
" \"Lightning goaltender pulled, lose to Flyers 4-1\",\n",
" \"Flyers 4 Lightning 1 final\",\n",
" \"Flyers win 4-1\"]\n",
"\n",
"def prompt(question):\n",
" return f\"\"\"\n",
" Answer the following question using the context below.\n",
" Question: {question}\n",
" Context:\n",
" \"\"\"\n",
"\n",
"# Submits a series of prompts to the Hugging Face API.\n",
"# This call can easily be switched to use the OpenAI API (GPT-3), Cohere API or a library like langchain.\n",
"def api(prompts):\n",
" response = requests.post(\"https://api-inference.huggingface.co/models/google/flan-t5-base\",\n",
" json={\"inputs\": prompts})\n",
"\n",
" return [x[\"generated_text\"] for x in response.json()]\n",
"\n",
"# Create embeddings model with content support\n",
"embeddings = Embeddings({\"path\": \"sentence-transformers/all-MiniLM-L6-v2\", \"content\": True})\n",
"\n",
"# Create RAG instance, submit prompts to the Hugging Face inference API\n",
"rag = RAG(embeddings, api)\n",
"\n",
"questions = [\"What team won the game?\", \"What was score?\"]\n",
"\n",
"execute = lambda query: rag([(question, query, prompt(question), False) for question in questions], data)\n",
"\n",
"for query in [\"Red Sox - Blue Jays\", \"Phillies - Braves\", \"Dodgers - Giants\", \"Flyers - Lightning\"]:\n",
" print(\"----\", query, \"----\")\n",
" for answer in execute(query):\n",
" print(answer)\n",
" print()\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "yYAa9N7EYm7E",
"outputId": "72208327-bfb7-466f-c664-3630f207b6dd"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"---- Red Sox - Blue Jays ----\n",
"('What team won the game?', 'Blue Jays')\n",
"('What was score?', '2-1')\n",
"\n",
"---- Phillies - Braves ----\n",
"('What team won the game?', 'Phillies')\n",
"('What was score?', '5-0')\n",
"\n",
"---- Dodgers - Giants ----\n",
"('What team won the game?', 'Giants')\n",
"('What was score?', '5-4')\n",
"\n",
"---- Flyers - Lightning ----\n",
"('What team won the game?', 'Flyers')\n",
"('What was score?', '4-1')\n",
"\n"
]
}
"source": [
"Sure enough it is 😃"
]
},
{
"cell_type": "markdown",
"source": [
"Everything matches with first example above in [Create Embeddings and RAG instances](#Create-Embeddings-and-RAG-instances) except the prompts are run as an external API call.\n",
"\n",
"The Embeddings instance can also swap out the vectorization, database and vector store components with external API services. Check out the [txtai documentation](https://neuml.github.io/txtai/embeddings/configuration/) documentation for more information.\n",
"\n"
],
"metadata": {
"id": "Xh8UhC3NdsGf"
}
},
{
"cell_type": "markdown",
"id": "KqfvCXp2B3li"
},
"source": [
"# Wrapping up\n",
"\n",
"This notebook covered how to run embeddings-guided and prompt-driven search with LLMs. This functionality is a major step forward towards `Generative Semantic Search` for txtai. More to come, stay tuned!"
],
"metadata": {
"id": "KqfvCXp2B3li"
}
]
}
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"provenance": []
},
"gpuClass": "standard",
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+179 -169
View File
@@ -1,17 +1,4 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU",
"gpuClass": "standard"
},
"cells": [
{
"cell_type": "markdown",
@@ -41,15 +28,15 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "LPQTb25tASIG"
},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api]"
],
"execution_count": null,
"outputs": []
]
},
{
"cell_type": "markdown",
@@ -61,36 +48,46 @@
"\n",
"First, we'll look at building a workflow with a series of model prompts. This workflow creates a conditional translation using a statement and target language. Another task reads that output text and detects the language.\n",
"\n",
"This workflow uses a sequences pipeline. The sequences pipeline loads a Hugging Face sequence to sequence model for inference, in this case [FLAN-T5](https://huggingface.co/google/flan-t5-base). The sequences pipeline takes a prompt as input and outputs the model inference result.\n",
"This workflow uses a LLM pipeline. The LLM pipeline loads a local model for inference, in this case [Qwen3-4B-Instruct-2507](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507). The [LLM pipeline](https://neuml.github.io/txtai/pipeline/llm/llm) supports local transformers models, llama.cpp models and LLM APIs such as Ollama, vLLM, OpenAI, Claude etc. \n",
"\n",
"It's important to note that a pipeline is simply a callable function. It can easily be replaced with a call to an external API."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "OUc9gqTyAYnm",
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "OUc9gqTyAYnm",
"outputId": "83300311-736c-47c8-bc16-ec0303274054"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['French', 'German']\n"
]
}
],
"source": [
"from txtai.pipeline import Sequences\n",
"from txtai.workflow import Workflow, TemplateTask\n",
"from txtai import LLM, Workflow\n",
"from txtai.workflow import TemplateTask\n",
"\n",
"# Create sequences pipeline\n",
"sequences = Sequences(\"google/flan-t5-large\")\n",
"# Create LLM\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"# Define workflow or chaining of tasks together.\n",
"workflow = Workflow([\n",
" TemplateTask(\n",
" template=\"Translate '{statement}' to {language} if it's English\",\n",
" action=sequences\n",
" template=\"Translate text '{statement}' to {language} if the text is English, otherwise keep the original text\",\n",
" action=llm\n",
" ),\n",
" TemplateTask(\n",
" template=\"What language is the following text? {text}\",\n",
" action=sequences\n",
" template=\"What language is the following text. Only print the answer? {text}\",\n",
" action=llm\n",
" )\n",
"])\n",
"\n",
@@ -100,20 +97,13 @@
"]\n",
"\n",
"print(list(workflow(inputs)))"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"['French', 'German']\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_zz4Do8BV-Lk"
},
"source": [
"Let's recap what happened here. The first workflow task conditionally translates text to a language if it's English.\n",
"\n",
@@ -122,40 +112,22 @@
"The second statement is German, so it's not converted to French.\n",
"\n",
"The next step asks the model what the language is and it correctly prints `French` and `German`."
],
"metadata": {
"id": "_zz4Do8BV-Lk"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iXDAKP4CX0W9"
},
"source": [
"# Prompt Workflow as YAML\n",
"\n",
"The same workflow above can be created with YAML configuration."
],
"metadata": {
"id": "iXDAKP4CX0W9"
}
]
},
{
"cell_type": "code",
"source": [
"%%writefile workflow.yml\n",
"\n",
"sequences:\n",
" path: google/flan-t5-large\n",
"\n",
"workflow:\n",
" chain:\n",
" tasks:\n",
" - task: template\n",
" template: Translate '{statement}' to {language} if it's English\n",
" action: sequences\n",
" - task: template\n",
" template: What language is the following text? {text}\n",
" action: sequences"
],
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -163,25 +135,35 @@
"id": "GwV5A9xRYtYs",
"outputId": "ffe6ee65-95a7-46c6-e6b9-5324eab26ca8"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"Writing workflow.yml\n"
]
}
],
"source": [
"%%writefile workflow.yml\n",
"\n",
"llm:\n",
" path: Qwen/Qwen3-4B-Instruct-2507\n",
"\n",
"workflow:\n",
" chain:\n",
" tasks:\n",
" - task: template\n",
" template: Translate text '{statement}' to {language} if the text is English, otherwise keep the original text\n",
" action: llm\n",
" - task: template\n",
" template: What language is the following text. Only print the answer? {text}\n",
" action: llm"
]
},
{
"cell_type": "code",
"source": [
"from txtai import Application\n",
"\n",
"app = Application(\"workflow.yml\")\n",
"print(list(app.workflow(\"chain\", inputs)))"
],
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -189,58 +171,58 @@
"id": "dr7Lv5S5X98e",
"outputId": "d6ac0427-671d-4525-aa21-664430109af3"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"['French', 'German']\n"
]
}
],
"source": [
"from txtai import Application\n",
"\n",
"app = Application(\"workflow.yml\")\n",
"print(list(app.workflow(\"chain\", inputs)))"
]
},
{
"cell_type": "markdown",
"source": [
"As expected, the same result! This is a matter of preference on how you want to create a workflow. One advantage of YAML workflows is that an API can easily be created from the workflow file."
],
"metadata": {
"id": "EGqiV45fYVse"
}
},
"source": [
"As expected, the same result! This is a matter of preference on how you want to create a workflow. One advantage of YAML workflows is that an API can easily be created from the workflow file."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9PqMU0bNYinf"
},
"source": [
"# Prompt Workflow via an API call\n",
"\n",
"Let's say you want the workflow to be available via an API call. Well good news, txtai has a built in API mechanism using FastAPI. "
],
"metadata": {
"id": "9PqMU0bNYinf"
}
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "vDxQj1ZIYsz3"
},
"outputs": [],
"source": [
"# Start an API service\n",
"!CONFIG=workflow.yml nohup uvicorn \"txtai.api:app\" &> api.log &\n",
"!sleep 60"
],
"metadata": {
"id": "vDxQj1ZIYsz3"
},
"execution_count": null,
"outputs": []
]
},
{
"cell_type": "code",
"source": [
"import requests\n",
"\n",
"# Run API request\n",
"requests.post(\"http://localhost:8000/workflow\", json={\"name\": \"chain\", \"elements\": inputs}).json()"
],
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -248,31 +230,53 @@
"id": "R1o08SVtZW7h",
"outputId": "99875acd-18a8-4c2c-ead3-cb6975a4b2d2"
},
"execution_count": null,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['French', 'German']"
]
},
"execution_count": 3,
"metadata": {},
"execution_count": 5
"output_type": "execute_result"
}
],
"source": [
"import requests\n",
"\n",
"# Run API request\n",
"requests.post(\"http://localhost:8000/workflow\", json={\"name\": \"chain\", \"elements\": inputs}).json()"
]
},
{
"cell_type": "markdown",
"source": [
"Just like the previous steps, except through an API call. Let's run via cURL for good measure."
],
"metadata": {
"id": "B88mCrGFl5W-"
}
},
"source": [
"Just like the previous steps, except through an API call. Let's run via cURL for good measure."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hRUyh0cQl_P2",
"outputId": "9db8481d-0b6e-4a31-bdf6-5443df5f768a"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[\"French\",\"German\"]"
]
}
],
"source": [
"%%bash\n",
"\n",
@@ -287,51 +291,51 @@
" ]\n",
"}\n",
"EOF"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hRUyh0cQl_P2",
"outputId": "9db8481d-0b6e-4a31-bdf6-5443df5f768a"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[\"French\",\"German\"]"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W0zL93WPoaCo"
},
"source": [
"One last time, the same output is shown.\n",
"\n",
"If your primary development environment isn't Python, txtai does have API bindings for [JavaScript](https://github.com/neuml/txtai.js), [Rust](https://github.com/neuml/txtai.rs), [Go](https://github.com/neuml/txtai.go) and [Java](https://github.com/neuml/txtai.java).\n",
"\n",
"More information on the API is available [here](https://neuml.github.io/txtai/api/)."
],
"metadata": {
"id": "W0zL93WPoaCo"
}
]
},
{
"cell_type": "markdown",
"source": [
"# Conversational chain\n",
"\n",
"Conversational search is another big area of focus in 2023. [txtchat](https://github.com/neuml/txtchat) is a framework for building conversational search applications. It relies heavily on txtai. Let's see a conversational example."
],
"metadata": {
"id": "q9WiFG6fpzw5"
}
},
"source": [
"# Chat with your data\n",
"\n",
"\"Chat with your data\" is a popular entry point into the AI space. Let's run an example."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "rM3Y551LqF-J",
"outputId": "85623785-c15f-4996-9460-0644f69cf5bf"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Writing search.yml\n"
]
}
],
"source": [
"%%writefile search.yml\n",
"\n",
@@ -341,48 +345,27 @@
" container: neuml/txtai-intro\n",
"\n",
"rag:\n",
" path: google/flan-t5-large\n",
" path: Qwen/Qwen3-4B-Instruct-2507\n",
" output: reference\n",
" template: |\n",
" Answer the following question using only the context below.\n",
"\n",
" Question: {question}\n",
" Context: {context}\n",
"\n",
"workflow:\n",
" search:\n",
" tasks:\n",
" - task: rag\n",
" template: |\n",
" Answer the following question using only the context below. Give a detailed answer.\n",
" Say 'I don't have data on that' when the question can't be answered.\n",
" Question: {text}\n",
" Context: \n",
" action: rag\n",
" - action: rag\n",
" - task: template\n",
" template: \"{answer}\\n\\nReference: {reference}\"\n",
" rules:\n",
" answer: I don't have data on that"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "rM3Y551LqF-J",
"outputId": "85623785-c15f-4996-9460-0644f69cf5bf"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Overwriting search.yml\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"app = Application(\"search.yml\")\n",
"print(list(app.workflow(\"search\", [\"Tell me something about North America\"])))"
],
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -390,40 +373,67 @@
"id": "1Elb8JANqpwX",
"outputId": "b1f1ffa1-6c47-4d90-b6f1-8098d4dc45f8"
},
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"[\"Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg\\n\\nReference: 1\"]\n"
"[\"Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg.\\n\\nReference: 1\"]\n"
]
}
],
"source": [
"app = Application(\"search.yml\")\n",
"print(list(app.workflow(\"search\", [\"Find something about North America\"])))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4r49V4c9s5nf"
},
"source": [
"The first thing the code above does is run an embeddings search to build a conversational context. That context is then used to build a prompt and inference is run against the LLM. \n",
"\n",
"The next task formats the outputs with a reference to the best matching record. In this case, it's only an id of 1. But this can be much more useful if the id is a URL or there is logic to format the id back to a unique reference string.\n",
"\n",
"The [txtchat](https://github.com/neuml/txtchat) project has much more on this, check it out!"
],
"metadata": {
"id": "4r49V4c9s5nf"
}
"The next task formats the outputs with a reference to the best matching record. In this case, it's only an id of 1. But this can be much more useful if the id is a URL or there is logic to format the id back to a unique reference string."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KqfvCXp2B3li"
},
"source": [
"# Wrapping up\n",
"\n",
"This notebook covered how to build prompt templates and task chains through a series of results. txtai has long had a robust and efficient workflow framework for connecting models together. This can be small and simple models and/or prompting with large models. Go ahead and give it a try!"
],
"metadata": {
"id": "KqfvCXp2B3li"
}
]
}
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"provenance": []
},
"gpuClass": "standard",
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+1 -2
View File
@@ -78,8 +78,7 @@
"\n",
"# LLM pipeline\n",
"llm:\n",
" path: google/flan-t5-large\n",
" torch_dtype: torch.bfloat16"
" path: Qwen/Qwen3-4B-Instruct-2507"
],
"metadata": {
"colab": {
+240 -271
View File
@@ -1,61 +1,45 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"gpuType": "T4"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "VGeVB8M41jqW"
},
"source": [
"# Build RAG pipelines with txtai\n",
"\n",
"Large Language Models (LLMs) have completely dominated the AI and machine learning space in 2023. The results have been amazing and the public imagination is almost endless.\n",
"Large Language Models (LLMs) have completely dominated the tech space in recent years. The results have been amazing and the public imagination is almost endless.\n",
"\n",
"While LLMs have been impressive, they are not problem free. The biggest challenge is with hallucinations. Hallucinations is the term for when a LLM generates output that is factually incorrect. The alarming part of this is that on a cursory glance, it actually sounds like good content. The default behavior of LLMs is to produce plausible answers even when no plausible answer exists. LLMs are not great at saying I don't know.\n",
"\n",
"Retrieval augmented generation (RAG) helps reduce the risk of hallucinations by limiting the context in which a LLM can generate answers. This is typically done with a vector search query that hydrates a prompt with a relevant context. RAG is one of the most practical and production-ready use cases for *Generative AI*. It's so popular now, that some are creating their entire companies around it.\n",
"\n",
"[txtai](https://github.com/neuml/txtai) has long had question-answering pipelines, which employ the same process of retrieving a relevant context. LLMs are now the preferred approach for analyzing that context and RAG pipelines are one of the main features of txtai. One of the other main features of txtai is that it's a vector database! You can build your prompts and limit your context all with one library. Hence the phrase *all-in-one embeddings database*.\n",
"[txtai](https://github.com/neuml/txtai) has long had question-answering pipelines, which employ the same process of retrieving a relevant context. LLMs are now the preferred approach for analyzing that context and RAG pipelines are one of the main features of txtai. One of the other main features of txtai is that it's a vector database! You can build your prompts and limit your context all with one library. Hence the phrase *all-in-one AI framework*.\n",
"\n",
"This notebook shows how to build RAG pipelines with txtai."
],
"metadata": {
"id": "VGeVB8M41jqW"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZQrHIw351lwE"
},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies. Since this notebook is using optional pipelines, we need to install the pipeline extras package."
],
"metadata": {
"id": "ZQrHIw351lwE"
}
]
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"id": "R0AqRP7v1hdr"
},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline] autoawq\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline]\n",
"\n",
"# Get test data\n",
"!wget -N https://github.com/neuml/txtai/releases/download/v6.2.0/tests.tar.gz\n",
@@ -68,50 +52,43 @@
},
{
"cell_type": "markdown",
"metadata": {
"id": "xmPN8RDF1pXd"
},
"source": [
"# Start with the basics\n",
"\n",
"Let's jump right in and start with a simple LLM pipeline. The [LLM pipeline](https://neuml.github.io/txtai/pipeline/text/llm/) supports local LLM models via [Hugging Face Transformers](https://github.com/huggingface/transformers) and [llama.cpp](https://github.com/abetlen/llama-cpp-python).\n",
"\n",
"The LLM pipeline also supports [API services (i.e. OpenAI, Claude, Bedrock etc) via LiteLLM](https://github.com/BerriAI/litellm). The LLM pipeline automatically detects the underlying LLM framework from the `path` parameter.\n"
],
"metadata": {
"id": "xmPN8RDF1pXd"
}
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "XZ7vPBIs1rGZ"
},
"outputs": [],
"source": [
"from txtai import LLM\n",
"\n",
"# Create LLM\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")"
],
"metadata": {
"id": "XZ7vPBIs1rGZ"
},
"execution_count": 21,
"outputs": []
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")"
]
},
{
"cell_type": "markdown",
"source": [
"Next, we'll load a document to query. The [Textractor pipeline](https://neuml.github.io/txtai/pipeline/data/textractor/) has support for extracting text from common document formats (docx, pdf, xlsx)."
],
"metadata": {
"id": "9rmTWMxAH3Vx"
}
},
"source": [
"Next, we'll load a document to query. The [Textractor pipeline](https://neuml.github.io/txtai/pipeline/data/textractor/) has support for extracting text from common document formats (docx, pdf, xlsx, web)."
]
},
{
"cell_type": "code",
"source": [
"from txtai.pipeline import Textractor\n",
"\n",
"# Create Textractor\n",
"textractor = Textractor()\n",
"text = textractor(\"txtai/document.docx\")\n",
"print(text)"
],
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -119,24 +96,24 @@
"id": "nifStGtOHuyc",
"outputId": "5a4010e0-75f9-4095-a24c-cd4c859847d0"
},
"execution_count": 22,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"txtai – the all-in-one embeddings database\n",
"# txtai – the all-in-one embeddings database\n",
"txtai is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Summary of txtai features:\n",
"· Vector search with SQL, object storage, topic modeling\n",
"· Create embeddings for text, documents, audio, images and video\n",
"· Pipelines powered by language models that run LLM prompts\n",
"· Workflows to join pipelines together and aggregate business logic\n",
"· Build with Python or YAML. API bindings available for JavaScript, Java, Rust and Go.\n",
"· Run local or scale out with container orchestration\n",
"· *Vector search* with SQL, object storage, topic modeling\n",
"· Create *embeddings* for text, documents, audio, images and video\n",
"· *Pipelines* powered by language models that run LLM prompts\n",
"· *Workflows* to join pipelines together and aggregate business logic\n",
"· Build with *Python* or *YAML* . API bindings available for JavaScript, Java, Rust and Go.\n",
"· *Run local or scale out with container orchestration* \n",
"\n",
"Examples\n",
"\n",
"## Examples\n",
"List of example notebooks.\n",
"|Notebook|Description|\n",
"|---|---|\n",
@@ -145,16 +122,17 @@
"|Build a QA database|Question matching with semantic search|\n",
"|Semantic Graphs|Explore topics, data connectivity and run network analysis|\n",
"\n",
"Install\n",
"## Install\n",
"The easiest way to install is via pip and PyPI\n",
"pip install txtai\n",
"Python 3.10+ is supported. Using a Python virtual environment is recommended.\n",
"Python 3.11+ is supported. Using a Python virtual environment is **recommended** .\n",
"See the detailed install instructions for more information covering optional dependencies, environment specific prerequisites, installing from source, conda support and how to run with containers.\n",
"\n",
"\n",
"\n",
"\n",
"Model guide\n",
"\n",
"## Model guide\n",
"The following shows a list of suggested models.\n",
"|Component|Model(s)|\n",
"|---|---|\n",
@@ -171,35 +149,28 @@
"|Translation|OPUS Model Series|\n"
]
}
],
"source": [
"from txtai import Textractor\n",
"\n",
"# Create Textractor\n",
"textractor = Textractor()\n",
"text = textractor(\"txtai/document.docx\")\n",
"print(text)"
]
},
{
"cell_type": "markdown",
"source": [
"Now we'll define a simple LLM pipeline. It takes a question and context (which in this case is the whole file), creates a prompt and runs it with the LLM."
],
"metadata": {
"id": "2jkamwgdIgEp"
}
},
"source": [
"Now we'll define a simple LLM pipeline. It takes a question and context (which in this case is the whole file), creates a prompt and runs it with the LLM."
]
},
{
"cell_type": "code",
"source": [
"def execute(question, text):\n",
" prompt = f\"\"\"<|im_start|>system\n",
" You are a friendly assistant. You answer questions from users.<|im_end|>\n",
" <|im_start|>user\n",
" Answer the following question using only the context below. Only include information specifically discussed.\n",
"\n",
" question: {question}\n",
" context: {text} <|im_end|>\n",
" <|im_start|>assistant\n",
" \"\"\"\n",
"\n",
" return llm(prompt, maxlength=4096, pad_token_id=32000)\n",
"\n",
"execute(\"Tell me about txtai in one sentence\", text)"
],
"execution_count": 18,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
@@ -208,28 +179,36 @@
"id": "9HU6C0OIIAKn",
"outputId": "f9d556c4-cd7a-4774-ef62-1f3fff90aa47"
},
"execution_count": 23,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'Txtai is an all-in-one embeddings database for semantic search, LLM orchestration, and language model workflows, offering features such as vector search, pipeline creation, workflow management, and API bindings for various programming languages.'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
"'txtai is an all-in-one embeddings database that supports semantic search, LLM orchestration, and language model workflows with features like vector search, embeddings for text, audio, images, and video, pipelines powered by language models, and scalable workflows available via Python or YAML with API bindings for multiple languages.'"
]
},
"execution_count": 18,
"metadata": {},
"execution_count": 23
"output_type": "execute_result"
}
],
"source": [
"def execute(question, text):\n",
" return llm([\n",
" {\"role\": \"system\", \"content\": \"You are a friendly assistant. You answer questions from users.\"},\n",
" {\"role\": \"user\", \"content\": f\"\"\"\n",
" Answer the following question using only the context below. Only include information specifically discussed.\n",
"\n",
" question: {question}\n",
" context: {text} \n",
" \"\"\"}\n",
" ], maxlength=4096)\n",
"\n",
"execute(\"Tell me about txtai in one sentence\", text)"
]
},
{
"cell_type": "code",
"source": [
"execute(\"What model does txtai recommend for transcription?\", text)"
],
"execution_count": 19,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
@@ -238,28 +217,25 @@
"id": "xxF7ajCPJP5_",
"outputId": "0e6f6dbb-c784-4841-fe3f-82754ef478eb"
},
"execution_count": 24,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'The model that txtai recommends for transcription is Whisper.'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
"'txtai recommends using Whisper for transcription.'"
]
},
"execution_count": 19,
"metadata": {},
"execution_count": 24
"output_type": "execute_result"
}
],
"source": [
"execute(\"What model does txtai recommend for transcription?\", text)"
]
},
{
"cell_type": "code",
"source": [
"execute(\"I don't know anything about txtai, what would be the best thing to read?\", text)"
],
"execution_count": 20,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
@@ -268,57 +244,38 @@
"id": "AKmmTqsnJa5X",
"outputId": "834bf3ee-b7ed-4e38-e2ef-d5950f99ed9a"
},
"execution_count": 25,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'The best thing to read to learn about txtai is the \"Introducing txtai\" notebook, which provides an overview of the functionality provided by txtai. This notebook covers various features such as vector search with SQL, object storage, topic modeling, creating embeddings for text, documents, audio, images, and video, and running language model workflows. Additionally, you can explore other example notebooks like \"Similarity search with images,\" \"Build a QA database,\" and \"Semantic Graphs\" to learn more about specific use cases and features. To install txtai, use pip and PyPI with Python 3.10+, and follow the detailed install instructions for more information on optional dependencies and environment-specific prerequisites.'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
"'The best thing to read if you don\\'t know anything about txtai would be the \"Introducing txtai\" notebook, as it provides an overview of the functionality offered by txtai.'"
]
},
"execution_count": 20,
"metadata": {},
"execution_count": 25
"output_type": "execute_result"
}
],
"source": [
"execute(\"I don't know anything about txtai, what would be the best thing to read?\", text)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WaVeEHrIMpFr"
},
"source": [
"If this is the first time you've seen *Generative AI*, then these statements are 🤯. Even if you've been in the space a while, it's still amazing how much a language model can understand and the high level of quality in it's answers.\n",
"\n",
"While this use case is fun, lets try to scale it to a larger set of documents."
],
"metadata": {
"id": "WaVeEHrIMpFr"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Before continuing, it's important to note that txtai has multiple ways to run LLM inference. In the past, prior to \"Chat Templates\", it was expected that the submitted text had all the required chat tokens embedded. The same prompt above can also be written with chat messages. This is especially important when working with LLM APIs (i.e. OpenAI, Claude, Bedrock etc)._\n",
"\n",
"```python\n",
"llm([\n",
" {\"role\": \"system\": \"You are a friendly assistant. You answer questions from users.\"}\n",
" {\"role\": \"user\", \"content\": f\"\"\"\n",
" Answer the following question using only the context below. Only include information specifically discussed.\n",
"\n",
" question: {question}\n",
" context: {text} \n",
" \"\"\"}\n",
"])\n",
"```\n",
"\n",
"_See the [LLM pipeline documentation](https://neuml.github.io/txtai/pipeline/text/llm/) for more information._"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "viVVft59NbKv"
},
"source": [
"# Build a RAG pipeline with vector search\n",
"\n",
@@ -329,13 +286,30 @@
"Typically, this candidate query uses vector search but it can be anything that runs a search and returns results. In fact, many complex production systems have customized retrieval pipelines that feed a context into LLM prompts.\n",
"\n",
"The first step in building our RAG pipeline is creating the knowledge store. In this case, it's a vector database of file content. The files will be split into paragraphs with each paragraph stored as a separate row."
],
"metadata": {
"id": "viVVft59NbKv"
}
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ipmsmtN1NahT",
"outputId": "64733e1f-fb7b-4a2d-bf02-8930478a8ee8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Indexing txtai/article.pdf\n",
"Indexing txtai/document.docx\n",
"Indexing txtai/document.pdf\n",
"Indexing txtai/spreadsheet.xlsx\n"
]
}
],
"source": [
"import os\n",
"\n",
@@ -357,39 +331,40 @@
"# Vector Database\n",
"embeddings = Embeddings(content=True)\n",
"embeddings.index(stream(\"txtai\"))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ipmsmtN1NahT",
"outputId": "64733e1f-fb7b-4a2d-bf02-8930478a8ee8"
},
"execution_count": 26,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Indexing txtai/article.pdf\n",
"Indexing txtai/document.docx\n",
"Indexing txtai/document.pdf\n",
"Indexing txtai/spreadsheet.xlsx\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"The next step is defining the RAG pipeline. This pipeline takes the input question, runs a vector search and builds a context using the search results. The context is then inserted into a prompt template and run with the LLM."
],
"metadata": {
"id": "ASlmAaR3nBPN"
}
},
"source": [
"The next step is defining the RAG pipeline. This pipeline takes the input question, runs a vector search and builds a context using the search results. The context is then inserted into a prompt template and run with the LLM."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 39
},
"id": "_-9SW6r4P5ha",
"outputId": "6a7bcd69-bcd0-4f6e-81c1-e32c323b3ffb"
},
"outputs": [
{
"data": {
"text/plain": [
"'txtai recommends using BLIP for image captioning.'"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def context(question):\n",
" context = \"\\n\".join(x[\"text\"] for x in embeddings.search(question))\n",
@@ -399,38 +374,11 @@
" return execute(question, context(question))\n",
"\n",
"rag(\"What model does txtai recommend for image captioning?\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 39
},
"id": "_-9SW6r4P5ha",
"outputId": "6a7bcd69-bcd0-4f6e-81c1-e32c323b3ffb"
},
"execution_count": 27,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'Based on the provided context, txtai recommends the model \"BLIP\" for image captioning.'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
},
"metadata": {},
"execution_count": 27
}
]
},
{
"cell_type": "code",
"source": [
"result = rag(\"When was the BLIP model added for image captioning?\")\n",
"print(result)"
],
"execution_count": 24,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -438,47 +386,47 @@
"id": "NbQhSunPQtB0",
"outputId": "de0caf04-4cdb-48e8-aadf-37283be9909a"
},
"execution_count": 28,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"The BLIP model was added for image captioning on 2022-03-17.\n"
]
}
],
"source": [
"result = rag(\"When was the BLIP model added for image captioning?\")\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "D6HW-3GtnTFl"
},
"source": [
"As we can see, the result is similar to what we had before without vector search. The difference is that we only used a relevant portion of the documents to generate the answer.\n",
"\n",
"As we discussed before, this is important when dealing with large volumes of data. Not all of the data can be added to a LLM prompt. Additionally, having only the most relevant context helps the LLM generate higher quality answers."
],
"metadata": {
"id": "D6HW-3GtnTFl"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FZ-yPC-xiUqa"
},
"source": [
"# Citations for LLMs\n",
"\n",
"A healthy level of skepticism should be applied to answers generated by AI. We're far from the day where we can blindly trust answers from an AI model.\n",
"\n",
"txtai has a couple approaches for generating citations. The basic approach is to take the answer and search the vector database for the closest match."
],
"metadata": {
"id": "FZ-yPC-xiUqa"
}
]
},
{
"cell_type": "code",
"source": [
"for x in embeddings.search(result):\n",
" print(x[\"text\"])"
],
"execution_count": 25,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -486,16 +434,15 @@
"id": "obttSg_dSFT5",
"outputId": "c7ae7675-6959-4bcb-ad06-065ea8609c31"
},
"execution_count": 29,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"E5-base-v2\n",
"Image Captions BLIP\n",
"Labels - Zero Shot BART-Large-MNLI\n",
"Model Guide\n",
"# Model Guide\n",
"|Component |Model(s)|Date Added|\n",
"|---|---|---|\n",
"|Embeddings |all-MiniLM-L6-v2|2022-04-15|\n",
@@ -507,66 +454,65 @@
"|Transcription |Whisper|2022-08-01|\n",
"|Translation |OPUS Model Series|2021-04-06|\n",
"&\"Times New Roman,Regular\"&12&A\n",
"Notebook Description\n",
"Introducing txtai Overview of the functionality provided by txtai\n",
"Similarity search with \n",
"images Embed images and text into the same space for search\n"
"## Model guide\n",
"The following shows a list of suggested models.\n",
"|Component|Model(s)|\n",
"|---|---|\n",
"|Embeddings|all-MiniLM-L6-v2|\n",
"||E5-base-v2|\n",
"|Image Captions|BLIP|\n",
"|Labels - Zero Shot|BART-Large-MNLI|\n",
"|Labels - Fixed|Fine-tune with training pipeline|\n",
"|Large Language Model (LLM)|Flan T5 XL|\n",
"||Mistral 7B OpenOrca|\n",
"|Summarization|DistilBART|\n",
"|Text-to-Speech|ESPnet JETS|\n",
"|Transcription|Whisper|\n",
"|Translation|OPUS Model Series|\n"
]
}
],
"source": [
"for x in embeddings.search(result):\n",
" print(x[\"text\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MDcB7GCWY6TO"
},
"source": [
"While the basic approach above works in this case, txtai has a more robust pipeline to handle citations and references.\n",
"\n",
"The RAG pipeline is defined below. A RAG pipeline works in the same way as a LLM + Vector Search pipeline, except it has special logic for generating citations. This pipeline takes the answers and compares it to the context passed to the LLM to determine the most likely reference."
],
"metadata": {
"id": "MDcB7GCWY6TO"
}
]
},
{
"cell_type": "code",
"source": [
"from txtai import RAG\n",
"\n",
"# RAG prompt\n",
"def prompt(question):\n",
" return [{\n",
" \"query\": question,\n",
" \"question\": f\"\"\"\n",
"Answer the following question using only the context below. Only include information specifically discussed.\n",
"\n",
"question: {question}\n",
"context:\n",
"\"\"\"\n",
"}]\n",
"\n",
"# Create LLM with system prompt template\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\", template=\"\"\"<|im_start|>system\n",
"You are a friendly assistant. You answer questions from users.<|im_end|>\n",
"<|im_start|>user\n",
"{text} <|im_end|>\n",
"<|im_start|>assistant\n",
"\"\"\")\n",
"\n",
"# Create RAG instance\n",
"rag = RAG(embeddings, llm, output=\"reference\")"
],
"execution_count": 26,
"metadata": {
"id": "Lm6gg85_Y7ot"
},
"execution_count": null,
"outputs": []
"outputs": [],
"source": [
"from txtai import RAG\n",
"\n",
"# Create the RAG pipeline\n",
"rag = RAG(embeddings, \"Qwen/Qwen3-4B-Instruct-2507\", template=\"\"\"\n",
" Answer the following question using the provided context.\n",
"\n",
" Question:\n",
" {question}\n",
"\n",
" Context:\n",
" {context}\n",
"\"\"\", output=\"reference\")"
]
},
{
"cell_type": "code",
"source": [
"result = rag(prompt(\"What version of Python is supported?\"), maxlength=4096, pad_token_id=32000)[0]\n",
"print(\"ANSWER:\", result[\"answer\"])\n",
"print(\"CITATION:\", embeddings.search(\"select id, text from txtai where id = :id\", limit=1, parameters={\"id\": result[\"reference\"]}))"
],
"execution_count": 27,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
@@ -574,36 +520,36 @@
"id": "4pOfE5paZatH",
"outputId": "2bed2de5-22ff-4f7b-dba5-41b8e4cc6c75"
},
"execution_count": 31,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"output_type": "stream",
"text": [
"ANSWER: Python 3.10+ is supported. Using a Python virtual environment is recommended. The easiest way to install is via pip and PyPI.\n",
"CITATION: [{'id': '24', 'text': 'Python 3.10+ is supported. Using a Python virtual environment is recommended.'}]\n"
"ANSWER: Python 3.11 and later versions (Python 3.11+) are supported.\n",
"CITATION: [{'id': '24', 'text': 'Python 3.11+ is supported. Using a Python virtual environment is recommended.'}]\n"
]
}
],
"source": [
"result = rag(\"What version of Python is supported?\", maxlength=4096)\n",
"print(\"ANSWER:\", result[\"answer\"])\n",
"print(\"CITATION:\", embeddings.search(\"select id, text from txtai where id = :id\", limit=1, parameters={\"id\": result[\"reference\"]}))"
]
},
{
"cell_type": "markdown",
"source": [
"And as we can see, not only is the answer to the statement shown, the RAG pipeline also provides a citation. This step is crucial in any line of work where answers must be verified (which is most lines of work)."
],
"metadata": {
"id": "vHdE2Q59jNnF"
}
},
{
"cell_type": "markdown",
"metadata": {},
},
"source": [
"_As with the LLM pipeline, the RAG pipeline also supports chat messages. See the [RAG pipeline documentation](https://neuml.github.io/txtai/pipeline/text/rag/) for more._"
"And as we can see, not only is the answer to the statement shown, the RAG pipeline also provides a citation. This step is crucial in any line of work where answers must be verified (which is most lines of work)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oPwgCgBc2Er2"
},
"source": [
"# Wrapping up\n",
"\n",
@@ -611,13 +557,36 @@
"\n",
"The advantages of building RAG pipelines with txtai are:\n",
"\n",
"- **All-in-one database** - one library can handle LLM inference and vector search retrieval\n",
"- **All-in-one AI framework** - one library can handle LLM inference and vector search retrieval\n",
"- **Generating citations** - generating answers is useful but referencing where those answers came from is crucial in gaining the trust of users\n",
"- **Simple yet powerful** - building pipelines can be done in a small amount of Python. Options are available to build pipelines in YAML and/or run through the API"
],
"metadata": {
"id": "oPwgCgBc2Er2"
}
]
}
]
],
"metadata": {
"accelerator": "GPU",
"colab": {
"gpuType": "T4",
"provenance": []
},
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
+1 -1
View File
@@ -90,7 +90,7 @@
"embeddings.index(data)\n",
"\n",
"# Create LLM with llama.cpp - GGUF file is automatically downloaded\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-GGUF/mistral-7b-openorca.Q4_K_M.gguf\", verbose=True)\n",
"llm = LLM(\"unsloth/Qwen3-4B-Instruct-2507-GGUF/Qwen3-4B-Instruct-2507-Q4_K_M.gguf\", verbose=True)\n",
"\n",
"template = \"\"\"<|im_start|>system\n",
"You are a friendly assistant. You answer questions from users.<|im_end|>\n",
@@ -19,7 +19,7 @@
"source": [
"# API Authorization and Authentication\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows. txtai can run in Python, with YAML configuration and through an API service.\n",
"txtai can run in Python, with YAML configuration and through an API service.\n",
"\n",
"The default API service implementation runs without any security. This may be OK for a local prototype or if it's run on a small internal network. But in most cases, additional security measures should be taken.\n",
"\n",
@@ -8,8 +8,6 @@
"source": [
"# Generate knowledge with Semantic Graphs and RAG\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Embeddings databases are a union of vector indexes (sparse and dense), graph networks and relational databases. This enables vector search with SQL, topic modeling, retrieval augmented generation and more.\n",
"\n",
"Semantic graphs were introduced in late 2022 with txtai 5.0, right before the start of the LLM era. This notebook picks back up where that work left off, opening a new frontier in semantic graph integration."
@@ -35,7 +33,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph]"
]
},
{
@@ -296,7 +294,7 @@
"outputs": [],
"source": [
"from txtai import LLM\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")"
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")"
]
},
{
-2
View File
@@ -21,8 +21,6 @@
"source": [
"# External vectorization\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Vectorization is the process of transforming data into numbers using machine learning models. Input data is run through a model and fixed dimension vectors are returned. These vectors can then be loaded into a vector database for similarity search.\n",
"\n",
"txtai is an open-source first system. Given it's own open-source roots, like-minded projects such as [sentence-transformers](https://github.com/UKPLab/sentence-transformers) are prioritized during development. But that doesn't mean txtai can't work with Embeddings API services.\n",
@@ -8,8 +8,6 @@
"source": [
"# Build knowledge graphs with LLM-driven entity extraction\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Embeddings databases are a union of vector indexes (sparse and dense), graph networks and relational databases. This enables vector search with SQL, topic modeling, retrieval augmented generation and more.\n",
"\n",
"Up until txtai 7.0, semantic graphs only supported automatic relationship detection. Now relationships can be loaded directly into a txtai database. This notebook will demonstrate how to work with this new feature."
@@ -35,7 +33,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph]"
]
},
{
@@ -99,7 +97,7 @@
"from txtai import LLM\n",
"\n",
"# Load LLM\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"data = []\n",
"for result in results:\n",
@@ -8,8 +8,6 @@
"source": [
"# Advanced RAG with graph path traversal\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Embeddings databases are a union of vector indexes (sparse and dense), graph networks and relational databases. This enables vector search with SQL, topic modeling, retrieval augmented generation (RAG) and more.\n",
"\n",
"A standard RAG process typically runs a single vector search query and returns the closest matches. Those matches are then passed into a LLM prompt and used to limit the context and help ensure more factually correct answers are generated. This works well with most simple cases. More complex use cases, require a more advanced approach.\n",
@@ -37,7 +35,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[graph]"
]
},
{
@@ -215,7 +213,7 @@
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")"
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")"
]
},
{
+2 -2
View File
@@ -54,7 +54,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api,graph,pipeline-train] datasets autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api,graph,pipeline-train] datasets"
]
},
{
@@ -244,7 +244,7 @@
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"def rag(question, text):\n",
" prompt = f\"\"\"<|im_start|>system\n",
@@ -8,8 +8,6 @@
"source": [
"# Advanced RAG with guided generation\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"A standard RAG process typically runs a single vector search query and returns the closest matches. Those matches are then passed into a LLM prompt and used to limit the context and help ensure more factually correct answers are generated. This works well with most simple cases. More complex use cases, require a more advanced approach.\n",
"\n",
"This notebook will demonstrate how constrained or guided generation can be applied to better control LLM output."
@@ -35,7 +33,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai autoawq outlines"
"!pip install git+https://github.com/neuml/txtai#egg=txtai outlines"
]
},
{
@@ -59,7 +57,7 @@
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"def rag(question, text):\n",
" prompt = f\"\"\"<|im_start|>system\n",
@@ -21,8 +21,6 @@
"source": [
"# Integrate txtai with Postgres\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"The default persistence methods for txtai are local and file-based. `SQLite` for content, `Faiss` for vectors and `NetworkX` for graph data. The main value add of txtai is getting up and running quickly with a minimal amount of external dependencies.\n",
"\n",
"Another key feature of txtai is being able to quickly move from prototyping to production. This notebook will demonstrate how txtai can integrate with [Postgres](https://www.postgresql.org/), a powerful, production-ready and open source object-relational database system. After txtai persists content to Postgres, we'll show it can be directly queried with SQL from any Postgres client 🔥"
@@ -8,8 +8,6 @@
"source": [
"# RAG with llama.cpp and external API services\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"txtai has been and always will be a local-first framework. It was originally designed to run models on local hardware using Hugging Face Transformers. As the AI space has evolved over the last year, so has txtai. Additional LLM inference frameworks have been available for a while using llama.cpp and external API services (via LiteLLM). Recent changes have added the ability to use these frameworks for vectorization and made it easier to use for LLM inference.\n",
"\n",
"This notebook will demonstrate how to run retrieval-augmented-generation (RAG) processes (vectorization and LLM inference) with llama.cpp and external API services."
@@ -182,7 +180,7 @@
"from txtai import LLM\n",
"\n",
"# LLM instance\n",
"llm = LLM(path=\"TheBloke/Mistral-7B-OpenOrca-GGUF/mistral-7b-openorca.Q4_K_M.gguf\")\n",
"llm = LLM(path=\"unsloth/Qwen3-4B-Instruct-2507-GGUF/Qwen3-4B-Instruct-2507-Q4_K_M.gguf\")\n",
"\n",
"# Question and context\n",
"question = \"Write a list of invented electric-powered devices\"\n",
@@ -237,11 +235,11 @@
"\n",
"# Download models\n",
"!wget https://huggingface.co/second-state/All-MiniLM-L6-v2-Embedding-GGUF/resolve/main/all-MiniLM-L6-v2-Q4_K_M.gguf\n",
"!wget https://huggingface.co/TheBloke/Mistral-7B-OpenOrca-GGUF/resolve/main/mistral-7b-openorca.Q4_K_M.gguf\n",
"!wget https://huggingface.co/unsloth/Qwen3-4B-Instruct-2507-GGUF/blob/main/Qwen3-4B-Instruct-2507-Q4_K_M.gguf\n",
"\n",
"# Start local API services\n",
"!nohup python -m llama_cpp.server --n_gpu_layers -1 --model all-MiniLM-L6-v2-Q4_K_M.gguf --host 127.0.0.1 --port 8000 &> vector.log &\n",
"!nohup python -m llama_cpp.server --n_gpu_layers -1 --model mistral-7b-openorca.Q4_K_M.gguf --chat_format chatml --host 127.0.0.1 --port 8001 &> llm.log &\n",
"!nohup python -m llama_cpp.server --n_gpu_layers -1 --model Qwen3-4B-Instruct-2507-Q4_K_M.gguf --chat_format chatml --host 127.0.0.1 --port 8001 &> llm.log &\n",
"!sleep 30"
]
},
+3 -5
View File
@@ -8,8 +8,6 @@
"source": [
"# How RAG with txtai works\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Large Language Models (LLMs) have captured the public's attention with their impressive capabilities. The Generative AI era has reached a fever pitch with some predicting the coming rise of superintelligence.\n",
"\n",
"LLMs are far from perfect though and we're still a ways away from true AI. The biggest challenge is with hallucinations. Hallucinations is the term for when a LLM generates output that is factually incorrect. The alarming part of this is that on a cursory glance, it actually sounds like factual content. The default behavior of LLMs is to produce plausible answers even when no plausible answer exists. LLMs are not great at saying I don't know.\n",
@@ -45,7 +43,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api,pipeline] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api,pipeline]"
]
},
{
@@ -74,7 +72,7 @@
"embeddings.load(provider=\"huggingface-hub\", container=\"neuml/txtai-wikipedia\")\n",
"\n",
"# Create LLM\n",
"llm = LLM(\"TheBloke/Mistral-7B-OpenOrca-AWQ\")"
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")"
]
},
{
@@ -310,7 +308,7 @@
"\n",
"# RAG pipeline configuration\n",
"rag:\n",
" path: TheBloke/Mistral-7B-OpenOrca-AWQ\n",
" path: Qwen/Qwen3-4B-Instruct-2507\n",
" output: flatten\n",
" template: |\n",
" <|im_start|>system\n",
@@ -21,8 +21,6 @@
"source": [
"# Embeddings index format for open data access\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"The main programming language with txtai is Python. A key tenet is that the underlying data in an embeddings index is accessible without txtai.\n",
"\n",
"This notebook will demonstrate this through a series of examples.\n"
+3 -5
View File
@@ -6,8 +6,6 @@
"source": [
"# Speech to Speech RAG\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"There are many articles, notebooks and examples covering how to perform vector search and/or retrieval augmented generation (RAG) with txtai. A lesser known component of txtai is it's built-in workflow component.\n",
"\n",
"Workflows are a simple yet powerful construct that takes a callable and returns elements. Workflows enable efficient processing of pipeline data. Workflows are streaming by nature and work on data in batches. This allows large volumes of data to be processed efficiently.\n",
@@ -33,7 +31,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-audio] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-audio]"
]
},
{
@@ -86,7 +84,7 @@
"# Create RAG pipeline\n",
"rag = RAG(\n",
" embeddings,\n",
" \"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\",\n",
" \"Qwen/Qwen3-4B-Instruct-2507\",\n",
" system=\"You are a friendly assistant. You answer questions from users.\",\n",
" template=template,\n",
" context=10\n",
@@ -160,7 +158,7 @@
"\n",
"# RAG\n",
"rag:\n",
" path: \"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\"\n",
" path: \"Qwen/Qwen3-4B-Instruct-2507\"\n",
" system: You are a friendly assistant. You answer questions from users.\n",
" template: |\n",
" Answer the following question using only the context below. Only include information\n",
+3 -5
View File
@@ -6,8 +6,6 @@
"source": [
"# Generative Audio\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"txtai works with much more than just text! It has rich multimedia and multimodal capabilities.\n",
"\n",
"This notebook will demonstrate how to build generative audio workflows. These workflows will generate a combined audio stream with text and relevant audio for a series of poems."
@@ -29,7 +27,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-audio] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-audio]"
]
},
{
@@ -41,7 +39,7 @@
"The next section defines a generative audio workflow. This workflow consists of a set of pipelines as follows:\n",
"\n",
"- LLM\n",
" - Llama 3 model used to describe the emotions of a given story or poem\n",
" - Model used to describe the emotions of a given story or poem\n",
"- Text To Audio\n",
" - Builds audio given a text prompt\n",
"- Text To Speech\n",
@@ -81,7 +79,7 @@
" return audio\n",
"\n",
"# LLM\n",
"llm = LLM(\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"# Text to Audio\n",
"# Important: The code for musicgen is licensed as MIT but model weights are CC-BY-NC\n",
+5 -7
View File
@@ -8,8 +8,6 @@
"source": [
"# 💡 What's new in txtai 8.0\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"The 8.0 release brings a major new feature: Agents 🚀\n",
"\n",
"Agents automatically create workflows to answer multi-faceted user requests. Agents iteratively prompt and/or interface with tools to\n",
@@ -42,7 +40,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent] autoawq model2vec"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent] model2vec"
]
},
{
@@ -94,7 +92,7 @@
"\n",
"agent = Agent(\n",
" tools=[today, wikipedia, arxiv, \"websearch\"],\n",
" llm=\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\",\n",
" llm=\"Qwen/Qwen3-4B-Instruct-2507\",\n",
" max_iterations=10,\n",
")"
]
@@ -254,7 +252,7 @@
"source": [
"Let's unpack what just happened here. The Agent reviewed multiple sources and aggregated the references into a single report. This is quite powerful 💪\n",
"\n",
"Note that depending on the LLM used, errors can be seen as the Agent tries to get the function parameters right. This example is using Llama 3.1 8B. A more powerful LLM will likely lead to even better results. Remember that txtai supports a number of LLM frameworks (Hugging Face, llama.cpp and LiteLLM APIs)."
"Note that depending on the LLM used, errors can be seen as the Agent tries to get the function parameters right. This example is using Qwen3 4B. A more powerful LLM will likely lead to even better results. Remember that txtai supports a number of LLM frameworks (Hugging Face, llama.cpp and LiteLLM APIs)."
]
},
{
@@ -277,7 +275,7 @@
"from txtai import Agent, LLM\n",
"\n",
"# Share the LLM instance across multiple agents\n",
"llm = LLM(\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"websearcher = Agent(\n",
" tools=[\"websearch\"],\n",
@@ -418,7 +416,7 @@
" container: neuml/txtai-arxiv\n",
"\n",
"llm:\n",
" path: hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4"
" path: Qwen/Qwen3-4B-Instruct-2507"
]
},
{
@@ -6,8 +6,6 @@
"source": [
"# Analyzing Hugging Face Posts with Graphs and Agents\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Embeddings databases can optionally build a graph network alongside stored vectors. The graph automatically infers relationships of the content using the computed vector embeddings. This provides an additional way to explore and analyze content. \n",
"\n",
"txtai 8.0 was recently released and added the ability to run agents. Agents automatically create workflows to answer multi-faceted user requests.\n",
@@ -36,7 +34,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph] datasets autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph] datasets"
]
},
{
@@ -59,7 +57,7 @@
"from datasets import load_dataset\n",
"from txtai import LLM\n",
"\n",
"llm = LLM(\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"def title(text):\n",
" prompt = f\"\"\"\n",
@@ -6,8 +6,6 @@
"source": [
"# Granting autonomy to agents\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"txtai 8.0 was recently released and added the ability to run agents. Agents automatically create workflows to answer multi-faceted user requests.\n",
"\n",
"Agents connect a series of tools with a reasoning engine (i.e. LLM). We're giving the agent a degree of latitude to go through it's own internal logic to address a user's request.\n",
@@ -33,7 +31,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph] autoawq"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph]"
]
},
{
@@ -62,7 +60,7 @@
" \"provider\": \"huggingface-hub\",\n",
" \"container\": \"neuml/txtai-wikipedia\"\n",
" }],\n",
" llm=\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\",\n",
" llm=\"Qwen/Qwen3-4B-Instruct-2507\",\n",
" max_iterations=10,\n",
")"
]
@@ -145,9 +143,7 @@
"source": [
"💥 Interesting indeed. The fundamental concept of search is we need to know what to look for. In this case, we didn't have that (i.e. we're bored 😀).\n",
"\n",
"Let's go to another example. This time we'll look at the [txtai-hfposts](https://huggingface.co/NeuML/txtai-hfposts) embeddings database. We'll ask the agent to research a specific topic then write a report about what was found.\n",
"\n",
"It's important to mention that txtai agents support any [LLM supported by txtai](https://neuml.github.io/txtai/pipeline/text/llm/). So while all of the examples have been using `Llama 3.1 8B`, other LLMs local and remote are supported (i.e. OpenAI, AWS Bedrock, Anthropic). To change it up, we'll use one of the [Qwen models](https://huggingface.co/Qwen) which have been receiving a lot of positive reviews lately."
"Let's go to another example. This time we'll look at the [txtai-hfposts](https://huggingface.co/NeuML/txtai-hfposts) embeddings database. We'll ask the agent to research a specific topic then write a report about what was found.\n"
]
},
{
@@ -163,7 +159,7 @@
" \"provider\": \"huggingface-hub\",\n",
" \"container\": \"neuml/txtai-hfposts\"\n",
" }],\n",
" llm=\"Qwen/Qwen2.5-7B-Instruct-AWQ\",\n",
" llm=\"Qwen/Qwen3-4B-Instruct-2507\",\n",
" max_iterations=10,\n",
")"
]
@@ -293,7 +289,7 @@
"\n",
"agent = Agent(\n",
" tools=[insert, embeddings.search, \"websearch\"],\n",
" llm=\"Qwen/Qwen2.5-7B-Instruct-AWQ\",\n",
" llm=\"Qwen/Qwen3-4B-Instruct-2507\",\n",
" max_iterations=10\n",
")"
]
@@ -6,8 +6,6 @@
"source": [
"# Analyzing LinkedIn Company Posts with Graphs and Agents\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"This notebook will analyze [NeuML's LinkedIn company posts](https://hf.co/datasets/neuml/neuml-linkedin-202501) over the last 12 months as of January 2025. It will build an embeddings database with an associated graph and topic modeling. The most popular topics will be explored using graphs and vector search queries.\n",
"\n",
"From there we'll use Agents to investigate the dataset and find ways to increase engagement with our future posts using past history."
@@ -29,7 +27,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph] datasets autoawq autoawq-kernels"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph] datasets"
]
},
{
@@ -74,7 +72,7 @@
"\n",
"posts = load_dataset(\"neuml/neuml-linkedin-202501\", split=\"train\")\n",
"\n",
"llm = LLM(\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"embeddings = Embeddings(\n",
" autoid=\"uuid5\",\n",
@@ -6,8 +6,6 @@
"source": [
"# Parsing the ⭐'s with txtai\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"In honor of txtai's recent milestone of reaching 10K ⭐'s on GitHub, this notebook will build an astronomical knowledge graph of known stars, planets, galaxies and other astronomical entities. It will show how a compendium of information can be built from a public knowledge source such as Wikipedia.\n",
"\n",
"While agents and retrieval augmented generation (RAG) can do great things, they can do even greater things if provided with an assist from the humans in the form of compiled knowledge. It's not only better accuracy, it's also faster as we don't need to wait for an agent to figure out what we already know.\n",
@@ -31,7 +29,7 @@
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph,pipeline-text] datasets autoawq autoawq-kernels"
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent,graph,pipeline-text] datasets"
]
},
{
@@ -401,7 +399,7 @@
"context: {context}\"\"\"\n",
"\n",
"# Load LLM\n",
"llm = LLM(\"hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\")\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"# Create RAG pipeline\n",
"rag = RAG(\n",
+2 -4
View File
@@ -6,8 +6,6 @@
"source": [
"# Chunking your data for RAG\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"One of the major workflows in `txtai` is Retrieval Augmented Generation (RAG). Large Language Models (LLM) are built to generate coherent sounding text. While in many cases it is factually accurate, that is not what they're built to do. RAG steps in to help inject smaller pieces of knowledge into a LLM prompt and increase the overall accuracy of responses. The `R` in RAG is very important.\n",
"\n",
"This notebook will demonstrate how to extract, chunk and index text to support retrieval operations for RAG."
@@ -102,12 +100,12 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'indexid': 0, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': '**GitHub - neuml/txtai: 💡 All-in-one open-source embeddings database for semantic search, LLM orchestration and language model workflows**\\n\\n*💡 All-in-one open-source embeddings database for semantic search, LLM orchestration and language model workflows - neuml/txtai*\\n\\n\\n\\n**All-in-one embeddings database** \\ntxtai is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\\n\\nEmbeddings databases are a union of vector indexes (sparse and dense), graph networks and relational databases.\\n\\nThis foundation enables vector search and/or serves as a powerful knowledge source for large language model (LLM) applications.\\n\\nBuild autonomous agents, retrieval augmented generation (RAG) processes, multi-model workflows and more.\\n\\nSummary of txtai features:\\n\\n- 🔎 Vector search with SQL, object storage, topic modeling, graph analysis and multimodal indexing\\n- 📄 Create embeddings for text, documents, audio, images and video\\n- 💡 Pipelines powered by language models that run LLM prompts, question-answering, labeling, transcription, translation, summarization and more\\n- ↪️️ Workflows to join pipelines together and aggregate business logic. txtai processes can be simple microservices or multi-model workflows.\\n- 🤖 Agents that intelligently connect embeddings, pipelines, workflows and other agents together to autonomously solve complex problems\\n- ⚙️ Build with Python or YAML. API bindings available for [JavaScript](https://github.com/neuml/txtai.js) , [Java](https://github.com/neuml/txtai.java) , [Rust](https://github.com/neuml/txtai.rs) and [Go](https://github.com/neuml/txtai.go) .\\n- 🔋 Batteries included with defaults to get up and running fast\\n- ☁️ Run local or scale out with container orchestration\\ntxtai is built with Python 3.10+, [Hugging Face Transformers](https://github.com/huggingface/transformers) , [Sentence Transformers](https://github.'}\n",
"{'indexid': 0, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': '**GitHub - neuml/txtai: 💡 All-in-one open-source embeddings database for semantic search, LLM orchestration and language model workflows**\\n\\n*💡 All-in-one open-source embeddings database for semantic search, LLM orchestration and language model workflows - neuml/txtai*\\n\\n\\n\\n**All-in-one embeddings database** \\ntxtai is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\\n\\nEmbeddings databases are a union of vector indexes (sparse and dense), graph networks and relational databases.\\n\\nThis foundation enables vector search and/or serves as a powerful knowledge source for large language model (LLM) applications.\\n\\nBuild autonomous agents, retrieval augmented generation (RAG) processes, multi-model workflows and more.\\n\\nSummary of txtai features:\\n\\n- 🔎 Vector search with SQL, object storage, topic modeling, graph analysis and multimodal indexing\\n- 📄 Create embeddings for text, documents, audio, images and video\\n- 💡 Pipelines powered by language models that run LLM prompts, question-answering, labeling, transcription, translation, summarization and more\\n- ↪️️ Workflows to join pipelines together and aggregate business logic. txtai processes can be simple microservices or multi-model workflows.\\n- 🤖 Agents that intelligently connect embeddings, pipelines, workflows and other agents together to autonomously solve complex problems\\n- ⚙️ Build with Python or YAML. API bindings available for [JavaScript](https://github.com/neuml/txtai.js) , [Java](https://github.com/neuml/txtai.java) , [Rust](https://github.com/neuml/txtai.rs) and [Go](https://github.com/neuml/txtai.go) .\\n- 🔋 Batteries included with defaults to get up and running fast\\n- ☁️ Run local or scale out with container orchestration\\ntxtai is built with Python 3.11+, [Hugging Face Transformers](https://github.com/huggingface/transformers) , [Sentence Transformers](https://github.'}\n",
"{'indexid': 1, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'com/UKPLab/sentence-transformers) and [FastAPI](https://github.com/tiangolo/fastapi) . txtai is open-source under an Apache 2.0 license.\\n\\n*Interested in an easy and secure way to run hosted txtai applications? Then join the* [txtai.cloud](https://txtai.cloud) *preview to learn more.* \\n\\n## Why txtai?\\nNew vector databases, LLM frameworks and everything in between are sprouting up daily. Why build with txtai?\\n\\n- Up and running in minutes with [pip](https://neuml.github.io/txtai/install/) or [Docker](https://neuml.github.io/txtai/cloud/) \\n```\\n# Get started in a couple lines\\nimport txtai\\n\\nembeddings = txtai.Embeddings()\\nembeddings.index([\"Correct\", \"Not what we hoped\"])\\nembeddings.search(\"positive\", 1)\\n#[(0, 0.29862046241760254)]\\n```\\n\\n- Built-in API makes it easy to develop applications using your programming language of choice\\n```\\n# app.yml\\nembeddings:\\n path: sentence-transformers/all-MiniLM-L6-v2\\n```\\n\\n```\\nCONFIG=app.yml uvicorn \"txtai.api:app\"\\ncurl -X GET \"http://localhost:8000/search?query=positive\"\\n```\\n\\n- Run local - no need to ship data off to disparate remote services\\n- Work with micromodels all the way up to large language models (LLMs)\\n- Low footprint - install additional dependencies and scale up when needed\\n- [Learn by example](https://neuml.github.io/txtai/examples) - notebooks cover all available functionality\\n\\n## Use Cases\\nThe following sections introduce common txtai use cases. A comprehensive set of over 60 [example notebooks and applications](https://neuml.github.io/txtai/examples) are also available.\\n\\n\\n### Semantic Search\\nBuild semantic/similarity/vector/neural search applications.'}\n",
"{'indexid': 2, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'Traditional search systems use keywords to find data. Semantic search has an understanding of natural language and identifies results that have the same meaning, not necessarily the same keywords.\\n\\nGet started with the following examples.\\n\\n|Notebook|Description||\\n|---|---|---|\\n|[Introducing txtai](https://github.com/neuml/txtai/blob/master/examples/01_Introducing_txtai.ipynb) |Overview of the functionality provided by txtai||\\n|[Similarity search with images](https://github.com/neuml/txtai/blob/master/examples/13_Similarity_search_with_images.ipynb) |Embed images and text into the same space for search||\\n|[Build a QA database](https://github.com/neuml/txtai/blob/master/examples/34_Build_a_QA_database.ipynb) |Question matching with semantic search||\\n|[Semantic Graphs](https://github.com/neuml/txtai/blob/master/examples/38_Introducing_the_Semantic_Graph.ipynb) |Explore topics, data connectivity and run network analysis||\\n\\n### LLM Orchestration\\nAutonomous agents, retrieval augmented generation (RAG), chat with your data, pipelines and workflows that interface with large language models (LLMs).\\n\\nSee below to learn more.\\n\\n|Notebook|Description||\\n|---|---|---|\\n|[Prompt templates and task chains](https://github.com/neuml/txtai/blob/master/examples/44_Prompt_templates_and_task_chains.ipynb) |Build model prompts and connect tasks together with workflows||\\n|[Integrate LLM frameworks](https://github.com/neuml/txtai/blob/master/examples/53_Integrate_LLM_Frameworks.ipynb) |Integrate llama.cpp, LiteLLM and custom generation frameworks||\\n|[Build knowledge graphs with LLMs](https://github.'}\n",
"{'indexid': 3, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'com/neuml/txtai/blob/master/examples/57_Build_knowledge_graphs_with_LLM_driven_entity_extraction.ipynb) |Build knowledge graphs with LLM-driven entity extraction||\\n\\n#### Agents\\nAgents connect embeddings, pipelines, workflows and other agents together to autonomously solve complex problems.\\n\\ntxtai agents are built on top of the Transformers Agent framework. This supports all LLMs txtai supports (Hugging Face, llama.cpp, OpenAI / Claude / AWS Bedrock via LiteLLM).\\n\\nSee the link below to learn more.\\n\\n|Notebook|Description||\\n|---|---|---|\\n|[Analyzing Hugging Face Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/68_Analyzing_Hugging_Face_Posts_with_Graphs_and_Agents.ipynb) |Explore a rich dataset with Graph Analysis and Agents||\\n|[Granting autonomy to agents](https://github.com/neuml/txtai/blob/master/examples/69_Granting_autonomy_to_agents.ipynb) |Agents that iteratively solve problems as they see fit||\\n|[Analyzing LinkedIn Company Posts with Graphs and Agents](https://github.com/neuml/txtai/blob/master/examples/71_Analyzing_LinkedIn_Company_Posts_with_Graphs_and_Agents.ipynb) |Exploring how to improve social media engagement with AI||\\n\\n#### Retrieval augmented generation\\nRetrieval augmented generation (RAG) reduces the risk of LLM hallucinations by constraining the output with a knowledge base as context. RAG is commonly used to \"chat with your data\".\\n\\nA novel feature of txtai is that it can provide both an answer and source citation.\\n\\n|Notebook|Description||\\n|---|---|---|\\n|[Build RAG pipelines with txtai](https://github.'}\n",
"{'indexid': 4, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'com/neuml/txtai/blob/master/examples/52_Build_RAG_pipelines_with_txtai.ipynb) |Guide on retrieval augmented generation including how to create citations||\\n|[How RAG with txtai works](https://github.com/neuml/txtai/blob/master/examples/63_How_RAG_with_txtai_works.ipynb) |Create RAG processes, API services and Docker instances||\\n|[Advanced RAG with graph path traversal](https://github.com/neuml/txtai/blob/master/examples/58_Advanced_RAG_with_graph_path_traversal.ipynb) |Graph path traversal to collect complex sets of data for advanced RAG||\\n|[Speech to Speech RAG](https://github.com/neuml/txtai/blob/master/examples/65_Speech_to_Speech_RAG.ipynb) |Full cycle speech to speech workflow with RAG||\\n\\n### Language Model Workflows\\nLanguage model workflows, also known as semantic workflows, connect language models together to build intelligent applications.\\n\\nWhile LLMs are powerful, there are plenty of smaller, more specialized models that work better and faster for specific tasks. This includes models for extractive question-answering, automatic summarization, text-to-speech, transcription and translation.\\n\\n|Notebook|Description||\\n|---|---|---|\\n|[Run pipeline workflows](https://github.com/neuml/txtai/blob/master/examples/14_Run_pipeline_workflows.ipynb) |Simple yet powerful constructs to efficiently process data||\\n|[Building abstractive text summaries](https://github.com/neuml/txtai/blob/master/examples/09_Building_abstractive_text_summaries.ipynb) |Run abstractive text summarization||\\n|[Transcribe audio to text](https://github.com/neuml/txtai/blob/master/examples/11_Transcribe_audio_to_text.'}\n",
"{'indexid': 5, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'ipynb) |Convert audio files to text||\\n|[Translate text between languages](https://github.com/neuml/txtai/blob/master/examples/12_Translate_text_between_languages.ipynb) |Streamline machine translation and language detection||\\n\\n## Installation\\nThe easiest way to install is via pip and PyPI\\n\\n```\\npip install txtai\\n```\\n\\nPython 3.10+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.\\n\\nSee the detailed [install instructions](https://neuml.github.io/txtai/install) for more information covering [optional dependencies](https://neuml.github.io/txtai/install/#optional-dependencies) , [environment specific prerequisites](https://neuml.github.io/txtai/install/#environment-specific-prerequisites) , [installing from source](https://neuml.github.io/txtai/install/#install-from-source) , [conda support](https://neuml.github.io/txtai/install/#conda) and how to [run with containers](https://neuml.github.io/txtai/cloud) .\\n\\n\\n## Model guide\\nSee the table below for the current recommended models. These models all allow commercial use and offer a blend of speed and performance.\\n\\n|Component|Model(s)|\\n|---|---|\\n|[Embeddings](https://neuml.github.io/txtai/embeddings) |[all-MiniLM-L6-v2](https://hf.co/sentence-transformers/all-MiniLM-L6-v2) |\\n|[Image Captions](https://neuml.github.io/txtai/pipeline/image/caption) |[BLIP](https://hf.co/Salesforce/blip-image-captioning-base) |'}\n",
"{'indexid': 5, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'ipynb) |Convert audio files to text||\\n|[Translate text between languages](https://github.com/neuml/txtai/blob/master/examples/12_Translate_text_between_languages.ipynb) |Streamline machine translation and language detection||\\n\\n## Installation\\nThe easiest way to install is via pip and PyPI\\n\\n```\\npip install txtai\\n```\\n\\nPython 3.11+ is supported. Using a Python [virtual environment](https://docs.python.org/3/library/venv.html) is recommended.\\n\\nSee the detailed [install instructions](https://neuml.github.io/txtai/install) for more information covering [optional dependencies](https://neuml.github.io/txtai/install/#optional-dependencies) , [environment specific prerequisites](https://neuml.github.io/txtai/install/#environment-specific-prerequisites) , [installing from source](https://neuml.github.io/txtai/install/#install-from-source) , [conda support](https://neuml.github.io/txtai/install/#conda) and how to [run with containers](https://neuml.github.io/txtai/cloud) .\\n\\n\\n## Model guide\\nSee the table below for the current recommended models. These models all allow commercial use and offer a blend of speed and performance.\\n\\n|Component|Model(s)|\\n|---|---|\\n|[Embeddings](https://neuml.github.io/txtai/embeddings) |[all-MiniLM-L6-v2](https://hf.co/sentence-transformers/all-MiniLM-L6-v2) |\\n|[Image Captions](https://neuml.github.io/txtai/pipeline/image/caption) |[BLIP](https://hf.co/Salesforce/blip-image-captioning-base) |'}\n",
"{'indexid': 6, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': '|[Labels - Zero Shot](https://neuml.github.io/txtai/pipeline/text/labels) |[BART-Large-MNLI](https://hf.co/facebook/bart-large) |\\n|[Labels - Fixed](https://neuml.github.io/txtai/pipeline/text/labels) |Fine-tune with [training pipeline](https://neuml.github.io/txtai/pipeline/train/trainer) |\\n|[Large Language Model (LLM)](https://neuml.github.io/txtai/pipeline/text/llm) |[Llama 3.1 Instruct](https://hf.co/meta-llama/Llama-3.1-8B-Instruct) |\\n|[Summarization](https://neuml.github.io/txtai/pipeline/text/summary) |[DistilBART](https://hf.co/sshleifer/distilbart-cnn-12-6) |\\n|[Text-to-Speech](https://neuml.github.io/txtai/pipeline/audio/texttospeech) |[ESPnet JETS](https://hf.co/NeuML/ljspeech-jets-onnx) |\\n|[Transcription](https://neuml.github.io/txtai/pipeline/audio/transcription) |[Whisper](https://hf.co/openai/whisper-base) |\\n|[Translation](https://neuml.github.io/txtai/pipeline/text/translation) |[OPUS Model Series](https://hf.co/Helsinki-NLP) |\\nModels can be loaded as either a path from the Hugging Face Hub or a local directory. Model paths are optional, defaults are loaded when not specified. For tasks with no recommended model, txtai uses the default models as shown in the Hugging Face Tasks guide.\\n\\nSee the following links to learn more.\\n\\n\\n## Powered by txtai\\nThe following applications are powered by txtai.'}\n",
"{'indexid': 7, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': \"|Application|Description|\\n|---|---|\\n|[rag](https://github.com/neuml/rag) |Retrieval Augmented Generation (RAG) application|\\n|[ragdata](https://github.com/neuml/ragdata) |Build knowledge bases for RAG|\\n|[paperai](https://github.com/neuml/paperai) |Semantic search and workflows for medical/scientific papers|\\n|[annotateai](https://github.com/neuml/annotateai) |Automatically annotate papers with LLMs|\\nIn addition to this list, there are also many other [open-source projects](https://github.com/neuml/txtai/network/dependents) , [published research](https://scholar.google.com/scholar?q=txtai&hl=en&as_ylo=2022) and closed proprietary/commercial projects that have built on txtai in production.\\n\\n\\n## Further Reading\\n- [Tutorial series on Hashnode](https://neuml.hashnode.dev/series/txtai-tutorial) | [dev.to](https://dev.to/neuml/tutorial-series-on-txtai-ibg) \\n- [What's new in txtai 8.0](https://medium.com/neuml/whats-new-in-txtai-8-0-2d7d0ab4506b) | [7.0](https://medium.com/neuml/whats-new-in-txtai-7-0-855ad6a55440) | [6.0](https://medium.com/neuml/whats-new-in-txtai-6-0-7d93eeedf804) | [5.0](https://medium.com/neuml/whats-new-in-txtai-5-0-e5c75a13b101) | [4.0](https://medium.\"}\n",
"{'indexid': 8, 'id': '0', 'url': 'https://github.com/neuml/txtai', 'text': 'com/neuml/whats-new-in-txtai-4-0-bbc3a65c3d1c) \\n- [Getting started with semantic search](https://medium.com/neuml/getting-started-with-semantic-search-a9fd9d8a48cf) | [workflows](https://medium.com/neuml/getting-started-with-semantic-workflows-2fefda6165d9) | [rag](https://medium.com/neuml/getting-started-with-rag-9a0cca75f748) \\n\\n## Documentation\\n[Full documentation on txtai](https://neuml.github.io/txtai) including configuration settings for embeddings, pipelines, workflows, API and a FAQ with common questions/issues is available.\\n\\n\\n## Contributing\\nFor those who would like to contribute to txtai, please see [this guide](https://github.com/neuml/.github/blob/master/CONTRIBUTING.md) .'}\n",
+2 -4
View File
@@ -6,8 +6,6 @@
"source": [
"# OpenAI Compatible API\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one embeddings database for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"`txtai` has long been able host a [FastAPI based service](https://neuml.github.io/txtai/api/). There are clients for [Python](https://github.com/neuml/txtai.py), [JavaScript](https://github.com/neuml/txtai.js), [Java](https://github.com/neuml/txtai.java), [Rust](https://github.com/neuml/txtai.rs), [Go](https://github.com/neuml/txtai.go).\n",
"\n",
"The API service also supports hosting OpenAI-compatible API endpoints. A standard OpenAI client can then be used to connect to a `txtai` service. This enables quickly trying `txtai` with a familiar-to-use client. It's also a way to do local/offline development testing using the OpenAI client.\n",
@@ -41,7 +39,7 @@
"\n",
"# RAG pipeline configuration\n",
"rag:\n",
" path: hugging-quants/Meta-Llama-3.1-8B-Instruct-AWQ-INT4\n",
" path: Qwen/Qwen3-4B-Instruct-2507\n",
" output: flatten\n",
" system: You are a friendly assistant. You answer questions from users.\n",
" template: |\n",
@@ -70,7 +68,7 @@
"Alternatively, txtai can be directly installed and run as follows:\n",
"\n",
"```\n",
"pip install txtai[all] autoawq autoawq-kernels\n",
"pip install txtai[all]\n",
"CONFIG=/tmp/config/config.yml uvicorn \"txtai.api:app\"\n",
"```\n",
"\n",
@@ -7,8 +7,6 @@
"source": [
"# Medical RAG Research with txtai\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one AI framework for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Large Language Models (LLMs) have captured the public's attention with their impressive capabilities. The Generative AI era has reached a fever pitch with some predicting the coming rise of superintelligence.\n",
"\n",
"LLMs are far from perfect though and we're still a ways away from true AI. One big challenge is with hallucinations. Hallucinations is the term for when an LLM generates output that is factually incorrect. The alarming part of this is that on a cursory glance, it actually sounds like factual content. The default behavior of LLMs is to produce plausible answers even when no plausible answer exists. LLMs are not great at saying I don't know.\n",
-2
View File
@@ -8,8 +8,6 @@
"source": [
"# 💡 What's new in txtai 9.0\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one AI framework for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"The 9.0 release adds first class support for sparse vector models (i.e. [SPLADE](https://en.wikipedia.org/wiki/Learned_sparse_retrieval)), late interaction models (i.e. [ColBERT](https://huggingface.co/colbert-ir/colbertv2.0)), fixed dimensional encoding (i.e. [MUVERA](https://arxiv.org/abs/2405.19504)) and reranking pipelines ✨ \n",
"\n",
"The embeddings framework was overhauled to seamlessly support both sparse and dense vector models. Previously, sparse vector support was limited to keyword/term indexes. Now learned sparse retrieval models such as SPLADE are supported. These models can help improve the accuracy of retrieval/search operations, which also improves RAG and Agents.\n",
@@ -7,8 +7,6 @@
"source": [
"# GraphRAG with Wikipedia and GPT OSS\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one AI framework for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"Retrieval Augmented Generation (RAG) is one of the most popular techniques in the AI space today. RAG takes a user request, retrieves the best matching content and then plugs that context into an LLM prompt to generate an answer. When otherwise not mentioned, most assume the context is generated using a vector database query. But there is no rule that says context can't be generated with other methods. It could be a simple web query, SQL query, text index search or other traditional search.\n",
"\n",
"We also often hear the term GraphRAG. GraphRAG means different things to different people. Here we're going to build an example that uses `txtai`, [wikipedia](https://huggingface.co/datasets/NeuML/wikipedia-20250620) and [gpt-oss](https://huggingface.co/openai/gpt-oss-20b) to research a specific topic with graphs. `txtai` has a built-in graph component that automatically generates a graph network over the data loaded into an embeddings database. We'll use a pre-built embeddings database hosted on the Hugging Face Hub, [txtai-wikipedia-slim](https://hf.co/neuml/txtai-wikipedia-slim)."
@@ -7,8 +7,6 @@
"source": [
"# Accessing Low Level Vector APIs\n",
"\n",
"[txtai](https://github.com/neuml/txtai) is an all-in-one AI framework for semantic search, LLM orchestration and language model workflows.\n",
"\n",
"The primary interface to build vector databases with `txtai` is through [Embeddings instances](https://neuml.github.io/txtai/embeddings/). `txtai` also supports accessing all of it's features through lower level APIs. \n",
"\n",
"Let's dive in.\n"
@@ -0,0 +1,251 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "4c8ab3b0",
"metadata": {},
"source": [
"# RAG is more than Vector Search\n",
"\n",
"Retrieval Augmented Generation (RAG) is often associated with vector search. And while that is a primary use case, any search will do.\n",
"\n",
"- ✅ Vector Search\n",
"- ✅ Web Search\n",
"- ✅ SQL Query\n",
"\n",
"This notebook will go over a few RAG examples covering different retrieval methods. These examples require txtai 9.3+."
]
},
{
"cell_type": "markdown",
"id": "ab8a77d1",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21bebb46",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-data]\n",
"\n",
"# Download example SQL database\n",
"!wget https://huggingface.co/NeuML/txtai-wikipedia-slim/resolve/main/documents"
]
},
{
"cell_type": "markdown",
"id": "1ece2b09",
"metadata": {},
"source": [
"# RAG with Late Interaction\n",
"\n",
"The first example will cover RAG with ColBERT / Late Interaction retrieval. TxtAI 9.0 added support for [MUVERA](https://arxiv.org/abs/2405.19504) and [ColBERT](https://arxiv.org/abs/2112.01488) multi-vector ranking. \n",
"\n",
"We'll build a pipeline that reads the ColBERT v2 paper, extracts the text into sections and builds an index with a ColBERT model. Then we'll wrap that as a [Reranker pipeline](https://neuml.github.io/txtai/pipeline/text/reranker/) using the same ColBERT model. Finally a RAG pipeline will utilize this for retrieval.\n",
"\n",
"_Note: This uses the custom [ColBERT Muvera Nano](https://huggingface.co/NeuML/colbert-muvera-nano) model which is only 970K parameters! That's right thousands. It's surprisingly effective._"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "dae2e6dc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"This paper introduces ColBERTv2, a neural information retrieval model that enhances the quality and efficiency of late interaction by combining an aggressive residual compression mechanism with a denoised supervision strategy, achieving state-of-the-art performance across diverse benchmarks while reducing the model's space footprint by 6–10× compared to previous methods.\n"
]
}
],
"source": [
"from txtai import Embeddings, RAG, Textractor\n",
"from txtai.pipeline import Reranker, Similarity\n",
"\n",
"# Get text from ColBERT v2 paper\n",
"textractor = Textractor(sections=True, backend=\"docling\")\n",
"data = textractor(\"https://arxiv.org/pdf/2112.01488\")\n",
"\n",
"# MUVERA fixed dimensional encodings\n",
"embeddings = Embeddings(content=True, path=\"neuml/colbert-muvera-nano\", vectors={\"trust_remote_code\": True})\n",
"embeddings.index(data)\n",
"\n",
"# Re-rank using same late interaction model\n",
"reranker = Reranker(embeddings, Similarity(\"neuml/colbert-muvera-nano\", lateencode=True, vectors={\"trust_remote_code\": True}))\n",
"\n",
"template = \"\"\"\n",
" Answer the following question using the provided context.\n",
"\n",
" Question:\n",
" {question}\n",
"\n",
" Context:\n",
" {context}\n",
"\"\"\"\n",
"\n",
"# RAG with late interaction models\n",
"rag = RAG(reranker, \"Qwen/Qwen3-4B-Instruct-2507\", template=template, output=\"flatten\")\n",
"print(rag(\"Write a sentence abstract about this paper\", maxlength=2048))"
]
},
{
"cell_type": "markdown",
"id": "b31e46de",
"metadata": {},
"source": [
"# RAG with a Web Search\n",
"\n",
"Next we'll run a RAG pipeline using a web search as the retrieval method."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "b61b684b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Artificial intelligence (AI) is the capability of computational systems to perform tasks typically associated with human intelligence, such as learning, reasoning, problem-solving, perception, and decision-making. It involves technologies like machine learning, deep learning, and natural language processing, and enables machines to simulate human-like learning, comprehension, problem solving, decision-making, creativity, and autonomy.\n"
]
}
],
"source": [
"from smolagents import WebSearchTool\n",
"\n",
"tool = WebSearchTool()\n",
"\n",
"def websearch(queries, limit):\n",
" results = []\n",
" for query in queries:\n",
" result = [\n",
" {\"id\": i, \"text\": f'{x[\"title\"]} {x[\"description\"]}', \"score\": 1.0} for i, x in enumerate(tool.search(query))\n",
" ]\n",
" results.append(result[:limit])\n",
"\n",
" return results\n",
"\n",
"# RAG with a websearch\n",
"rag = RAG(websearch, \"Qwen/Qwen3-4B-Instruct-2507\", template=template, output=\"flatten\")\n",
"print(rag(\"What is AI?\", maxlength=2048))"
]
},
{
"cell_type": "markdown",
"id": "45c8a096",
"metadata": {},
"source": [
"# RAG with a SQL Query\n",
"\n",
"The last example we'll cover is running RAG with a SQL query. We'll use the SQL database that's a component of the [txtai-wikipedia-slim](https://huggingface.co/NeuML/txtai-wikipedia-slim) embeddings database.\n",
"\n",
"Since this is just a database with Wikipedia abstracts, we'll need a way to build a SQL query from a search query. For that we'll use an LLM to extract a keyword to use in a `LIKE` clause.\n",
"\n",
"Given that the LLM used was released in August 2025, let's ask it a question that can only be accurated answered with external data. `Who won the 2025 World Series?` which ended in November."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c7ff2a35",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"In the 2025 World Series, the Los Angeles Dodgers defeated the Toronto Blue Jays in seven games to win the championship. The series took place from October 24 to November 1 (ending early on November 2, Toronto time). Dodgers pitcher Yoshinobu Yamamoto was named the World Series MVP. The series was televised by Fox in the United States and by Sportsnet in Canada.\n"
]
}
],
"source": [
"import sqlite3\n",
"\n",
"from txtai import LLM\n",
"\n",
"def keyword(query):\n",
" return llm(f\"\"\"\n",
" Extract a keyword for this search query: {query}.\n",
" Return only text with no other formatting or explanation.\n",
" \"\"\")\n",
"\n",
"def sqlsearch(queries, limit):\n",
" results = []\n",
" sql = \"SELECT id, text FROM sections WHERE id LIKE ? LIMIT ?\"\n",
"\n",
" for query in queries:\n",
" # Extract a keyword for this search\n",
" query = keyword(query)\n",
"\n",
" # Run the SQL Query\n",
" results.append([\n",
" {\"id\": uid, \"text\": text, \"score\": 1.0}\n",
" for uid, text in cursor.execute(sql, [f\"%{query}%\", limit])\n",
" ])\n",
"\n",
" return results\n",
"\n",
"# Load the database\n",
"cursor = sqlite3.connect(\"documents\")\n",
"\n",
"# Load the LLM\n",
"llm = LLM(\"Qwen/Qwen3-4B-Instruct-2507\")\n",
"\n",
"# RAG with a SQL query\n",
"rag = RAG(sqlsearch, llm, template=template, output=\"flatten\")\n",
"print(rag(\"Tell me what happened in the 2025 World Series\", maxlength=2048))"
]
},
{
"cell_type": "markdown",
"id": "a9f78076",
"metadata": {},
"source": [
"And as we see, this answer is using the SQL database!"
]
},
{
"cell_type": "markdown",
"id": "97b1e282",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This notebook showed that RAG is about much more than vector search. With txtai 9.3+, any callable method is now supported for retrieval. Enjoy!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -0,0 +1,360 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "c65bdb85",
"metadata": {},
"source": [
"# Distilling Knowledge into Tiny LLMs\n",
"\n",
"Large Language Models (LLMs) are the magic behind AI. These massive billion and trillion parameter models have been shown to generalize well when trained on enough data.\n",
"\n",
"A big problem is that they are hard to run and expensive. So many just call LLMs through APIs such as OpenAI or Claude. Additionally, in many instances, developers spend a lot of time with complex prompt logic hoping to cover all the edge cases and believe they need a model that's large enough to handle all the rules.\n",
"\n",
"If you truly want control over your business processes, running a local model is a better choice. And the good news is that it doesn't have to be a giant and expensive multi-billion parameter model. We can finetune LLMs to handle our specific business logic, which helps us take control and limit prompt complexity. \n",
"\n",
"This notebook will show how we can distill knowledge into tiny LLMs."
]
},
{
"cell_type": "markdown",
"id": "279ecd4b",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f7bca3a",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-train] datasets"
]
},
{
"cell_type": "markdown",
"id": "c7b1b4be",
"metadata": {},
"source": [
"# The LLM\n",
"\n",
"We'll use a [600M parameter Qwen3 model](https://hf.co/qwen/qwen3-0.6b) for this example. Our target task will be translating user requests into linux commands."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e1d95dd8",
"metadata": {},
"outputs": [],
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(\"Qwen/Qwen3-0.6B\")"
]
},
{
"cell_type": "markdown",
"id": "8f276cfc",
"metadata": {},
"source": [
"Let's try one with the base model as it is."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "686c3983",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'ps -e'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm(\"\"\"\n",
"Translate the following request into a linux command. Only print the command.\n",
"\n",
"Find number of logged in users\n",
"\"\"\", maxlength=1024)"
]
},
{
"cell_type": "markdown",
"id": "dcd92414",
"metadata": {},
"source": [
"As we can see, the model actually has a good understanding and at least prints a command. But in this case it's not correct. Let's get to fine-tuning!"
]
},
{
"cell_type": "markdown",
"id": "73666982",
"metadata": {},
"source": [
"# Finetuning the LLM with knowledge\n",
"\n",
"Yes, 600M parameters is small and we can't possibly expect it to do well with everything. But the good news is that we can distill knowledge into this tiny LLM and make it better. We'll use this [linux commands dataset](https://huggingface.co/datasets/mecha-org/linux-command-dataset) from the Hugging Face Hub. We'll also use this [training pipeline from txtai](https://neuml.github.io/txtai/pipeline/train/trainer).\n",
"\n",
"First, we'll create the training dataset. We'll use the same prompt strategy from above.\n",
"\n",
"```python\n",
"\"\"\"\n",
"Translate the following request into a linux command. Only print the command.\n",
"\n",
"{user request}\n",
"\"\"\"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "43d6b563",
"metadata": {},
"outputs": [],
"source": [
"from datasets import load_dataset\n",
"from transformers import AutoTokenizer\n",
"\n",
"# LLM path\n",
"path = \"Qwen/Qwen3-0.6B\"\n",
"tokenizer = AutoTokenizer.from_pretrained(path)\n",
"\n",
"# Load the training dataset\n",
"dataset = load_dataset(\"mecha-org/linux-command-dataset\", split=\"train\")\n",
"\n",
"def prompt(row):\n",
" text = tokenizer.apply_chat_template([\n",
" {\"role\": \"system\", \"content\": \"Translate the following request into a linux command. Only print the command.\"},\n",
" {\"role\": \"user\", \"content\": row[\"input\"]},\n",
" {\"role\": \"assistant\", \"content\": row[\"output\"]}\n",
" ], tokenize=False, enable_thinking=False)\n",
"\n",
" return {\"text\": text}\n",
"\n",
"# Map to training prompts\n",
"train = dataset.map(prompt, remove_columns=[\"input\", \"output\"])"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "7f71dce0",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" <div>\n",
" \n",
" <progress value='210' max='210' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
" [210/210 01:12, Epoch 1/1]\n",
" </div>\n",
" <table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: left;\">\n",
" <th>Step</th>\n",
" <th>Training Loss</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>50</td>\n",
" <td>0.625300</td>\n",
" </tr>\n",
" <tr>\n",
" <td>100</td>\n",
" <td>0.490200</td>\n",
" </tr>\n",
" <tr>\n",
" <td>150</td>\n",
" <td>0.403300</td>\n",
" </tr>\n",
" <tr>\n",
" <td>200</td>\n",
" <td>0.391800</td>\n",
" </tr>\n",
" </tbody>\n",
"</table><p>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from txtai.pipeline import HFTrainer\n",
"\n",
"# Load the training pipeline\n",
"trainer = HFTrainer()\n",
"\n",
"# Train the model\n",
"# Set output_dir to save, trained in memory for this example\n",
"model = trainer(\n",
" \"Qwen/Qwen3-0.6B\",\n",
" train,\n",
" task=\"language-generation\",\n",
" maxlength=512,\n",
" bf16=True,\n",
" per_device_train_batch_size=4,\n",
" num_train_epochs=1,\n",
" logging_steps=50,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "68b5bc4e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'who | wc -l'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from txtai import LLM\n",
"\n",
"llm = LLM(model)\n",
"\n",
"llm([\n",
" {\"role\": \"system\", \"content\": \"Translate the following request into a linux command. Only print the command.\"},\n",
" {\"role\": \"user\", \"content\": \"Find number of logged in users\"}\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7427186d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'ls ~/'"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm([\n",
" {\"role\": \"system\", \"content\": \"Translate the following request into a linux command. Only print the command.\"},\n",
" {\"role\": \"user\", \"content\": \"List the files in my home directory\"}\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "a141d63b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'zip -r data.zip data'"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm([\n",
" {\"role\": \"system\", \"content\": \"Translate the following request into a linux command. Only print the command.\"},\n",
" {\"role\": \"user\", \"content\": \"Zip the data directory with all it's contents\"}\n",
"])"
]
},
{
"cell_type": "markdown",
"id": "fc7d0fda",
"metadata": {},
"source": [
"It even works well without the system prompt."
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "a7d0c671",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'du -sh ~'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm(\"Calculate the total amount of disk space used for my home directory. Only print the total.\")"
]
},
{
"cell_type": "markdown",
"id": "48cfcacf",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This notebook demonstrated how it's very straightforward to distill knowledge into LLMs with `txtai`. Don't always go for the giant LLM, spend a little time finetuning a tiny LLM, it is well worth it!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+377
View File
@@ -0,0 +1,377 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "f95d2373",
"metadata": {},
"source": [
"# OpenCode as a txtai LLM\n",
"\n",
"[OpenCode](https://github.com/anomalyco/opencode) is an open source AI coding agent. It's rapidly growing in popularity as an open alternative to [Claude Code](https://code.claude.com/docs/en/overview). \n",
"\n",
"OpenCode shows the power of permissive open source. It's rapidly undergoing mass adoption and as of January 2026 sits at `81K+` GitHub ⭐'s. OpenCode supports running as a [local server](https://opencode.ai/docs/server/) via `opencode serve`.\n",
"\n",
"This notebook will explore how TxtAI integrates this as a LLM pipeline."
]
},
{
"cell_type": "markdown",
"id": "a8719b92",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e00c85bc",
"metadata": {
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[api,pipeline-llm]\n",
"\n",
"# Install OpenCode if not already installed and run serve\n",
"!curl -fsSL https://opencode.ai/install | bash\n",
"!opencode serve &"
]
},
{
"cell_type": "markdown",
"id": "73ffe60e",
"metadata": {},
"source": [
"# Create a OpenCode LLM\n",
"\n",
"Now that everything is installed, let's test it out!"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0e35a304",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"print(\"Hello, World!\")\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import Markdown, display\n",
"\n",
"from txtai import LLM\n",
"\n",
"def generate(request):\n",
" display(Markdown(llm(request)))\n",
"\n",
"# Connect to OpenCode server and use default LLM provider\n",
"llm = LLM(\"opencode\")\n",
"\n",
"generate(\"Show a Python Hello World example\")"
]
},
{
"cell_type": "markdown",
"id": "55dd0fad",
"metadata": {},
"source": [
"OK, now let's try this for a more advanced use case."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b3080841",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"from txtai import Embeddings, LLM\n",
"\n",
"# Create embeddings model\n",
"embeddings = Embeddings(path=\"sentence-transformers/all-MiniLM-L6-v2\")\n",
"\n",
"# Create LLM\n",
"llm = LLM(\"huggingface/Qwen/Qwen2.5-1.5B-Instruct\")\n",
"\n",
"# Sample documents\n",
"documents = [\n",
" \"Python is a programming language created by Guido van Rossum\",\n",
" \"Machine learning is a subset of artificial intelligence\",\n",
" \"Deep learning uses neural networks with multiple layers\"\n",
"]\n",
"\n",
"# Build the index\n",
"embeddings.index([(i, doc) for i, doc in enumerate(documents)])\n",
"\n",
"# RAG function\n",
"def rag_query(question):\n",
" # Search for relevant documents\n",
" results = embeddings.search(question, 2)\n",
" \n",
" # Build context from retrieved documents\n",
" context = \" \".join([documents[result[0]] for result in results])\n",
" \n",
" # Generate response using LLM with context\n",
" prompt = f\"Context: {context}\\n\\nQuestion: {question}\\n\\nAnswer:\"\n",
" return llm(prompt)\n",
"\n",
"# Example usage\n",
"question = \"What is Python?\"\n",
"answer = rag_query(question)\n",
"print(f\"Question: {question}\")\n",
"print(f\"Answer: {answer}\")\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"generate(\"Show a simple and basic TxtAI RAG example\")"
]
},
{
"cell_type": "markdown",
"id": "b44e0309",
"metadata": {},
"source": [
"Interesting! It's not limited to Python though."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "0a2ec1b4",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```assembly\n",
"section .data\n",
" hello db 'Hello, World!', 10 ; String with newline\n",
" hello_len equ $ - hello ; Length of string\n",
"\n",
"section .text\n",
" global _start\n",
"\n",
"_start:\n",
" ; sys_write system call\n",
" mov eax, 4 ; sys_write\n",
" mov ebx, 1 ; stdout\n",
" mov ecx, hello ; message\n",
" mov edx, hello_len ; message length\n",
" int 0x80 ; kernel interrupt\n",
"\n",
" ; sys_exit system call\n",
" mov eax, 1 ; sys_exit\n",
" mov ebx, 0 ; exit code 0\n",
" int 0x80 ; kernel interrupt\n",
"```\n",
"\n",
"Compile and run:\n",
"```bash\n",
"nasm -f elf32 hello.asm -o hello.o\n",
"ld -m elf_i386 hello.o -o hello\n",
"./hello\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"generate(\"Show a x86 assembly hello world\")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "4e28d5c4",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"a = None\n",
"if a is not None:\n",
" a.startswith(\"hello\")\n",
"else:\n",
" print(\"a is None, cannot call startswith\")\n",
"```\n",
"\n",
"**What's wrong:** The variable `a` is `None`, which is a `NoneType` object. The `startswith()` method only exists for strings, not for `NoneType`. You need to check if `a` is not `None` before calling string methods on it."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"generate(\"\"\"\n",
"Fix the following error in the code below and explain what's wrong.\n",
"\n",
"Error:\n",
"AttributeError: 'NoneType' object has no attribute 'startswith'\n",
"\n",
"Code:\n",
"a = None\n",
"a.startswith(\"hello\")\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "156122f0",
"metadata": {},
"source": [
"# OpenAI-compatible Endpoint\n",
"\n",
"Now that OpenCode is integrated into the TxtAI ecosystem, it opens a lot of different opportunities. Let's say we want to host a local OpenAI compatible endpoint, no problem!\n",
"\n",
"Write the following file.\n",
"\n",
"## config.yml\n",
"\n",
"```yaml\n",
"# Enable OpenAI compat endpoint\n",
"openai: True\n",
"\n",
"llm:\n",
" path: opencode\n",
"```\n",
"\n",
"and start the following process.\n",
"\n",
"```\n",
"CONFIG=config.yml uvicorn \"txtai.api:app\"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "33057f59",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"def factorial(n):\n",
" if n < 0:\n",
" raise ValueError(\"Factorial is not defined for negative numbers\")\n",
" if n == 0 or n == 1:\n",
" return 1\n",
" result = 1\n",
" for i in range(2, n + 1):\n",
" result *= i\n",
" return result\n",
"\n",
"# Example usage:\n",
"# print(factorial(5)) # Output: 120\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import Markdown, display\n",
"\n",
"from openai import OpenAI\n",
"\n",
"client = OpenAI(\n",
" base_url=\"http://localhost:8000/v1\",\n",
" api_key=\"api-key\",\n",
")\n",
"\n",
"response = client.chat.completions.create(\n",
" messages=[{\n",
" \"role\": \"user\",\n",
" \"content\": \"Show a Python factorial function\",\n",
" }],\n",
" model=\"opencode\",\n",
")\n",
"\n",
"display(Markdown((response.choices[0].message.content)))"
]
},
{
"cell_type": "markdown",
"id": "58a9169b",
"metadata": {},
"source": [
"Just like before we get an answer! This time via the OpenAI client. Fun times."
]
},
{
"cell_type": "markdown",
"id": "47f9dbbd",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This notebook showed how to connect TxtAI and OpenCode. This will lead to some interesting integrations. One such example is [ncoder](https://github.com/neuml/ncoder), an AI coding agent that integrates with Jupyter Notebooks. Stay tuned for more!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+358
View File
@@ -0,0 +1,358 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "5a13697b",
"metadata": {},
"source": [
"# Agentic College Search\n",
"\n",
"This example will demonstrate how to use `txtai` agents to identify list of strong engineering colleges with baseball programs 🎓⚙️⚾.\n",
"\n",
"We'll setup a default [agents.md](https://github.com/agentsmd/agents.md) file and then give an LLM access to the web.\n",
"\n",
"Let's get started!"
]
},
{
"cell_type": "markdown",
"id": "face0f9e",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f5da3842",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent]"
]
},
{
"cell_type": "markdown",
"id": "f9a6a500",
"metadata": {},
"source": [
"# Define an `agents.md` file\n",
"\n",
"Next, we'll define an agents.md file. This file defines default behavior for our college search agent and is inserted into the system prompt of every agent run."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4e0c500d",
"metadata": {},
"outputs": [],
"source": [
"%%writefile agents.md\n",
"# College Researcher\n",
"\n",
"You are a college research agent. Your job is to help find the best matching schools given a set of criteria.\n",
"\n",
"## Academics\n",
"\n",
"Work to match the request with a set of schools that match the academic requirements\n",
"\n",
"## Athletics\n",
"\n",
"Some requests may be interested in collegiate athletics. Make sure to balance that with other parts of the request."
]
},
{
"cell_type": "markdown",
"id": "83dee7de",
"metadata": {},
"source": [
"# Identify the Top 20 schools\n",
"\n",
"Next, let's run a prompt to identify the best 20 colleges given a set of criteria.\n",
"\n",
"First, we'll setup the scaffolding code to create and run an agent. We'll use a [Qwen3 4B non-thinking LLM](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507) as the agent's model. We'll add the `websearch` and `webview` tools to the agent along with the `agents.md` file previously created.\n",
"\n",
"Additionally, we'll add a sliding window of the last 5 responses as \"agent memory\". This will help create a rolling dialogue. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "410f2585",
"metadata": {},
"outputs": [],
"source": [
"from txtai import Agent\n",
"from IPython.display import display, Markdown\n",
"\n",
"def run(query, reset=False):\n",
" answer = agent(query, maxlength=60000, reset=reset)\n",
" display(Markdown(answer))\n",
"\n",
"agent = Agent(model=\"Qwen/Qwen3-4B-Instruct-2507\", tools=[\"websearch\", \"webview\"], memory=5, instructions=\"agents.md\", max_steps=50)"
]
},
{
"cell_type": "markdown",
"id": "53aa302b",
"metadata": {},
"source": [
"Now we can run the search. To come up with our list of colleges, a series of web searches were executed by the agent. It's like if you had the superpower 🚀 to kick off 10+ web searches with slight variations each time as you go. It's a rapid fire set of operations to collect information for the LLM for analysis.\n",
"\n",
"_Note: The output below has the `verbosity_level` set to 0 for brevity. If you run this again, you'll get the full details with each step._"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f2d1ef2e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d4b702; text-decoration-color: #d4b702\">╭──────────────────────────────────────────────────── </span><span style=\"color: #d4b702; text-decoration-color: #d4b702; font-weight: bold\">New run</span><span style=\"color: #d4b702; text-decoration-color: #d4b702\"> ────────────────────────────────────────────────────╮</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">List 20 universities located in the Mid-Atlantic or Northeast that would be good candidates to consider with </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">top 50 engineering programs and an active baseball team. Visit websites covering the top engineering schools in</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">the Mid-Atlantic and Northeast. Add a rationale for each of the picks in a few words.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">╰─ PipelineModel - Qwen/Qwen3-4B-Instruct-2507 ───────────────────────────────────────────────────────────────────╯</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[38;2;212;183;2m╭─\u001b[0m\u001b[38;2;212;183;2m───────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m \u001b[0m\u001b[1;38;2;212;183;2mNew run\u001b[0m\u001b[38;2;212;183;2m \u001b[0m\u001b[38;2;212;183;2m───────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m─╮\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mList 20 universities located in the Mid-Atlantic or Northeast that would be good candidates to consider with \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mtop 50 engineering programs and an active baseball team. Visit websites covering the top engineering schools in\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mthe Mid-Atlantic and Northeast. Add a rationale for each of the picks in a few words.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m╰─\u001b[0m\u001b[38;2;212;183;2m PipelineModel - Qwen/Qwen3-4B-Instruct-2507 \u001b[0m\u001b[38;2;212;183;2m──────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m─╯\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"Here are 20 universities in the Mid-Atlantic or Northeast with top 50 engineering programs and active baseball teams, along with a brief rationale for each:\n",
"\n",
"1. **Massachusetts Institute of Technology (MIT)** – Top-ranked engineering program in the Northeast with a strong research focus and active baseball team.\n",
"2. **Princeton University** – Renowned for engineering excellence and competitive baseball in the Ivy League.\n",
"3. **Columbia University** – Strong engineering programs and a consistently active baseball team.\n",
"4. **University of Pennsylvania** – Top-tier engineering and a well-established baseball program in the Ivy League.\n",
"5. **Carnegie Mellon University** – Leading in computer and engineering fields with a competitive baseball team.\n",
"6. **Cornell University** – Excellent engineering programs and a strong baseball presence.\n",
"7. **Northeastern University** – Strong engineering programs and active baseball team.\n",
"8. **New York University** – Top engineering programs with a competitive baseball team.\n",
"9. **Rensselaer Polytechnic Institute (RPI)** – Strong engineering focus and active baseball in the Liberty League.\n",
"10. **Rutgers University** – Top engineering programs and a well-established baseball team.\n",
"11. **Lehigh University** – Strong engineering and active baseball in the Patriot League.\n",
"12. **University of Connecticut** – Top engineering programs and a competitive baseball team.\n",
"13. **University of Massachusetts Amherst** – Solid engineering programs and active baseball.\n",
"14. **University of Massachusetts Lowell** – Strong engineering and active baseball in the America East Conference.\n",
"15. **Syracuse University** – Top engineering programs and a competitive baseball team.\n",
"16. **Boston University** – Strong engineering and active baseball.\n",
"17. **Dartmouth College** – Excellent engineering programs and competitive baseball.\n",
"18. **Brown University** – Top engineering and active baseball.\n",
"19. **Bucknell University** – Solid engineering and active baseball.\n",
"20. **University of Rochester** – Strong engineering and competitive baseball.\n",
"\n",
"These institutions combine top-tier engineering programs with active collegiate baseball teams, making them excellent candidates for students seeking both academic excellence and athletic engagement."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run((\n",
" \"List 20 universities located in the Mid-Atlantic or Northeast that would be good candidates to consider \"\n",
" \"with top 50 engineering programs and an active baseball team. \"\n",
" \"Visit websites covering the top engineering schools in the Mid-Atlantic and Northeast. \"\n",
" \"Add a rationale for each of the picks in a few words. \"\n",
"))"
]
},
{
"cell_type": "markdown",
"id": "a7533137",
"metadata": {},
"source": [
"Interesting! Looks like quite an impressive list of colleges. This output is the product of taking the results of 10+ web searches and analyzing the results with an LLM. A very practical and realistic use of \"Agentic AI\". This is a great list of strong engineering schools with baseball programs 🎓⚙️⚾.\n",
"\n",
"Let's narrow it down to the top 5 engineering schools."
]
},
{
"cell_type": "code",
"execution_count": 105,
"id": "5e261825",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d4b702; text-decoration-color: #d4b702\">╭──────────────────────────────────────────────────── </span><span style=\"color: #d4b702; text-decoration-color: #d4b702; font-weight: bold\">New run</span><span style=\"color: #d4b702; text-decoration-color: #d4b702\"> ────────────────────────────────────────────────────╮</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">Read the list below and pick the Top 5 engineering programs.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">Use the following conversation history to help answer the question above.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">User: List 20 universities located in the Mid-Atlantic or Northeast that would be good candidates to consider </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">with top 50 engineering programs and an active baseball team. Visit websites covering the top engineering </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">schools in the Mid-Atlantic and Northeast. Add a rationale for each of the picks in a few words. </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">Assistant: Here are 20 universities in the Mid-Atlantic or Northeast with top 50 engineering programs and </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">active baseball teams, along with a brief rationale for each:</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">1. **Massachusetts Institute of Technology (MIT)** – Top-ranked engineering program in the Northeast with a </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">strong research focus and active baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">2. **Princeton University** – Renowned for engineering excellence and competitive baseball in the Ivy League.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">3. **Columbia University** – Strong engineering programs and a consistently active baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">4. **University of Pennsylvania** – Top-tier engineering and a well-established baseball program in the Ivy </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">League.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">5. **Carnegie Mellon University** – Leading in computer and engineering fields with a competitive baseball </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">6. **Cornell University** – Excellent engineering programs and a strong baseball presence.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">7. **Northeastern University** – Strong engineering programs and active baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">8. **New York University** – Top engineering programs with a competitive baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">9. **Rensselaer Polytechnic Institute (RPI)** – Strong engineering focus and active baseball in the Liberty </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">League.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">10. **Rutgers University** – Top engineering programs and a well-established baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">11. **Lehigh University** – Strong engineering and active baseball in the Patriot League.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">12. **University of Connecticut** – Top engineering programs and a competitive baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">13. **University of Massachusetts Amherst** – Solid engineering programs and active baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">14. **University of Massachusetts Lowell** – Strong engineering and active baseball in the America East </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">Conference.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">15. **Syracuse University** – Top engineering programs and a competitive baseball team.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">16. **Boston University** – Strong engineering and active baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">17. **Dartmouth College** – Excellent engineering programs and competitive baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">18. **Brown University** – Top engineering and active baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">19. **Bucknell University** – Solid engineering and active baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">20. **University of Rochester** – Strong engineering and competitive baseball.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">These institutions combine top-tier engineering programs with active collegiate baseball teams, making them </span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">excellent candidates for students seeking both academic excellence and athletic engagement.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"font-weight: bold\">If the history is irrelevant, forget it and use other tools to answer the question.</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span> <span style=\"color: #d4b702; text-decoration-color: #d4b702\">│</span>\n",
"<span style=\"color: #d4b702; text-decoration-color: #d4b702\">╰─ PipelineModel - Qwen/Qwen3-4B-Instruct-2507 ───────────────────────────────────────────────────────────────────╯</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[38;2;212;183;2m╭─\u001b[0m\u001b[38;2;212;183;2m───────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m \u001b[0m\u001b[1;38;2;212;183;2mNew run\u001b[0m\u001b[38;2;212;183;2m \u001b[0m\u001b[38;2;212;183;2m───────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m─╮\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mRead the list below and pick the Top 5 engineering programs.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mUse the following conversation history to help answer the question above.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mUser: List 20 universities located in the Mid-Atlantic or Northeast that would be good candidates to consider \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mwith top 50 engineering programs and an active baseball team. Visit websites covering the top engineering \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mschools in the Mid-Atlantic and Northeast. Add a rationale for each of the picks in a few words. \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mAssistant: Here are 20 universities in the Mid-Atlantic or Northeast with top 50 engineering programs and \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mactive baseball teams, along with a brief rationale for each:\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m1. **Massachusetts Institute of Technology (MIT)** – Top-ranked engineering program in the Northeast with a \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mstrong research focus and active baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m2. **Princeton University** – Renowned for engineering excellence and competitive baseball in the Ivy League.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m3. **Columbia University** – Strong engineering programs and a consistently active baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m4. **University of Pennsylvania** – Top-tier engineering and a well-established baseball program in the Ivy \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mLeague.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m5. **Carnegie Mellon University** – Leading in computer and engineering fields with a competitive baseball \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mteam.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m6. **Cornell University** – Excellent engineering programs and a strong baseball presence.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m7. **Northeastern University** – Strong engineering programs and active baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m8. **New York University** – Top engineering programs with a competitive baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m9. **Rensselaer Polytechnic Institute (RPI)** – Strong engineering focus and active baseball in the Liberty \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mLeague.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m10. **Rutgers University** – Top engineering programs and a well-established baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m11. **Lehigh University** – Strong engineering and active baseball in the Patriot League.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m12. **University of Connecticut** – Top engineering programs and a competitive baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m13. **University of Massachusetts Amherst** – Solid engineering programs and active baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m14. **University of Massachusetts Lowell** – Strong engineering and active baseball in the America East \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mConference.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m15. **Syracuse University** – Top engineering programs and a competitive baseball team.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m16. **Boston University** – Strong engineering and active baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m17. **Dartmouth College** – Excellent engineering programs and competitive baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m18. **Brown University** – Top engineering and active baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m19. **Bucknell University** – Solid engineering and active baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1m20. **University of Rochester** – Strong engineering and competitive baseball.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mThese institutions combine top-tier engineering programs with active collegiate baseball teams, making them \u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mexcellent candidates for students seeking both academic excellence and athletic engagement.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[1mIf the history is irrelevant, forget it and use other tools to answer the question.\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m│\u001b[0m \u001b[38;2;212;183;2m│\u001b[0m\n",
"\u001b[38;2;212;183;2m╰─\u001b[0m\u001b[38;2;212;183;2m PipelineModel - Qwen/Qwen3-4B-Instruct-2507 \u001b[0m\u001b[38;2;212;183;2m──────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;212;183;2m─╯\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/markdown": [
"The top 5 engineering programs from the list of universities in the Mid-Atlantic or Northeast with active baseball teams are:\n",
"\n",
"1. **Massachusetts Institute of Technology (MIT)** – Top-ranked engineering program in the Northeast with a strong research focus and active baseball team.\n",
"2. **Princeton University** – Renowned for engineering excellence and competitive baseball in the Ivy League.\n",
"3. **Carnegie Mellon University** – Leading in computer and engineering fields with a competitive baseball team.\n",
"4. **Cornell University** – Excellent engineering programs and a strong baseball presence.\n",
"5. **University of Pennsylvania** – Top-tier engineering and a well-established baseball program in the Ivy League.\n",
"\n",
"These schools stand out due to their exceptional engineering programs and active collegiate baseball teams, offering a balanced academic and athletic experience."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run(\"Read the list below and pick the Top 5 engineering programs.\")"
]
},
{
"cell_type": "markdown",
"id": "e6c27f16",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This example showed how to run an Agentic Loop that identified the best set of colleges to research further. It's an agent with memory and can be used to build an ongoing dialogue with an agent. Give it a try!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+410
View File
@@ -0,0 +1,410 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "8d8cb3ad",
"metadata": {},
"source": [
"# TxtAI got skills\n",
"\n",
"This example will demonstrate how to use `txtai` agents with [`skill.md`](https://agentskills.io/specification) files.\n",
"\n",
"We'll setup a `skill.md` file with details on how to use TxtAI and run a series of agent requests.\n",
"\n",
"Let's get started!"
]
},
{
"cell_type": "markdown",
"id": "00a5a0ea",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0ff7aa19",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[agent]"
]
},
{
"cell_type": "markdown",
"id": "98bcd5c3",
"metadata": {},
"source": [
"# Define a `skill.md` file\n",
"\n",
"Next, we'll create our `skill.md` file. This file has examples on how to build embeddings databases, how to use re-ranker pipelines, RAG pipelines and more.\n",
"\n",
"The upside of a `skill.md` file vs an `agents.md` file is that it can be dynamically added to the agent context. The description helps the agent decide if the `skill` is necessary given the request. Think of it like a dynamic knowledge base that's easy to modify."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "49179643",
"metadata": {},
"outputs": [],
"source": [
"%%writefile skill.md\n",
"---\n",
"name: txtai\n",
"description: Examples on how to build txtai embeddings databases, txtai RAG pipelines, txtai reranker pipelines and txtai translation pipelines\n",
"---\n",
"\n",
"# Build an embeddings database\n",
"\n",
"```python\n",
"from txtai import Embeddings\n",
"\n",
"# Create embeddings model, backed by sentence-transformers & transformers\n",
"embeddings = Embeddings(path=\"sentence-transformers/nli-mpnet-base-v2\")\n",
"\n",
"data = [\n",
" \"US tops 5 million confirmed virus cases\",\n",
" \"Canada's last fully intact ice shelf has suddenly collapsed, \" +\n",
" \"forming a Manhattan-sized iceberg\",\n",
" \"Beijing mobilises invasion craft along coast as Taiwan tensions escalate\",\n",
" \"The National Park Service warns against sacrificing slower friends \" +\n",
" \"in a bear attack\",\n",
" \"Maine man wins $1M from $25 lottery ticket\",\n",
" \"Make huge profits without work, earn up to $100,000 a day\"\n",
"]\n",
"\n",
"# Index the list of text\n",
"embeddings.index(data)\n",
"```\n",
"\n",
"# Search an embeddings database\n",
"\n",
"```python\n",
"embeddings.search(\"Search query\")\n",
"```\n",
"\n",
"# Build a RAG pipeline\n",
"\n",
"```python\n",
"from txtai import Embeddings, RAG\n",
"\n",
"# Input data\n",
"data = [\n",
" \"US tops 5 million confirmed virus cases\",\n",
" \"Canada's last fully intact ice shelf has suddenly collapsed, \" +\n",
" \"forming a Manhattan-sized iceberg\",\n",
" \"Beijing mobilises invasion craft along coast as Taiwan tensions escalate\",\n",
" \"The National Park Service warns against sacrificing slower friends \" +\n",
" \"in a bear attack\",\n",
" \"Maine man wins $1M from $25 lottery ticket\",\n",
" \"Make huge profits without work, earn up to $100,000 a day\"\n",
"]\n",
"\n",
"# Build embeddings index\n",
"embeddings = Embeddings(content=True)\n",
"embeddings.index(data)\n",
"\n",
"# Create the RAG pipeline\n",
"rag = RAG(embeddings, \"Qwen/Qwen3-0.6B\", template=\"\"\"\n",
" Answer the following question using the provided context.\n",
"\n",
" Question:\n",
" {question}\n",
"\n",
" Context:\n",
" {context}\n",
"\"\"\")\n",
"\n",
"# Run RAG pipeline\n",
"rag(\"What was won?\")\n",
"```\n",
"\n",
"# Translate text from English into French\n",
"\n",
"```python\n",
"from txtai.pipeline import Translation\n",
"\n",
"# Create and run pipeline\n",
"translate = Translation()\n",
"translate(\"This is a test translation\", \"fr\")\n",
"```\n",
"\n",
"# Re-ranker pipeline\n",
"\n",
"```python\n",
"from txtai import Embeddings\n",
"from txtai.pipeline import Reranker, Similarity\n",
"\n",
"# Embeddings instance\n",
"embeddings = Embeddings()\n",
"embeddings.load(provider=\"huggingface-hub\", container=\"neuml/txtai-wikipedia\")\n",
"\n",
"# Similarity instance\n",
"similarity = Similarity(path=\"colbert-ir/colbertv2.0\", lateencode=True)\n",
"\n",
"# Reranking pipeline\n",
"reranker = Reranker(embeddings, similarity)\n",
"reranker(\"Tell me about AI\")\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "4ed26969",
"metadata": {},
"source": [
"# Query for TxtAI questions\n",
"\n",
"Now, let's try this out and see if the LLM is smart enough to use the defined skill vs. going out on the web.\n",
"\n",
"Let's setup the scaffolding code to create and run an agent. We'll use a [Qwen3 4B non-thinking LLM](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507) as the agent's model. We'll add the `websearch` and `webview` tools to the agent along with the `skill.md` file previously created.\n",
"\n",
"Additionally, we'll add a sliding window of the last 2 responses as \"agent memory\". This will help create a rolling dialogue. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b6a1aaf1",
"metadata": {},
"outputs": [],
"source": [
"from txtai import Agent\n",
"from IPython.display import display, Markdown\n",
"\n",
"def run(query, reset=False):\n",
" answer = agent(query, maxlength=50000, reset=reset)\n",
" display(Markdown(answer))\n",
"\n",
"agent = Agent(\n",
" model=\"Qwen/Qwen3-4B-Instruct-2507\",\n",
" tools=[\"websearch\", \"webview\", \"skill.md\"],\n",
" memory=2,\n",
" verbosity_level=0\n",
")"
]
},
{
"cell_type": "markdown",
"id": "19302f54",
"metadata": {},
"source": [
"First, we'll ask how to build a TxtAI embeddings database."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "121d0b8a",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"To create a txtai embeddings program that indexes data, use the following Python code:\n",
"\n",
"```python\n",
"from txtai import Embeddings\n",
"\n",
"# Create embeddings model using sentence-transformers\n",
"embeddings = Embeddings(path=\"sentence-transformers/nli-mpnet-base-v2\")\n",
"\n",
"# Sample data to index\n",
"data = [\n",
" \"US tops 5 million confirmed virus cases\",\n",
" \"Canada's last fully intact ice shelf has suddenly collapsed, \" +\n",
" \"forming a Manhattan-sized iceberg\",\n",
" \"Beijing mobilises invasion craft along coast as Taiwan tensions escalate\",\n",
" \"The National Park Service warns against sacrificing slower friends \" +\n",
" \"in a bear attack\",\n",
" \"Maine man wins $1M from $25 lottery ticket\",\n",
" \"Make huge profits without work, earn up to $100,000 a day\"\n",
"]\n",
"\n",
"# Index the data\n",
"embeddings.index(data)\n",
"```\n",
"\n",
"This program initializes an embeddings database using the `sentence-transformers/nli-mpnet-base-v2` model and indexes a list of text data. The indexed data can later be searched or used in other applications like retrieval, RAG, or translation."
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run(\"Write a txtai embeddings program that indexes data\")"
]
},
{
"cell_type": "markdown",
"id": "f723e07f",
"metadata": {},
"source": [
"The Agent pulled the correct section from the `skill.md` file. Now, let's look for an example on how to use a re-ranker pipeline."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "221a590c",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"from txtai import Embeddings\n",
"from txtai.pipeline import Reranker, Similarity\n",
"\n",
"# Embeddings instance\n",
"embeddings = Embeddings()\n",
"embeddings.load(provider=\"huggingface-hub\", container=\"neuml/txtai-wikipedia\")\n",
"\n",
"# Similarity instance\n",
"similarity = Similarity(path=\"colbert-ir/colbertv2.0\", lateencode=True)\n",
"\n",
"# Reranking pipeline\n",
"reranker = Reranker(embeddings, similarity)\n",
"reranker(\"Tell me about AI\")\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run(\"Write a txtai re-ranker pipeline\")"
]
},
{
"cell_type": "markdown",
"id": "4af3a6b6",
"metadata": {},
"source": [
"Great! This also works. But remember we have access to an LLM here. It doesn't have to blindly just pull the text. Let's ask it to modify the last example."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c9f1eed4",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"from txtai import Embeddings\n",
"from txtai.pipeline import Reranker, Similarity\n",
"\n",
"# Embeddings instance\n",
"embeddings = Embeddings()\n",
"embeddings.load(provider=\"huggingface-hub\", container=\"neuml/txtai-wikipedia\")\n",
"\n",
"# Similarity instance with a different reranker model and lateencode disabled\n",
"similarity = Similarity(path=\"BAAI/bge-reranker-base\", lateencode=False)\n",
"\n",
"# Reranking pipeline\n",
"reranker = Reranker(embeddings, similarity)\n",
"reranker(\"Tell me about AI\")\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run(\"Update the similarity path to use another reranker model. Disable lateencode.\")"
]
},
{
"cell_type": "markdown",
"id": "4a3bb21e",
"metadata": {},
"source": [
"Notice it just edited the code with a different reranker model and even added a comment to note this change.\n",
"\n",
"We can also clear the rolling dialogue and start fresh. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ad53f7a8",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"```python\n",
"from txtai.pipeline import Translation\n",
"\n",
"# Create and run pipeline for English to Spanish translation\n",
"translate = Translation()\n",
"translated_text = translate(\"This is a test translation\", \"es\")\n",
"print(translated_text)\n",
"```"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"run(\"Write a txtai program that translate text from English to Spanish\", reset=True)"
]
},
{
"cell_type": "markdown",
"id": "007daee0",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This example shows how to add a `skill.md` file to `txtai` agents. Go give it a try!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.19"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
File diff suppressed because it is too large Load Diff
+337
View File
@@ -0,0 +1,337 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "40f124c0",
"metadata": {},
"source": [
"# Progressive Distillation\n",
"\n",
"Now that almost everyone has thought about or is actively integrating AI workflows into their projects, some might ask is this all worth the cost? Many think the current economics of the AI space don't scale and that there will be upward price movement. Others still might not be comfortable with sending their data to remote services for processing. Then there is the crowd that wants to deploy models in small spaces with limited compute.\n",
"\n",
"Are there ways we can deploy small models locally and run at a lower cost? Yes with [Knowledge Distillation](https://en.wikipedia.org/wiki/Knowledge_distillation). Knowledge distillation can get a bad rap due to it's questionable use in training some Large Language Models (LLMs). But it's a perfectly valid way to transfer performance from a larger model to a smaller one. Especially when both models are yours and/or open. \n",
"\n",
"This notebook will explore progressive distillation which is a technique to incrementally transfer knowledge from a series of larger teacher models into a smaller student."
]
},
{
"cell_type": "markdown",
"id": "f4aad867",
"metadata": {},
"source": [
"# Install dependencies\n",
"\n",
"Install `txtai` and all dependencies."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "16e2c760",
"metadata": {},
"outputs": [],
"source": [
"%%capture\n",
"!pip install git+https://github.com/neuml/txtai#egg=txtai[pipeline-train] datasets"
]
},
{
"cell_type": "markdown",
"id": "e3a23082",
"metadata": {},
"source": [
"# Setup the Training Pipeline\n",
"\n",
"The first step we need to do is setup up the training pipeline. We'll use the Hugging Face Training framework to build a series of models.\n",
"\n",
"The following code establishes a `train` method, `test` method and loads the classification training data."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ea7ee576",
"metadata": {},
"outputs": [],
"source": [
"from datasets import load_dataset\n",
"from transformers import AutoModelForSequenceClassification, AutoTokenizer\n",
"from txtai.pipeline import HFTrainer, Labels\n",
"\n",
"def train(teacher, student, distillation, **kwargs):\n",
" trainer = HFTrainer()\n",
"\n",
" model = AutoModelForSequenceClassification.from_pretrained(student, trust_remote_code=True)\n",
" tokenizer = AutoTokenizer.from_pretrained(student, trust_remote_code=True)\n",
"\n",
" return trainer(\n",
" (model, tokenizer),\n",
" ds[\"train\"],\n",
" columns=(\"sentence\", \"label\"),\n",
" maxlength=maxlength,\n",
" teacher=teacher,\n",
" distillation=distillation,\n",
" **kwargs\n",
" )\n",
"\n",
"def test(model):\n",
" labels = Labels(model, dynamic=False, trust_remote_code=True)\n",
"\n",
" # Determine accuracy on test set\n",
" results = [row[\"label\"] == labels(row[\"sentence\"], max_length=maxlength)[0][0] for row in ds[\"validation\"]]\n",
" print(sum(results) / len(ds[\"validation\"]))\n",
"\n",
"# Hugging Face dataset\n",
"ds = load_dataset(\"nyu-mll/glue\", \"sst2\")\n",
"maxlength = 128"
]
},
{
"cell_type": "markdown",
"id": "732fad7d",
"metadata": {},
"source": [
"# Progressive Distillation\n",
"\n",
"We're going to build a [bert-hash-femto](https://huggingface.co/NeuML/bert-hash-femto) classifier which is a extremely small 250K parameter model. This model was pretrained using the same recipe as [BERT](https://arxiv.org/abs/1810.04805). The paper [Well-Read Students Learn Better: On the Importance of Pre-training Compact Models](https://arxiv.org/abs/1908.08962) established that small models perform better with Knowledge Distillation tasks when they are pretrained. [This article](https://huggingface.co/blog/NeuML/bert-hash-embeddings) is also a good source for more information on the topic.\n",
"\n",
"The next series of steps will do the following:\n",
"\n",
"- Train a [BERT Mini](https://huggingface.co/google/bert_uncased_L-4_H-256_A-4) model using a [BERT Large](https://huggingface.co/assemblyai/bert-large-uncased-sst2) teacher\n",
"- Train a [BERT Tiny](https://huggingface.co/google/bert_uncased_L-2_H-128_A-2) model using the BERT Mini teacher above\n",
"- Train a [BERT Hash Femto](https://huggingface.co/NeuML/bert-hash-femto) model using the BERT Tiny teacher above\n",
"\n",
"This path goes from a 11M parameter model -> 4.4M parameter model -> 250K parameter model\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "43baccd6",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[transformers] \u001b[1mBertForSequenceClassification LOAD REPORT\u001b[0m from: google/bert_uncased_L-4_H-256_A-4\n",
"Key | Status | \n",
"-------------------------------------------+------------+-\n",
"cls.predictions.transform.dense.weight | UNEXPECTED | \n",
"cls.predictions.decoder.bias | UNEXPECTED | \n",
"cls.predictions.transform.LayerNorm.bias | UNEXPECTED | \n",
"cls.predictions.decoder.weight | UNEXPECTED | \n",
"cls.seq_relationship.bias | UNEXPECTED | \n",
"cls.seq_relationship.weight | UNEXPECTED | \n",
"cls.predictions.transform.dense.bias | UNEXPECTED | \n",
"cls.predictions.bias | UNEXPECTED | \n",
"cls.predictions.transform.LayerNorm.weight | UNEXPECTED | \n",
"classifier.weight | MISSING | \n",
"classifier.bias | MISSING | \n",
"\n",
"Notes:\n",
"- UNEXPECTED:\tcan be ignored when loading from different task/architecture; not ok if you expect identical arch.\n",
"- MISSING:\tthose params were newly initialized because missing from the checkpoint. Consider training on your downstream task.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.875\n"
]
}
],
"source": [
"test(train(\n",
" \"assemblyai/bert-large-uncased-sst2\",\n",
" \"google/bert_uncased_L-4_H-256_A-4\",\n",
" (1.0, 1.0),\n",
" learning_rate=1e-4,\n",
" num_train_epochs=5,\n",
" per_device_train_batch_size=32,\n",
" output_dir=\"bert-mini-sst2\"\n",
"))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9ba3158e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[transformers] \u001b[1mBertForSequenceClassification LOAD REPORT\u001b[0m from: google/bert_uncased_L-2_H-128_A-2\n",
"Key | Status | \n",
"-------------------------------------------+------------+-\n",
"cls.predictions.transform.dense.weight | UNEXPECTED | \n",
"cls.predictions.transform.LayerNorm.bias | UNEXPECTED | \n",
"cls.seq_relationship.weight | UNEXPECTED | \n",
"cls.seq_relationship.bias | UNEXPECTED | \n",
"cls.predictions.transform.dense.bias | UNEXPECTED | \n",
"cls.predictions.bias | UNEXPECTED | \n",
"cls.predictions.transform.LayerNorm.weight | UNEXPECTED | \n",
"classifier.weight | MISSING | \n",
"classifier.bias | MISSING | \n",
"\n",
"Notes:\n",
"- UNEXPECTED:\tcan be ignored when loading from different task/architecture; not ok if you expect identical arch.\n",
"- MISSING:\tthose params were newly initialized because missing from the checkpoint. Consider training on your downstream task.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.8325688073394495\n"
]
}
],
"source": [
"test(train(\n",
" \"bert-mini-sst2\",\n",
" \"google/bert_uncased_L-2_H-128_A-2\",\n",
" (1.0, 1.0),\n",
" learning_rate=1e-4,\n",
" num_train_epochs=5,\n",
" per_device_train_batch_size=32,\n",
" output_dir=\"bert-tiny-sst2\"\n",
"))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "e98d950e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[transformers] \u001b[1mBertHashForSequenceClassification LOAD REPORT\u001b[0m from: neuml/bert-hash-femto\n",
"Key | Status | \n",
"-------------------------+---------+-\n",
"bert.pooler.dense.bias | MISSING | \n",
"bert.pooler.dense.weight | MISSING | \n",
"classifier.bias | MISSING | \n",
"classifier.weight | MISSING | \n",
"\n",
"Notes:\n",
"- MISSING:\tthose params were newly initialized because missing from the checkpoint. Consider training on your downstream task.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.8084862385321101\n"
]
}
],
"source": [
"test(train(\n",
" \"bert-tiny-sst2\",\n",
" \"neuml/bert-hash-femto\",\n",
" (1.0, 1.0),\n",
" learning_rate=3e-4,\n",
" num_train_epochs=5,\n",
" per_device_train_batch_size=32,\n",
" output_dir=\"bert-femto-sst2\"\n",
"))"
]
},
{
"cell_type": "markdown",
"id": "5f1c94e7",
"metadata": {},
"source": [
"Let's look at the performance. The 11M parameter model registered an accuracy score of `0.8750` on the SST2 dev set. Then the 4M parameter model scored `0.8326` and finally the tiny femto model scored `0.8085`. As we can see each score got progressively worse but each model has less capability. Let's train a femto model directly to compare."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "b89d8292",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[transformers] \u001b[1mBertHashForSequenceClassification LOAD REPORT\u001b[0m from: neuml/bert-hash-femto\n",
"Key | Status | \n",
"-------------------------+---------+-\n",
"bert.pooler.dense.bias | MISSING | \n",
"bert.pooler.dense.weight | MISSING | \n",
"classifier.bias | MISSING | \n",
"classifier.weight | MISSING | \n",
"\n",
"Notes:\n",
"- MISSING:\tthose params were newly initialized because missing from the checkpoint. Consider training on your downstream task.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.801605504587156\n"
]
}
],
"source": [
"test(train(\n",
" None,\n",
" \"neuml/bert-hash-femto\",\n",
" None,\n",
" learning_rate=3e-4,\n",
" num_train_epochs=5,\n",
" per_device_train_batch_size=32,\n",
" output_dir=\"bert-femto-sst2\"\n",
"))"
]
},
{
"cell_type": "markdown",
"id": "4864b8d2",
"metadata": {},
"source": [
"This scored `0.8016` a sizable shift down from the progressively distilled model. Now keep in mind the femto model only has `250K` parameters but we gave it a sizable accuracy boost within it's capabilities."
]
},
{
"cell_type": "markdown",
"id": "e4e04226",
"metadata": {},
"source": [
"# Wrapping up\n",
"\n",
"This example showed how progressive distillation can boost overall model performance, especially for tiny models. Incrementally compressing knowledge into a series of smaller subsets enabled the final model to learn more efficiently than directly training the model on the dataset without distillation. Put progressive distillation in the toolkit when working with tiny models!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "local",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.20"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+80
View File
@@ -0,0 +1,80 @@
"""
Agent Quick Start
Easy to use way to get started with AI Agents.
TxtAI has many example notebooks covering everything the framework provides
Examples: https://neuml.github.io/txtai/examples
Install TxtAI
pip install txtai[agent]
"""
# pylint: disable=C0103
from datetime import datetime
from txtai import Agent
# Step 1: Define your Embeddings database
#
# Replace provider/container with a path to a local Embeddings database
# See RAG Quickstart for an example of building your own custom database
embeddings = {
"name": "wikipedia",
"description": "Searches a Wikipedia database",
# "path": "path to your embeddings database"
"provider": "huggingface-hub",
"container": "neuml/txtai-wikipedia",
}
# Step 2: Define other tools
#
# Add any Python function. Just need to describe it.
def today() -> str:
"""
Gets the current date and time
Returns:
current date and time
"""
return datetime.today().isoformat()
# Step 3: Create a list of available tools
#
# Combine defined tools with default tools
tools = [
embeddings, # Embeddings database with YOUR data
today, # Python function
"websearch", # Runs a websearch using default engine
"webview", # Loads a web page
]
# Step 4: Set LLM configuration
#
# LLM APIs
# model = "gpt-5.1"
# model = "claude-opus-4-5-20251101"
# model = "gemini/gemini-3-pro-preview"
#
# Local LLMs
# model = "ollama/gpt-oss
# model = "openai/gpt-oss-20b"
# model = "unsloth/gpt-oss-20b-GGUF/gpt-oss-20b-Q4_K_M.gguf"
#
# Pass multiple options as a dictionary
# model = {
# "path": "unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF/Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf",
# "n_ctx": 25000
# }
model = "Qwen/Qwen3-4B-Instruct-2507"
# Step 4: Create an Agent
#
# Set LLM, tools and other configuration
# See this for more options: https://huggingface.co/docs/smolagents/reference/agents#agents
agent = Agent(model=model, tools=tools, max_steps=10)
print(agent("Tell me about the Roman Empire"))
print(agent("What is the current date?"))
print(agent("Get the 5 top news stories for today", maxlength=25000))
+70 -35
View File
@@ -15,7 +15,7 @@ import numpy as np
import pandas as pd
import streamlit as st
from txtai.embeddings import Embeddings
from txtai import Embeddings
class Stats:
@@ -38,7 +38,7 @@ class Stats:
self.names = self.loadnames()
# Build index
self.vectors, self.data, self.embeddings = self.index()
self.vectors, self.data, self.maxyear, self.embeddings = self.index()
def loadcolumns(self):
"""
@@ -122,16 +122,12 @@ class Stats:
# Build data dictionary
vectors = {f'{row["yearID"]}{row["playerID"]}': self.transform(row) for _, row in self.stats.iterrows()}
data = {f'{row["yearID"]}{row["playerID"]}': dict(row) for _, row in self.stats.iterrows()}
maxyear = max(row["yearID"] for _, row in self.stats.iterrows())
embeddings = Embeddings(
{
"transform": self.transform,
}
)
embeddings = Embeddings({"transform": Stats.transform})
embeddings.index((uid, vectors[uid], None) for uid in vectors)
return vectors, data, embeddings
return vectors, data, maxyear, embeddings
def metrics(self, name):
"""
@@ -159,13 +155,14 @@ class Stats:
return range(1871, datetime.datetime.today().year), 1950, None
def search(self, name=None, year=None, row=None, limit=10):
def search(self, name=None, year=None, window=None, row=None, limit=10):
"""
Runs an embeddings search. This method takes either a player-year or stats row as input.
Args:
name: player name to search
year: year to search
window: limit to window recent seasons
row: row of stats to search
limit: max results to return
@@ -183,13 +180,17 @@ class Stats:
results, ids = [], set()
if query is not None:
for uid, _ in self.embeddings.search(query, limit * 5):
candidates = limit * 100 if window else limit * 5
for uid, _ in self.embeddings.search(query, candidates):
# Only add unique players
if uid[4:] not in ids:
result = self.data[uid].copy()
result["link"] = f'https://www.baseball-reference.com/players/{result["nameLast"].lower()[0]}/{result["bbrefID"]}.shtml'
results.append(result)
ids.add(uid[4:])
# Add first player if this is a player comparison. Limit results to window, if necessary
if (not ids and not row) or not window or result["yearID"] > self.maxyear - window:
result["link"] = f'https://www.baseball-reference.com/players/{result["nameLast"].lower()[0]}/{result["bbrefID"]}.shtml'
results.append(result)
ids.add(uid[4:])
if len(ids) >= limit:
break
@@ -253,10 +254,10 @@ class Batting(Stats):
]
def load(self):
# Retrieve raw data from GitHub
players = pd.read_csv("https://raw.githubusercontent.com/chadwickbureau/baseballdatabank/master/core/People.csv")
batting = pd.read_csv("https://raw.githubusercontent.com/chadwickbureau/baseballdatabank/master/core/Batting.csv")
fielding = pd.read_csv("https://raw.githubusercontent.com/chadwickbureau/baseballdatabank/master/core/Fielding.csv")
# Retrieve raw data
players = pd.read_csv("https://hf.co/datasets/neuml/baseballdata/resolve/main/People.csv")
batting = pd.read_csv("https://hf.co/datasets/neuml/baseballdata/resolve/main/Batting.csv")
fielding = pd.read_csv("https://hf.co/datasets/neuml/baseballdata/resolve/main/Fielding.csv")
# Merge player data in
batting = pd.merge(players, batting, how="inner", on=["playerID"])
@@ -387,9 +388,9 @@ class Pitching(Stats):
]
def load(self):
# Retrieve raw data from GitHub
players = pd.read_csv("https://raw.githubusercontent.com/chadwickbureau/baseballdatabank/master/core/People.csv")
pitching = pd.read_csv("https://raw.githubusercontent.com/chadwickbureau/baseballdatabank/master/core/Pitching.csv")
# Retrieve raw data
players = pd.read_csv("https://hf.co/datasets/neuml/baseballdata/resolve/main/People.csv")
pitching = pd.read_csv("https://hf.co/datasets/neuml/baseballdata/resolve/main/Pitching.csv")
# Merge player data in
pitching = pd.merge(players, pitching, how="inner", on=["playerID"])
@@ -435,13 +436,14 @@ class Application:
Runs a Streamlit application.
"""
st.title("⚾ Baseball Statistics")
st.set_page_config(layout="wide", page_title="Baseball Stats", page_icon="⚾")
st.title("⚾ Baseball Stats")
st.markdown(
"""
This application finds the best matching historical players using vector search with [txtai](https://github.com/neuml/txtai).
Raw data is from the [Baseball Databank](https://github.com/chadwickbureau/baseballdatabank) GitHub project. Read [this
This application finds the best matching players using vector search with [txtai](https://github.com/neuml/txtai).
Raw data is from the [Lahman Baseball Database](https://sabr.org/lahman-database/). Read [this
article](https://medium.com/neuml/explore-baseball-history-with-vector-search-5778d98d6846) for more details.
"""
"""
)
player, search = st.tabs(["Player", "Search"])
@@ -471,6 +473,9 @@ class Application:
# Player name
name = self.name(stats.names, params.get("name"))
# Limit player-year comparisons using this window
window = self.window(params.get("window"), "window")
# Player metrics
active, best, metrics = stats.metrics(name)
@@ -482,13 +487,16 @@ class Application:
self.chart(category, metrics)
# Run search
results = stats.search(name, year)
results = stats.search(name, year, window)
# Display results
self.table(results, ["link", "nameFirst", "nameLast", "teamID"] + stats.columns[1:])
# Save parameters
st.experimental_set_query_params(category=category, name=name, year=year)
# Save query parameters
st.query_params.clear()
for key, value in [("category", category), ("name", name), ("window", window), ("year", year)]:
if value:
st.query_params[key] = value
def search(self):
"""
@@ -498,6 +506,10 @@ class Application:
st.markdown("Find players with similar statistics.")
stats, category = None, self.category("Batting", "searchcategory")
# Limit player-year comparisons using this window
window = self.window(None, "searchwindow")
with st.form("search"):
if category == "Batting":
stats, columns = self.batting, self.batting.columns[:-6]
@@ -510,7 +522,7 @@ class Application:
submitted = st.form_submit_button("Search")
if submitted:
# Run search
results = stats.search(row=inputs.to_dict(orient="records")[0])
results = stats.search(window=window, row=inputs.to_dict(orient="records")[0])
# Display table
self.table(results, ["link", "nameFirst", "nameLast", "teamID"] + stats.columns[1:])
@@ -523,18 +535,18 @@ class Application:
parameters
"""
# Get parameters
params = st.experimental_get_query_params()
params = {x: params[x][0] for x in params}
# Get query parameters
params = {x: st.query_params.get(x) for x in ["category", "name", "window", "year"]}
# Sync parameters with session state
if all(x in st.session_state for x in ["category", "name", "year"]):
# Copy session year if category and name are unchanged
params["year"] = str(st.session_state["year"]) if all(params.get(x) == st.session_state[x] for x in ["category", "name"]) else None
# Copy category and name from session state
# Copy category, name and window from session state
params["category"] = st.session_state["category"]
params["name"] = st.session_state["name"]
params["window"] = st.session_state["window"]
return params
@@ -559,6 +571,29 @@ class Application:
# Radio box component
return st.radio("Stat", categories, index=default, horizontal=True, key=key)
def window(self, window, key):
"""
Limit results to last N seasons.
Args:
window: limit to window seasons
key: widget key
Returns:
window component
"""
# Get window size
window = st.text_input("Limit to last N seasons", value=window, key=key)
# Clear invalid input
if window and (not window.isnumeric() or int(window) < 1):
st.error("Window must be a number greater or equal to 1")
return None
# Convert to int
return int(window) if window else window
def name(self, names, name):
"""
Builds name input widget.
@@ -627,7 +662,7 @@ class Application:
chart = (chart + rule).encode(y=alt.Y(title=metric)).properties(height=200).configure_axis(grid=False)
# Draw chart
st.altair_chart(chart + rule, theme="streamlit", use_container_width=True)
st.altair_chart(chart + rule, theme="streamlit", width="stretch")
def table(self, results, columns):
"""
@@ -643,7 +678,7 @@ class Application:
results,
column_order=columns,
column_config={
"link": st.column_config.LinkColumn("Link", width="small"),
"link": st.column_config.LinkColumn("Link", width="small", display_text=":material/open_in_new:"),
"yearID": st.column_config.NumberColumn("Year", format="%d"),
"nameFirst": "First",
"nameLast": "Last",
+70
View File
@@ -0,0 +1,70 @@
"""
RAG Quick Start
Easy to use way to get started with RAG using YOUR data
For a complete application see this: https://github.com/neuml/rag
TxtAI has many example notebooks covering everything the framework provides
Examples: https://neuml.github.io/txtai/examples
Install TxtAI
pip install txtai[pipeline-data]
"""
# pylint: disable=C0103
import os
from txtai import Embeddings, RAG
from txtai.pipeline import Textractor
# Step 1: Collect files from local directory
#
# Defaults to "data". Set to whereever your files are.
path = "data"
files = [os.path.join(path, f) for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
# Step 2: Text Extraction / Chunking
#
# Using section based chunking here. More complex options available such as semantic chunking, iterative chunking etc.
# Documentation: https://neuml.github.io/txtai/pipeline/data/textractor
# Supports Chonkie chunking as well: https://docs.chonkie.ai/oss/chunkers/overview
textractor = Textractor(backend="docling", sections=True)
chunks = []
for f in files:
for chunk in textractor(f):
chunks.append((f, chunk))
# Step 3: Build an embeddings database
#
# The `path` parameter sets the vector embeddings model. Supports Hugging Face models, llama.cpp, Ollama, vLLM and more.
# Documentation: https://neuml.github.io/txtai/embeddings/
embeddings = Embeddings(content=True, path="Qwen/Qwen3-Embedding-0.6B", maxlength=2048)
embeddings.index(chunks)
# Step 4: Create RAG pipeline
#
# Combines an embeddings database and an LLM.
# Supports Hugging Face models, llama.cpp, Ollama, vLLM and more
# Documentation: https://neuml.github.io/txtai/pipeline/text/rag
# User prompt template
template = """
Answer the following question using the provided context.
Question:
{question}
Context:
{context}
"""
rag = RAG(
embeddings,
"Qwen/Qwen3-0.6B",
system="You are a friendly assistant",
template=template,
output="flatten",
)
question = "Summarize the main advancements made by BERT"
print(rag(question, maxlength=2048, stripthink=True))
+59
View File
@@ -0,0 +1,59 @@
"""
Workflow Quick Start
Easy to use way to get started with deterministic workflows.
TxtAI has many example notebooks covering everything the framework provides
Examples: https://neuml.github.io/txtai/examples
Install TxtAI
pip install txtai[pipeline-data]
"""
from txtai import LLM, Workflow
from txtai.pipeline import Summary, Textractor, Translation
from txtai.workflow import Task
# Step 1: Define available pipelines
textractor = Textractor(backend="docling", headers={"user-agent": "Mozilla/5.0"})
summary = Summary()
translate = Translation()
# Step 2: Define workflow tasks
workflow = Workflow([Task(textractor), Task(summary), Task(lambda inputs: [translate(x, "fr") for x in inputs])])
# Step 3: Run the workflow
print(list(workflow(["https://neuml.com"])))
# Each component above is a single model that specializes in a task
# LLMs can also be used to accomplish the same tasks
# pylint: disable=E0102,C0116
def summary(text):
return f"""
Summarize the following text in 40 words or less.
{text}
"""
def translate(text, language):
return f"""
Translate the following text to {language}.
{text}
"""
textractor = Textractor(backend="docling", headers={"user-agent": "Mozilla/5.0"})
llm = LLM("Qwen/Qwen3-4B-Instruct-2507")
workflow = Workflow(
[
Task(textractor),
Task(lambda inputs: llm([summary(x) for x in inputs], maxlength=25000, defaultrole="user")),
Task(lambda inputs: llm([translate(x, "fr") for x in inputs], maxlength=25000, defaultrole="user")),
]
)
print(list(workflow(["https://neuml.com"])))
+10 -5
View File
@@ -43,11 +43,12 @@ plugins:
show_root_toc_entry: false
- redirects:
redirect_maps:
"pipeline/text/extractor.md": "pipeline/text/rag.md"
"pipeline/text/generator.md": "pipeline/text/llm.md"
"pipeline/text/sequences.md": "pipeline/text/llm.md"
"pipeline/text/llm.md": "pipeline/llm/llm.md"
"pipeline/text/rag.md": "pipeline/llm/rag.md"
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.highlight
- pymdownx.superfences
nav:
@@ -90,21 +91,25 @@ nav:
- Segmentation: pipeline/data/segmentation.md
- Tabular: pipeline/data/tabular.md
- Textractor: pipeline/data/textractor.md
- Tokenizer: pipeline/data/tokenizer.md
- URL Retrieve: pipeline/data/urlretrieve.md
- Image:
- Caption: pipeline/image/caption.md
- Image Hash: pipeline/image/imagehash.md
- Objects: pipeline/image/objects.md
- LLM:
- LLM: pipeline/llm/llm.md
- RAG: pipeline/llm/rag.md
- Text:
- Entity: pipeline/text/entity.md
- Labels: pipeline/text/labels.md
- LLM: pipeline/text/llm.md
- RAG: pipeline/text/rag.md
- Reranker: pipeline/text/reranker.md
- Similarity: pipeline/text/similarity.md
- Summary: pipeline/text/summary.md
- Translation: pipeline/text/translation.md
- Train:
- HF ONNX: pipeline/train/hfonnx.md
- LEMUR Trainer: pipeline/train/lemur.md
- ML ONNX: pipeline/train/mlonnx.md
- Trainer: pipeline/train/trainer.md
- Workflow:
+55 -14
View File
@@ -1,4 +1,6 @@
# pylint: disable = C0111
# pylint: disable = C0103,C0111
import os
from setuptools import find_packages, setup
with open("README.md", "r", encoding="utf-8") as f:
@@ -6,14 +8,38 @@ with open("README.md", "r", encoding="utf-8") as f:
DESCRIPTION = "".join([line for line in f if "gh-dark-mode-only" not in line])
# Required dependencies
install = ["faiss-cpu>=1.7.1.post2", "msgpack>=1.0.7", "torch>=2.4", "transformers>=4.46.3"]
install = []
# Required dependencies that are also base transformers dependencies
install += ["huggingface-hub>=0.34.0", "numpy>=1.18.4", "pyyaml>=5.3", "regex>=2022.8.17", "safetensors>=0.4.5"]
# Default dependencies
default = [
"faiss-cpu>=1.7.1.post2",
"huggingface-hub>=0.34.0",
"msgpack>=1.0.7",
"numpy>=1.18.4",
"regex>=2022.8.17",
"pyyaml>=5.3",
"safetensors>=0.4.5",
"torch>=2.4",
"tqdm>=4.66.3",
"transformers>=5.9.0",
]
# Optional dependencies
extras = {}
# Package name
package = "txtai"
if os.getenv("MINIMAL"):
# Add default extra
extras["default"] = default
# Rename this package to have minimal suffix
package += "_minimal"
else:
# Default dependencies are required with standard install
install += default
# Development dependencies - not included in "all" install
extras["dev"] = [
"black",
@@ -27,24 +53,28 @@ extras["dev"] = [
"pylint",
]
extras["agent"] = ["mcpadapt>=0.1.0", "smolagents>=1.23"]
extras["agent"] = ["beautifulsoup4>=4.9.3", "jinja2>=3.1.6", "mcp<2.0", "mcpadapt>=0.1.0", "smolagents>=1.23"]
extras["ann"] = [
"annoy>=1.16.3",
"bitsandbytes>=0.42.0",
"ggml-py>=0.9.4",
"ggml-python>=0.0.41",
"hnswlib>=0.5.0",
"milvus-lite>=3.1.1",
"pgvector>=0.4.1",
"rabitqlib>=0.5.1",
"scikit-learn>=0.23.1",
"scipy>=1.4.1",
"sqlalchemy>=2.0.20",
"sqlite-vec>=0.1.1",
"turbovec>=0.7.0",
"zvec>=0.5.1",
]
extras["api"] = [
"aiohttp>=3.8.1",
"fastapi>=0.94.0",
"fastapi-mcp>=0.2.0",
"fastapi-mcp>=0.4.0",
"httpx>=0.28.1",
"pillow>=7.1.2",
"python-multipart>=0.0.7",
@@ -55,7 +85,7 @@ extras["cloud"] = ["apache-libcloud>=3.3.1", "fasteners>=0.14.1"]
extras["console"] = ["rich>=12.0.1"]
extras["database"] = ["duckdb>=0.7.1", "pillow>=7.1.2", "sqlalchemy>=2.0.20"]
extras["database"] = ["duckdb>=0.8.0", "pillow>=7.1.2", "sqlalchemy>=2.0.20"]
extras["graph"] = ["grand-cypher>=0.6.0", "grand-graph>=0.6.0", "networkx>=2.7.1", "sqlalchemy>=2.0.20"]
@@ -71,13 +101,21 @@ extras["pipeline-audio"] = [
"webrtcvad-wheels>=2.0.14",
]
extras["pipeline-data"] = ["beautifulsoup4>=4.9.3", "chonkie>=1.0.2", "docling>=2.8.2", "nltk>=3.5", "pandas>=1.1.0", "tika>=1.24"]
extras["pipeline-data"] = [
"beautifulsoup4>=4.9.3",
"chonkie>=1.0.2",
"docling>=2.8.2",
"liteparse>=2.1.1",
"nltk>=3.5",
"pandas>=1.1.0",
"tika>=1.24",
]
extras["pipeline-image"] = ["imagehash>=4.2.1", "pillow>=7.1.2", "timm>=0.4.12"]
extras["pipeline-llm"] = ["litellm>=1.37.16", "llama-cpp-python>=0.2.75"]
extras["pipeline-llm"] = ["httpx>=0.28.1", "litert-lm-api>=0.11.0", "litellm>=1.37.16", "llama-cpp-python>=0.2.75"]
extras["pipeline-text"] = ["gliner>=0.2.16,<=0.2.21", "sentencepiece>=0.1.91", "staticvectors>=0.2.0"]
extras["pipeline-text"] = ["gliner-py>=0.2.27", "sentencepiece>=0.1.91", "staticvectors>=0.2.0"]
extras["pipeline-train"] = [
"accelerate>=0.26.0",
@@ -101,14 +139,17 @@ extras["pipeline"] = (
extras["scoring"] = ["sqlalchemy>=2.0.20"]
extras["vectors"] = [
"ai-edge-litert>=2.1.5",
"litellm>=1.37.16",
"llama-cpp-python>=0.2.75",
"model2vec>=0.3.0",
"onnxruntime>=1.11.0",
"scikit-learn>=0.23.1",
"scipy>=1.4.1",
"sentence-transformers>=5.0.0",
"skops>=0.9.0",
"staticvectors>=0.2.0",
"tokenizers>=0.22.2",
]
extras["workflow"] = [
@@ -139,8 +180,8 @@ extras["all"] = (
)
setup(
name="txtai",
version="9.2.0",
name=package,
version="9.15.0",
author="NeuML",
description="All-in-one open-source AI framework for semantic search, LLM orchestration and language model workflows",
long_description=DESCRIPTION,
@@ -155,7 +196,7 @@ setup(
packages=find_packages(where="src/python"),
package_dir={"": "src/python"},
keywords="search embedding machine-learning nlp",
python_requires=">=3.10",
python_requires=">=3.11",
install_requires=install,
extras_require=extras,
classifiers=[
+1 -1
View File
@@ -8,7 +8,7 @@ import logging
from .agent import Agent
from .app import Application
from .embeddings import Embeddings
from .pipeline import LLM, RAG
from .pipeline import LLM, RAG, Textractor
from .workflow import Workflow
# Configure logging per standard Python library recommendations
+91 -3
View File
@@ -2,6 +2,12 @@
Agent module
"""
import os
from collections import deque
from jinja2.sandbox import SandboxedEnvironment
from .factory import ProcessFactory
@@ -15,11 +21,13 @@ class Agent:
should be explored.
"""
def __init__(self, **kwargs):
def __init__(self, template=None, memory=None, **kwargs):
"""
Creates a new Agent.
Args:
template: optional prompt jinja template, must include {{ text }} and {{ memory }} placeholders
memory: number of prior outputs to keep as "memory", defaults to None for no memory
kwargs: arguments to pass to the underlying Agent backend and LLM pipeline instance
"""
@@ -27,13 +35,36 @@ class Agent:
if "max_iterations" in kwargs:
kwargs["max_steps"] = kwargs.pop("max_iterations")
# Custom instructions
if "instructions" in kwargs:
kwargs["instructions"] = self.instructions(kwargs)
# Create agent process runner
self.process = ProcessFactory.create(kwargs)
# Tools dictionary
self.tools = self.process.tools
def __call__(self, text, maxlength=8192, stream=False, **kwargs):
# Agent memory
self.memory = {}
self.window = memory
# Create template
self.template = SandboxedEnvironment().from_string(
template
if template
else """{{ text }}
{% if memory %}
Use the following conversation history to help answer the question above.
{{ memory }}
If the history is irrelevant, forget it and use other tools to answer the question.
{% endif %}
"""
)
def __call__(self, text, maxlength=8192, stream=False, session=None, reset=False, **kwargs):
"""
Runs an agent loop.
@@ -41,6 +72,8 @@ class Agent:
text: instructions to run
maxlength: maximum sequence length
stream: stream response if True, defaults to False
session: session id for stored memory, defaults to None which shares all memory
reset: clears previously stored memory if True, defaults to False
kwargs: additional keyword arguments
Returns:
@@ -50,5 +83,60 @@ class Agent:
# Process parameters
self.process.model.parameters(maxlength)
# Create memory, if necessary
if self.window and (session not in self.memory or reset):
self.memory[session] = deque(maxlen=self.window)
# Run agent loop
return self.process.run(text, stream=stream, **kwargs)
output = self.process.run(self.prompt(text, session), stream=stream, **kwargs)
# Add output to memory, if necessary
if session in self.memory:
self.memory[session].append((text, output))
return output
def prompt(self, text, session):
"""
Generates the full agent prompt using the input instructions. Adds in agent memory
if available.
Args:
text: instructions to run
session: session id for stored memory
Returns:
formatted instructions
"""
# pylint: disable=E1133
memory = []
if self.memory.get(session):
# Add memory context
for request, output in self.memory[session]:
memory.append(f"User: {request}\nAssistant: {output}")
memory = "\n\n".join(memory)
# Command template with memory
return self.template.render(text=text, memory=memory)
def instructions(self, config):
"""
Reads and formats custom instructions. Supports agents.md files.
Args:
config: agent configuration
Returns:
agent instructions, if any
"""
# Check if this is a file path (i.e. agents.md)
path = config.pop("instructions", None)
if path and os.path.isfile(path):
with open(path, encoding="utf-8") as f:
# Read entire file
return f"\nBelow is a set of general instructions to follow:\n\n{f.read()}"
return path
+1 -4
View File
@@ -30,11 +30,8 @@ class PipelineModel(Model):
self.llm = path if isinstance(path, LLM) else LLM(path, method, **kwargs)
self.maxlength = 8192
# Set base class parameters
self.model_id = self.llm.generator.path
# Call parent constructor
super().__init__(flatten_messages_as_text=not self.llm.isvision(), **kwargs)
super().__init__(flatten_messages_as_text=not self.llm.isvision(), model_id=self.llm.generator.path, **kwargs)
# pylint: disable=W0613
def generate(self, messages, stop_sequences=None, response_format=None, tools_to_call_from=None, **kwargs):
+7
View File
@@ -5,3 +5,10 @@ Tool imports
from .embeddings import EmbeddingsTool
from .factory import ToolFactory
from .function import FunctionTool
from .bash import BashTool
from .edit import EditTool
from .glob import GlobTool
from .grep import GrepTool
from .read import ReadTool
from .skill import SkillTool
from .todo import TodoWriteTool
+67
View File
@@ -0,0 +1,67 @@
"""
Bash imports
"""
import subprocess
from smolagents import Tool
class BashTool(Tool):
"""
The BashTool runs a command through a subprocess. This tool only allows a small subset of commands.
More can be added through configuration.
"""
# pylint: disable=W0231
def __init__(self, allowed=None, timeout=30):
"""
Creates a BashTool.
Args:
allowed: list of allowed commands to run, has limited set of defaults which are a best effort not a sandbox
timeout: maximum number of seconds to wait for a command to complete, defaults to 30, None disables the timeout
"""
# Tool parameters
self.name = "bash"
self.description = "Implementation of a bash shell subprocess tool. Runs a shell command and returns the output."
self.inputs = {
"command": {"type": "array", "description": "Command to run. Follows Python subprocess.open pattern for command as a list of arguments."}
}
self.output_type = "any"
# Default list of allowed commands
self.allowed = allowed if allowed is not None else ["cat", "cut", "diff", "grep", "head", "ls", "tail"]
# Maximum time to wait for a command, None waits indefinitely
self.timeout = timeout
# Validate parameters and initialize tool
super().__init__()
# pylint: disable=W0221
def forward(self, command):
"""
Runs a shell command as a subprocess.
stdin is closed and a timeout is applied. Otherwise an allowed command called with no file arguments
(i.e. `cat`) reads from stdin and blocks the agent indefinitely.
Args:
command: command arguments as a list
Returns:
command output
"""
output = None
if command and command[0] in self.allowed:
try:
output = subprocess.run(
command, capture_output=True, text=True, encoding="utf-8", check=False, stdin=subprocess.DEVNULL, timeout=self.timeout
).stdout
except subprocess.TimeoutExpired:
output = f"Command timed out after {self.timeout} seconds"
return output

Some files were not shown because too many files have changed in this diff Show More