TalkPipe 0.7.0__tar.gz → 0.7.0a2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/CHANGELOG.md +2 -8
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/PKG-INFO +1 -41
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/README.md +0 -40
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/__init__.py +1 -1
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/static/unit-docs.html +49 -62
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/static/unit-docs.txt +36 -49
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/basic.py +5 -5
- talkpipe-0.7.0a2/src/talkpipe/search/abstract.py +43 -0
- talkpipe-0.7.0a2/src/talkpipe/search/whoosh.py +127 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/util/data_manipulation.py +2 -2
- talkpipe-0.7.0a2/src/talkpipe/vectordb/abstract.py +68 -0
- talkpipe-0.7.0a2/src/talkpipe/vectordb/simplevectordb.py +598 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/PKG-INFO +1 -41
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/SOURCES.txt +4 -7
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/search/test_whoosh.py +15 -78
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/util/test_util.py +0 -8
- {talkpipe-0.7.0/tests/talkpipe/search → talkpipe-0.7.0a2/tests/talkpipe/vectordb}/test_simplevectordb.py +26 -25
- talkpipe-0.7.0/docs/.gitignore +0 -3
- talkpipe-0.7.0/docs/make_structure_diagram.sh +0 -3
- talkpipe-0.7.0/docs/structure.tex +0 -59
- talkpipe-0.7.0/docs/talkpipe_diagram.png +0 -0
- talkpipe-0.7.0/src/talkpipe/search/abstract.py +0 -64
- talkpipe-0.7.0/src/talkpipe/search/simplevectordb.py +0 -413
- talkpipe-0.7.0/src/talkpipe/search/whoosh.py +0 -324
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/.github/ISSUE_TEMPLATE/release-checklist.md +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/.gitignore +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/.vscode/settings.json +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/.vscode/tasks.json +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/COPYRIGHT +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/Dockerfile +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/LICENSE +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/base-image/Dockerfile +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/bin/config-analyzer.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/bin/config_bash +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/docs/LLMChat.png +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/docs/LLMEvaluateWebPage.png +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/docs/TalkPipe.png +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/docs/TalkPipe.xcf +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/pyproject.toml +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/pytest.ini +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/setup.cfg +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/setup.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/apiendpoint.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/chatcli.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/chatterlang_server.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/runscript.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/static/.gitignore +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/static/favicon.ico +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/app/unit_documentation_analyzer.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/chatterlang/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/chatterlang/compiler.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/chatterlang/parsers.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/chatterlang/registry.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/email.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/extraction.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/html.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/mongo.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/data/rss.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/jupyter/basic.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/jupyter/examples.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/jupyter/interactive.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/chat.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/config.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/embedding.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/embedding_adapters.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/llm/prompt_adapters.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/filtering.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/matrices.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/signatures.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/thread_ops.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/operations/transforms.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/core.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/fork.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/io.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/pipe/math.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/util/__init__.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/util/collections.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/util/config.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe/util/os.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/dependency_links.txt +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/entry_points.txt +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/requires.txt +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/src/talkpipe.egg-info/top_level.txt +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/conftest.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/app/test_chatcli.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/app/test_runscript.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/chatterlang/test_chatterlang_server.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/chatterlang/test_compiler.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/chatterlang/test_parsers.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/sample_feed.pkl +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test.docx +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_email.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_extraction.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_html.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_html_exceptions.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_mogomock.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_mongo.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_mongo_integration.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/data/test_rss.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/jupyter/test_basic_jupyter.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/jupyter/test_examples.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/jupyter/test_interactive.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/llm/test_chat.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/llm/test_embedding.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/operations/test_filtering.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/operations/test_matrices.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/operations/test_signatures.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/operations/test_threading.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/operations/test_transforms.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/pipe/test_basic.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/pipe/test_core.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/pipe/test_fork.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/pipe/test_io.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/pipe/test_math.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/test_documentation_examples.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/talkpipe/util/test_collections.py +0 -0
- {talkpipe-0.7.0 → talkpipe-0.7.0a2}/tests/testutils.py +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
## In Progress
|
|
3
4
|
### New Segments and Sources
|
|
4
5
|
- **progressTicks** – Prints out a tick for every n items seen and a new line for every m ticks.
|
|
5
6
|
Especially useful for debugging and marking progress in logs.
|
|
@@ -11,10 +12,6 @@
|
|
|
11
12
|
### Improvements
|
|
12
13
|
- Rewrote firstN to use decorator syntax (making it shorter) and to not throw an exception
|
|
13
14
|
when there are fewer than N items.
|
|
14
|
-
- Created a set of protocols for search engines, both full-text and vector DB-based.
|
|
15
|
-
These protocols can be used to write wrappers around different search engines and
|
|
16
|
-
vector databases, providing a common API that can then be used in different segments
|
|
17
|
-
and sources.
|
|
18
15
|
- Integrated the Whoosh pure-Python, stand-alone search engine. This is intended for testing,
|
|
19
16
|
debugging, and smaller stand-alone scenarios. It allows a programmer to work on pipelines that
|
|
20
17
|
use full-text search engines without setting up a full search engine server. It can support
|
|
@@ -23,9 +20,6 @@
|
|
|
23
20
|
- Added SimpleVectorDB, a pure Python, simple vector database. It allows a programmer to build
|
|
24
21
|
and debug pipelines requiring simple vector databases. It supports smaller-scale databases
|
|
25
22
|
that can later be replaced with a separate server.
|
|
26
|
-
- Added a default option to extract_property and propagated the option to several segments.
|
|
27
|
-
- Wrote a conceptual diagram for the library and wrote short descriptions to orient people to
|
|
28
|
-
how the library can be used.
|
|
29
23
|
|
|
30
24
|
## 0.6.0
|
|
31
25
|
### New Segments and Sources
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: talkpipe
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.0a2
|
|
4
4
|
Summary: Python internal and external DSL for writing generative AI analytics
|
|
5
5
|
Author-email: Travis Bauer <tlbauer@sandia.gov>
|
|
6
6
|
Maintainer-email: Travis Bauer <tlbauer@sandia.gov>
|
|
@@ -56,46 +56,6 @@ TalkPipe is a Python toolkit that makes it easy to create, test, and deploy work
|
|
|
56
56
|
- **Create AI Agents** - Build agents that can debate topics, evaluate streams of documents, or monitor RSS feeds
|
|
57
57
|
- **Deploy Anywhere** - Run in Jupyter notebooks, as Docker containers, or as standalone Python applications
|
|
58
58
|
|
|
59
|
-
## Structure
|
|
60
|
-
|
|
61
|
-
<center><img src="docs/talkpipe_diagram.png" width=700></center>
|
|
62
|
-
|
|
63
|
-
Talkpipe is structured in five layers: Key Functionality, Pipe, ChatterLang, Applications Components, and Docker Containers.
|
|
64
|
-
|
|
65
|
-
The Key Functionality layer offers foundational utilities and abstractions that ensure consistency across the entire system. It includes configuration management, as well as standardized wrappers for interacting with LLMs, full-text search engines, and a lightweight vector database. These components provide a unified interface for core capabilities, making it easy to integrate advanced AI and search features throughout your workflows.
|
|
66
|
-
|
|
67
|
-
The Pipe layer serves as TalkPipe's internal domain-specific language (DSL), enabling you to construct sophisticated workflows directly in Python. By instantiating modular classes and chaining them together using the `|` (pipe) operator, you can seamlessly connect sources, segments, and sinks to process data in a clear, readable, and composable manner. This approach leverages Python's native syntax and type checking, allowing for rapid development, easy debugging, and full IDE support. The Pipe layer is ideal for users who prefer programmatic control and want to integrate TalkPipe pipelines into larger Python applications or scripts.
|
|
68
|
-
|
|
69
|
-
The ChatterLang layer serves as TalkPipe's external domain-specific language (DSL), enabling you to define workflows using concise, human-readable text scripts. These scripts can be compiled directly in Python, producing callable functions that integrate seamlessly with your codebase. ChatterLang also supports specifying workflows via environment variables or command-line arguments, making it easy to configure and automate pipelines in Docker containers, shell scripts, CI/CD pipelines, and other deployment environments. This flexibility empowers both developers and non-developers to create, share, and modify AI-powered workflows without writing Python code, streamlining experimentation and operationalization.
|
|
70
|
-
|
|
71
|
-
The Application Components layer contains runnable applications that provide user interfaces and automation tools for working with TalkPipe pipelines and ChatterLang scripts. These components are designed to make it easy to interact with TalkPipe from the command line, web browser, or as part of automated workflows.
|
|
72
|
-
|
|
73
|
-
### Key Applications
|
|
74
|
-
|
|
75
|
-
- **chatterlang_server**
|
|
76
|
-
Launches an interactive web interface for writing, testing, and running ChatterLang scripts. It provides real-time execution, logging, and documentation lookup.
|
|
77
|
-
|
|
78
|
-
- **chatterlang_script**
|
|
79
|
-
Runs ChatterLang scripts from files or directly from the command line, enabling batch processing and automation.
|
|
80
|
-
|
|
81
|
-
- **talkpipe_ref**
|
|
82
|
-
Generates HTML and text documentation for all available sources and segments, making it easy to discover and understand built-in functionality.
|
|
83
|
-
|
|
84
|
-
- **talkpipe_endpoint**
|
|
85
|
-
Exposes ChatterLang pipelines as REST APIs or web forms, allowing you to deploy workflows as web services or user-facing endpoints.
|
|
86
|
-
|
|
87
|
-
These applications are entry points for different usage scenarios, from interactive development to production deployment.
|
|
88
|
-
|
|
89
|
-
The Docker layer provides ready-to-use container images for deploying TalkPipe in different environments. It includes:
|
|
90
|
-
|
|
91
|
-
- **talkpipe-base**
|
|
92
|
-
A minimal container image that contains all dependencies required by TalkPipe, but does not install TalkPipe itself. Use this as a foundation for building your own images, custom workflows, or CI/CD jobs where you want to control the installation of TalkPipe or add additional components.
|
|
93
|
-
|
|
94
|
-
- **chatterlang_script**
|
|
95
|
-
An image that installs TalkPipe on top of the base dependencies and runs a talkpipe script.
|
|
96
|
-
|
|
97
|
-
These containers exist to simplify deployment, ensure consistent environments, and enable rapid experimentation or production use of TalkPipe and ChatterLang across platforms.
|
|
98
|
-
|
|
99
59
|
## Quick Start
|
|
100
60
|
|
|
101
61
|
Install TalkPipe:
|
|
@@ -13,46 +13,6 @@ TalkPipe is a Python toolkit that makes it easy to create, test, and deploy work
|
|
|
13
13
|
- **Create AI Agents** - Build agents that can debate topics, evaluate streams of documents, or monitor RSS feeds
|
|
14
14
|
- **Deploy Anywhere** - Run in Jupyter notebooks, as Docker containers, or as standalone Python applications
|
|
15
15
|
|
|
16
|
-
## Structure
|
|
17
|
-
|
|
18
|
-
<center><img src="docs/talkpipe_diagram.png" width=700></center>
|
|
19
|
-
|
|
20
|
-
Talkpipe is structured in five layers: Key Functionality, Pipe, ChatterLang, Applications Components, and Docker Containers.
|
|
21
|
-
|
|
22
|
-
The Key Functionality layer offers foundational utilities and abstractions that ensure consistency across the entire system. It includes configuration management, as well as standardized wrappers for interacting with LLMs, full-text search engines, and a lightweight vector database. These components provide a unified interface for core capabilities, making it easy to integrate advanced AI and search features throughout your workflows.
|
|
23
|
-
|
|
24
|
-
The Pipe layer serves as TalkPipe's internal domain-specific language (DSL), enabling you to construct sophisticated workflows directly in Python. By instantiating modular classes and chaining them together using the `|` (pipe) operator, you can seamlessly connect sources, segments, and sinks to process data in a clear, readable, and composable manner. This approach leverages Python's native syntax and type checking, allowing for rapid development, easy debugging, and full IDE support. The Pipe layer is ideal for users who prefer programmatic control and want to integrate TalkPipe pipelines into larger Python applications or scripts.
|
|
25
|
-
|
|
26
|
-
The ChatterLang layer serves as TalkPipe's external domain-specific language (DSL), enabling you to define workflows using concise, human-readable text scripts. These scripts can be compiled directly in Python, producing callable functions that integrate seamlessly with your codebase. ChatterLang also supports specifying workflows via environment variables or command-line arguments, making it easy to configure and automate pipelines in Docker containers, shell scripts, CI/CD pipelines, and other deployment environments. This flexibility empowers both developers and non-developers to create, share, and modify AI-powered workflows without writing Python code, streamlining experimentation and operationalization.
|
|
27
|
-
|
|
28
|
-
The Application Components layer contains runnable applications that provide user interfaces and automation tools for working with TalkPipe pipelines and ChatterLang scripts. These components are designed to make it easy to interact with TalkPipe from the command line, web browser, or as part of automated workflows.
|
|
29
|
-
|
|
30
|
-
### Key Applications
|
|
31
|
-
|
|
32
|
-
- **chatterlang_server**
|
|
33
|
-
Launches an interactive web interface for writing, testing, and running ChatterLang scripts. It provides real-time execution, logging, and documentation lookup.
|
|
34
|
-
|
|
35
|
-
- **chatterlang_script**
|
|
36
|
-
Runs ChatterLang scripts from files or directly from the command line, enabling batch processing and automation.
|
|
37
|
-
|
|
38
|
-
- **talkpipe_ref**
|
|
39
|
-
Generates HTML and text documentation for all available sources and segments, making it easy to discover and understand built-in functionality.
|
|
40
|
-
|
|
41
|
-
- **talkpipe_endpoint**
|
|
42
|
-
Exposes ChatterLang pipelines as REST APIs or web forms, allowing you to deploy workflows as web services or user-facing endpoints.
|
|
43
|
-
|
|
44
|
-
These applications are entry points for different usage scenarios, from interactive development to production deployment.
|
|
45
|
-
|
|
46
|
-
The Docker layer provides ready-to-use container images for deploying TalkPipe in different environments. It includes:
|
|
47
|
-
|
|
48
|
-
- **talkpipe-base**
|
|
49
|
-
A minimal container image that contains all dependencies required by TalkPipe, but does not install TalkPipe itself. Use this as a foundation for building your own images, custom workflows, or CI/CD jobs where you want to control the installation of TalkPipe or add additional components.
|
|
50
|
-
|
|
51
|
-
- **chatterlang_script**
|
|
52
|
-
An image that installs TalkPipe on top of the base dependencies and runs a talkpipe script.
|
|
53
|
-
|
|
54
|
-
These containers exist to simplify deployment, ensure consistent environments, and enable rapid experimentation or production use of TalkPipe and ChatterLang across platforms.
|
|
55
|
-
|
|
56
16
|
## Quick Start
|
|
57
17
|
|
|
58
18
|
Install TalkPipe:
|
|
@@ -16,4 +16,4 @@ from talkpipe.operations.matrices import *
|
|
|
16
16
|
from talkpipe.operations.signatures import *
|
|
17
17
|
from talkpipe.app.apiendpoint import *
|
|
18
18
|
from talkpipe.search.whoosh import *
|
|
19
|
-
from talkpipe.
|
|
19
|
+
from talkpipe.vectordb.simplevectordb import *
|
|
@@ -451,17 +451,6 @@
|
|
|
451
451
|
<td class="toc-talkpipe">scale</td>
|
|
452
452
|
<td class="toc-description">Scale each item in the input stream by the multiplier.</td>
|
|
453
453
|
</tr>
|
|
454
|
-
<tr><td class="toc-package" colspan="3"><a href="#talkpipe-search-simplevectordb">talkpipe.search.simplevectordb</a></td></tr>
|
|
455
|
-
<tr>
|
|
456
|
-
<td class="toc-name"><a href="#talkpipe-search-simplevectordb-add_vector">add_vector</a></td>
|
|
457
|
-
<td class="toc-talkpipe">addVector</td>
|
|
458
|
-
<td class="toc-description">Segment to add a vector to the SimpleVectorDB.</td>
|
|
459
|
-
</tr>
|
|
460
|
-
<tr>
|
|
461
|
-
<td class="toc-name"><a href="#talkpipe-search-simplevectordb-search_vector">search_vector</a></td>
|
|
462
|
-
<td class="toc-talkpipe">searchVector</td>
|
|
463
|
-
<td class="toc-description">Segment to search for similar vectors in the SimpleVectorDB.</td>
|
|
464
|
-
</tr>
|
|
465
454
|
<tr><td class="toc-package" colspan="3"><a href="#talkpipe-search-whoosh">talkpipe.search.whoosh</a></td></tr>
|
|
466
455
|
<tr>
|
|
467
456
|
<td class="toc-name"><a href="#talkpipe-search-whoosh-indexWhoosh">indexWhoosh</a></td>
|
|
@@ -472,6 +461,17 @@
|
|
|
472
461
|
<td class="toc-name"><a href="#talkpipe-search-whoosh-searchWhoosh">searchWhoosh</a></td>
|
|
473
462
|
<td class="toc-talkpipe">searchWhoosh</td>
|
|
474
463
|
<td class="toc-description">Search documents using Whoosh full-text indexing.</td>
|
|
464
|
+
</tr>
|
|
465
|
+
<tr><td class="toc-package" colspan="3"><a href="#talkpipe-vectordb-simplevectordb">talkpipe.vectordb.simplevectordb</a></td></tr>
|
|
466
|
+
<tr>
|
|
467
|
+
<td class="toc-name"><a href="#talkpipe-vectordb-simplevectordb-add_vector">add_vector</a></td>
|
|
468
|
+
<td class="toc-talkpipe">addVector</td>
|
|
469
|
+
<td class="toc-description">Segment to add a vector to the SimpleVectorDB.</td>
|
|
470
|
+
</tr>
|
|
471
|
+
<tr>
|
|
472
|
+
<td class="toc-name"><a href="#talkpipe-vectordb-simplevectordb-search_vector">search_vector</a></td>
|
|
473
|
+
<td class="toc-talkpipe">searchVector</td>
|
|
474
|
+
<td class="toc-description">Segment to search for similar vectors in the SimpleVectorDB.</td>
|
|
475
475
|
</tr>
|
|
476
476
|
</tbody>
|
|
477
477
|
</table>
|
|
@@ -1319,7 +1319,6 @@ Returns:
|
|
|
1319
1319
|
<ul class="param-list">
|
|
1320
1320
|
<li>template: str</li>
|
|
1321
1321
|
<li>fail_on_missing: bool = True</li>
|
|
1322
|
-
<li>default: Optional[Any] = ''</li>
|
|
1323
1322
|
</ul>
|
|
1324
1323
|
</div>
|
|
1325
1324
|
<div class="class" id="talkpipe-pipe-basic-FilterExpression">
|
|
@@ -1539,7 +1538,6 @@ dictionary represents a row in the DataFrame.</pre></div>
|
|
|
1539
1538
|
<li>self</li>
|
|
1540
1539
|
<li>field_list: str = '_'</li>
|
|
1541
1540
|
<li>fail_on_missing: bool = True</li>
|
|
1542
|
-
<li>default: Optional[Any] = None</li>
|
|
1543
1541
|
</ul>
|
|
1544
1542
|
<p><strong>Base Classes:</strong> AbstractSegment</p>
|
|
1545
1543
|
</div>
|
|
@@ -1859,8 +1857,42 @@ Raises:
|
|
|
1859
1857
|
<li>multiplier: Union[int, float]</li>
|
|
1860
1858
|
</ul>
|
|
1861
1859
|
</div>
|
|
1862
|
-
<div class="package-header" id="talkpipe-search-
|
|
1863
|
-
<div class="function" id="talkpipe-search-
|
|
1860
|
+
<div class="package-header" id="talkpipe-search-whoosh">talkpipe.search.whoosh</div>
|
|
1861
|
+
<div class="function" id="talkpipe-search-whoosh-indexWhoosh">
|
|
1862
|
+
<h2>Segment Function: indexWhoosh</h2>
|
|
1863
|
+
<p class="talkpipe-name">Chatterlang Name: indexWhoosh</p>
|
|
1864
|
+
<div><pre>Index documents using Whoosh full-text indexing.
|
|
1865
|
+
|
|
1866
|
+
Args:
|
|
1867
|
+
fields (list[str]): List of fields to index.
|
|
1868
|
+
index_path (str): Path to the Whoosh index directory.
|
|
1869
|
+
yield_doc (bool): If True, yield each indexed document. Otherwise yield the original
|
|
1870
|
+
item.</pre></div>
|
|
1871
|
+
<h3>Parameters:</h3>
|
|
1872
|
+
<ul class="param-list">
|
|
1873
|
+
<li>index_path: str</li>
|
|
1874
|
+
<li>field_list: list[str] = ['_:content']</li>
|
|
1875
|
+
<li>yield_doc = False</li>
|
|
1876
|
+
</ul>
|
|
1877
|
+
</div>
|
|
1878
|
+
<div class="function" id="talkpipe-search-whoosh-searchWhoosh">
|
|
1879
|
+
<h2>Segment Function: searchWhoosh</h2>
|
|
1880
|
+
<p class="talkpipe-name">Chatterlang Name: searchWhoosh</p>
|
|
1881
|
+
<div><pre>Search documents using Whoosh full-text indexing.
|
|
1882
|
+
|
|
1883
|
+
Args:
|
|
1884
|
+
index_path (str): Path to the Whoosh index directory.
|
|
1885
|
+
limit (int): Maximum number of results to return for each query. Defaults to 100.
|
|
1886
|
+
all_results_at_once (bool): If True, yield all results at once. Otherwise, yield one result at a time.</pre></div>
|
|
1887
|
+
<h3>Parameters:</h3>
|
|
1888
|
+
<ul class="param-list">
|
|
1889
|
+
<li>index_path: str</li>
|
|
1890
|
+
<li>limit: int = 100</li>
|
|
1891
|
+
<li>all_results_at_once: bool = False</li>
|
|
1892
|
+
</ul>
|
|
1893
|
+
</div>
|
|
1894
|
+
<div class="package-header" id="talkpipe-vectordb-simplevectordb">talkpipe.vectordb.simplevectordb</div>
|
|
1895
|
+
<div class="function" id="talkpipe-vectordb-simplevectordb-add_vector">
|
|
1864
1896
|
<h2>Segment Function: add_vector</h2>
|
|
1865
1897
|
<p class="talkpipe-name">Chatterlang Name: addVector</p>
|
|
1866
1898
|
<div><pre>Segment to add a vector to the SimpleVectorDB.
|
|
@@ -1883,7 +1915,7 @@ Returns:
|
|
|
1883
1915
|
<li>overwrite: bool = False</li>
|
|
1884
1916
|
</ul>
|
|
1885
1917
|
</div>
|
|
1886
|
-
<div class="function" id="talkpipe-
|
|
1918
|
+
<div class="function" id="talkpipe-vectordb-simplevectordb-search_vector">
|
|
1887
1919
|
<h2>Segment Function: search_vector</h2>
|
|
1888
1920
|
<p class="talkpipe-name">Chatterlang Name: searchVector</p>
|
|
1889
1921
|
<div><pre>Segment to search for similar vectors in the SimpleVectorDB.
|
|
@@ -1894,7 +1926,7 @@ Args:
|
|
|
1894
1926
|
search_method: Search method ("brute-force", "brute-force-heap", or "k-means").
|
|
1895
1927
|
path: Optional path to a saved vector database.
|
|
1896
1928
|
Yields:
|
|
1897
|
-
List of
|
|
1929
|
+
List of tuples containing (vector_id, similarity_score, VectorRecord).</pre></div>
|
|
1898
1930
|
<h3>Parameters:</h3>
|
|
1899
1931
|
<ul class="param-list">
|
|
1900
1932
|
<li>path: str</li>
|
|
@@ -1903,51 +1935,6 @@ Yields:
|
|
|
1903
1935
|
<li>search_metric: str = 'cosine'</li>
|
|
1904
1936
|
<li>search_method: str = 'brute-force'</li>
|
|
1905
1937
|
</ul>
|
|
1906
|
-
</div>
|
|
1907
|
-
<div class="package-header" id="talkpipe-search-whoosh">talkpipe.search.whoosh</div>
|
|
1908
|
-
<div class="function" id="talkpipe-search-whoosh-indexWhoosh">
|
|
1909
|
-
<h2>Segment Function: indexWhoosh</h2>
|
|
1910
|
-
<p class="talkpipe-name">Chatterlang Name: indexWhoosh</p>
|
|
1911
|
-
<div><pre>Index documents using Whoosh full-text indexing.
|
|
1912
|
-
|
|
1913
|
-
Args:
|
|
1914
|
-
items: Iterator of items to index
|
|
1915
|
-
index_path (str): Path to the Whoosh index directory.
|
|
1916
|
-
field_list (list[str]): List of fields to index.
|
|
1917
|
-
yield_doc (bool): If True, yield each indexed document. Otherwise yield the original item.
|
|
1918
|
-
continue_on_error (bool): If True, continue processing other documents when one fails.
|
|
1919
|
-
overwrite (bool): If True, clear existing index before indexing.
|
|
1920
|
-
commit_seconds (int): If > 0, commit changes if it has been this many seconds since the last commit.</pre></div>
|
|
1921
|
-
<h3>Parameters:</h3>
|
|
1922
|
-
<ul class="param-list">
|
|
1923
|
-
<li>index_path: str</li>
|
|
1924
|
-
<li>field_list: list[str] = ['_:content']</li>
|
|
1925
|
-
<li>yield_doc = False</li>
|
|
1926
|
-
<li>continue_on_error = True</li>
|
|
1927
|
-
<li>overwrite = False</li>
|
|
1928
|
-
<li>commit_seconds: int = -1</li>
|
|
1929
|
-
</ul>
|
|
1930
|
-
</div>
|
|
1931
|
-
<div class="function" id="talkpipe-search-whoosh-searchWhoosh">
|
|
1932
|
-
<h2>Segment Function: searchWhoosh</h2>
|
|
1933
|
-
<p class="talkpipe-name">Chatterlang Name: searchWhoosh</p>
|
|
1934
|
-
<div><pre>Search documents using Whoosh full-text indexing.
|
|
1935
|
-
|
|
1936
|
-
Args:
|
|
1937
|
-
queries: Iterator of query strings
|
|
1938
|
-
index_path (str): Path to the Whoosh index directory.
|
|
1939
|
-
limit (int): Maximum number of results to return for each query. Defaults to 100.
|
|
1940
|
-
all_results_at_once (bool): If True, yield all results at once. Otherwise, yield one result at a time.
|
|
1941
|
-
continue_on_error (bool): If True, continue with next query when one fails.
|
|
1942
|
-
reload_seconds (int): If > 0, reload the index if the last search was at least this many seconds ago.</pre></div>
|
|
1943
|
-
<h3>Parameters:</h3>
|
|
1944
|
-
<ul class="param-list">
|
|
1945
|
-
<li>index_path: str</li>
|
|
1946
|
-
<li>limit: int = 100</li>
|
|
1947
|
-
<li>all_results_at_once: bool = False</li>
|
|
1948
|
-
<li>continue_on_error = True</li>
|
|
1949
|
-
<li>reload_seconds: int = 60</li>
|
|
1950
|
-
</ul>
|
|
1951
1938
|
</div>
|
|
1952
1939
|
</div>
|
|
1953
1940
|
</body>
|
|
@@ -810,7 +810,6 @@ Segment Function: fillTemplate
|
|
|
810
810
|
Parameters:
|
|
811
811
|
template: str
|
|
812
812
|
fail_on_missing: bool = True
|
|
813
|
-
default: Optional[Any] = ''
|
|
814
813
|
|
|
815
814
|
Segment Class: FilterExpression
|
|
816
815
|
Chatterlang Name: lambdaFilter
|
|
@@ -1004,7 +1003,6 @@ Segment Class: ToDict
|
|
|
1004
1003
|
Parameters:
|
|
1005
1004
|
field_list: str = '_'
|
|
1006
1005
|
fail_on_missing: bool = True
|
|
1007
|
-
default: Optional[Any] = None
|
|
1008
1006
|
|
|
1009
1007
|
Segment Class: ToList
|
|
1010
1008
|
Chatterlang Name: toList
|
|
@@ -1285,8 +1283,41 @@ Segment Function: scale
|
|
|
1285
1283
|
multiplier: Union[int, float]
|
|
1286
1284
|
|
|
1287
1285
|
|
|
1288
|
-
PACKAGE: talkpipe.search.
|
|
1289
|
-
|
|
1286
|
+
PACKAGE: talkpipe.search.whoosh
|
|
1287
|
+
-------------------------------
|
|
1288
|
+
|
|
1289
|
+
Segment Function: indexWhoosh
|
|
1290
|
+
Chatterlang Name: indexWhoosh
|
|
1291
|
+
Docstring:
|
|
1292
|
+
Index documents using Whoosh full-text indexing.
|
|
1293
|
+
|
|
1294
|
+
Args:
|
|
1295
|
+
fields (list[str]): List of fields to index.
|
|
1296
|
+
index_path (str): Path to the Whoosh index directory.
|
|
1297
|
+
yield_doc (bool): If True, yield each indexed document. Otherwise yield the original
|
|
1298
|
+
item.
|
|
1299
|
+
Parameters:
|
|
1300
|
+
index_path: str
|
|
1301
|
+
field_list: list[str] = ['_:content']
|
|
1302
|
+
yield_doc = False
|
|
1303
|
+
|
|
1304
|
+
Segment Function: searchWhoosh
|
|
1305
|
+
Chatterlang Name: searchWhoosh
|
|
1306
|
+
Docstring:
|
|
1307
|
+
Search documents using Whoosh full-text indexing.
|
|
1308
|
+
|
|
1309
|
+
Args:
|
|
1310
|
+
index_path (str): Path to the Whoosh index directory.
|
|
1311
|
+
limit (int): Maximum number of results to return for each query. Defaults to 100.
|
|
1312
|
+
all_results_at_once (bool): If True, yield all results at once. Otherwise, yield one result at a time.
|
|
1313
|
+
Parameters:
|
|
1314
|
+
index_path: str
|
|
1315
|
+
limit: int = 100
|
|
1316
|
+
all_results_at_once: bool = False
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
PACKAGE: talkpipe.vectordb.simplevectordb
|
|
1320
|
+
-----------------------------------------
|
|
1290
1321
|
|
|
1291
1322
|
Segment Function: add_vector
|
|
1292
1323
|
Chatterlang Name: addVector
|
|
@@ -1320,7 +1351,7 @@ Segment Function: search_vector
|
|
|
1320
1351
|
search_method: Search method ("brute-force", "brute-force-heap", or "k-means").
|
|
1321
1352
|
path: Optional path to a saved vector database.
|
|
1322
1353
|
Yields:
|
|
1323
|
-
List of
|
|
1354
|
+
List of tuples containing (vector_id, similarity_score, VectorRecord).
|
|
1324
1355
|
Parameters:
|
|
1325
1356
|
path: str
|
|
1326
1357
|
vector_field = '_'
|
|
@@ -1329,47 +1360,3 @@ Segment Function: search_vector
|
|
|
1329
1360
|
search_method: str = 'brute-force'
|
|
1330
1361
|
|
|
1331
1362
|
|
|
1332
|
-
PACKAGE: talkpipe.search.whoosh
|
|
1333
|
-
-------------------------------
|
|
1334
|
-
|
|
1335
|
-
Segment Function: indexWhoosh
|
|
1336
|
-
Chatterlang Name: indexWhoosh
|
|
1337
|
-
Docstring:
|
|
1338
|
-
Index documents using Whoosh full-text indexing.
|
|
1339
|
-
|
|
1340
|
-
Args:
|
|
1341
|
-
items: Iterator of items to index
|
|
1342
|
-
index_path (str): Path to the Whoosh index directory.
|
|
1343
|
-
field_list (list[str]): List of fields to index.
|
|
1344
|
-
yield_doc (bool): If True, yield each indexed document. Otherwise yield the original item.
|
|
1345
|
-
continue_on_error (bool): If True, continue processing other documents when one fails.
|
|
1346
|
-
overwrite (bool): If True, clear existing index before indexing.
|
|
1347
|
-
commit_seconds (int): If > 0, commit changes if it has been this many seconds since the last commit.
|
|
1348
|
-
Parameters:
|
|
1349
|
-
index_path: str
|
|
1350
|
-
field_list: list[str] = ['_:content']
|
|
1351
|
-
yield_doc = False
|
|
1352
|
-
continue_on_error = True
|
|
1353
|
-
overwrite = False
|
|
1354
|
-
commit_seconds: int = -1
|
|
1355
|
-
|
|
1356
|
-
Segment Function: searchWhoosh
|
|
1357
|
-
Chatterlang Name: searchWhoosh
|
|
1358
|
-
Docstring:
|
|
1359
|
-
Search documents using Whoosh full-text indexing.
|
|
1360
|
-
|
|
1361
|
-
Args:
|
|
1362
|
-
queries: Iterator of query strings
|
|
1363
|
-
index_path (str): Path to the Whoosh index directory.
|
|
1364
|
-
limit (int): Maximum number of results to return for each query. Defaults to 100.
|
|
1365
|
-
all_results_at_once (bool): If True, yield all results at once. Otherwise, yield one result at a time.
|
|
1366
|
-
continue_on_error (bool): If True, continue with next query when one fails.
|
|
1367
|
-
reload_seconds (int): If > 0, reload the index if the last search was at least this many seconds ago.
|
|
1368
|
-
Parameters:
|
|
1369
|
-
index_path: str
|
|
1370
|
-
limit: int = 100
|
|
1371
|
-
all_results_at_once: bool = False
|
|
1372
|
-
continue_on_error = True
|
|
1373
|
-
reload_seconds: int = 60
|
|
1374
|
-
|
|
1375
|
-
|
|
@@ -124,7 +124,7 @@ class Cast(AbstractSegment):
|
|
|
124
124
|
class ToDict(AbstractSegment):
|
|
125
125
|
"""Creates a dictionary from the input data."""
|
|
126
126
|
|
|
127
|
-
def __init__(self, field_list: str = "_", fail_on_missing: bool = True
|
|
127
|
+
def __init__(self, field_list: str = "_", fail_on_missing: bool = True):
|
|
128
128
|
"""Convert each item in the input string into a dictionary based on the provided parameter list.
|
|
129
129
|
|
|
130
130
|
Args:
|
|
@@ -392,7 +392,7 @@ class ConfigureLogger(AbstractSegment):
|
|
|
392
392
|
"""
|
|
393
393
|
yield from input_iter
|
|
394
394
|
|
|
395
|
-
def hash_data(data, algorithm="MD5", field_list="_", use_repr=False, fail_on_missing=True
|
|
395
|
+
def hash_data(data, algorithm="MD5", field_list="_", use_repr=False, fail_on_missing=True):
|
|
396
396
|
"""Hash a single data item using the specified parameters.
|
|
397
397
|
|
|
398
398
|
Args:
|
|
@@ -407,7 +407,7 @@ def hash_data(data, algorithm="MD5", field_list="_", use_repr=False, fail_on_mis
|
|
|
407
407
|
"""
|
|
408
408
|
hasher = hashlib.new(algorithm)
|
|
409
409
|
for field in field_list:
|
|
410
|
-
item = extract_property(data, field, fail_on_missing
|
|
410
|
+
item = extract_property(data, field, fail_on_missing)
|
|
411
411
|
if item is None:
|
|
412
412
|
if fail_on_missing:
|
|
413
413
|
raise ValueError(f"Field {field} value was None")
|
|
@@ -459,7 +459,7 @@ class Hash(AbstractSegment):
|
|
|
459
459
|
|
|
460
460
|
@registry.register_segment("fillTemplate")
|
|
461
461
|
@field_segment
|
|
462
|
-
def fillTemplate(item, template:str, fail_on_missing:bool=True
|
|
462
|
+
def fillTemplate(item, template:str, fail_on_missing:bool=True):
|
|
463
463
|
"""Fill a template string with values from the input item.
|
|
464
464
|
|
|
465
465
|
Args:
|
|
@@ -471,7 +471,7 @@ def fillTemplate(item, template:str, fail_on_missing:bool=True, default: Optiona
|
|
|
471
471
|
"""
|
|
472
472
|
assert template is not None
|
|
473
473
|
field_names = extract_template_field_names(template)
|
|
474
|
-
values = {field_name:extract_property(item, field_name, fail_on_missing=fail_on_missing
|
|
474
|
+
values = {field_name:extract_property(item, field_name, fail_on_missing=fail_on_missing) for field_name in field_names}
|
|
475
475
|
return fill_template(template, values)
|
|
476
476
|
|
|
477
477
|
@registry.register_segment("lambda")
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import List, Dict, Any, Optional
|
|
3
|
+
import uuid
|
|
4
|
+
from talkpipe.util.data_manipulation import extract_property
|
|
5
|
+
from whoosh import index
|
|
6
|
+
from whoosh.fields import Schema, TEXT, ID, STORED
|
|
7
|
+
from whoosh.qparser import MultifieldParser
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
class SearchResult:
|
|
11
|
+
"""A single search result."""
|
|
12
|
+
def __init__(self, doc_id: str, score: float, snippet: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None):
|
|
13
|
+
self.doc_id = doc_id
|
|
14
|
+
self.score = score
|
|
15
|
+
self.snippet = snippet
|
|
16
|
+
self.metadata = metadata or {}
|
|
17
|
+
|
|
18
|
+
class AbstractFullTextIndex(ABC):
|
|
19
|
+
"""Abstract base class for a full text index."""
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def add_document(self, document: dict[str, Any]) -> None:
|
|
23
|
+
"""Add or update a document in the index."""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def search(self, query: str, limit: int = 10) -> List[SearchResult]:
|
|
28
|
+
"""Search for documents matching the query."""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def clear(self) -> None:
|
|
33
|
+
"""Remove all documents from the index."""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
def __enter__(self):
|
|
37
|
+
"""Support context manager for resource management."""
|
|
38
|
+
return self
|
|
39
|
+
|
|
40
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
41
|
+
"""Support context manager for resource management."""
|
|
42
|
+
pass
|
|
43
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from typing import List, Any
|
|
2
|
+
import os
|
|
3
|
+
import uuid
|
|
4
|
+
from whoosh import index
|
|
5
|
+
from whoosh.fields import Schema, TEXT, ID
|
|
6
|
+
from whoosh.qparser import MultifieldParser
|
|
7
|
+
from talkpipe.pipe import segment
|
|
8
|
+
from talkpipe.chatterlang import register_segment
|
|
9
|
+
from talkpipe.util.data_manipulation import toDict
|
|
10
|
+
from talkpipe.util.config import parse_key_value_str
|
|
11
|
+
from .abstract import AbstractFullTextIndex, SearchResult
|
|
12
|
+
|
|
13
|
+
class WhooshFullTextIndex(AbstractFullTextIndex):
|
|
14
|
+
def __init__(self, index_path: str, fields: list[str] = None):
|
|
15
|
+
self.index_path = index_path
|
|
16
|
+
self.fields = fields
|
|
17
|
+
if not os.path.exists(index_path):
|
|
18
|
+
os.makedirs(index_path)
|
|
19
|
+
if index.exists_in(index_path):
|
|
20
|
+
self.ix = index.open_dir(index_path)
|
|
21
|
+
self.schema = self.ix.schema
|
|
22
|
+
ix_fields = set(self.ix.schema.names())
|
|
23
|
+
expected_fields = set(self.ix.schema.names())
|
|
24
|
+
if fields is not None:
|
|
25
|
+
expected_fields = set(['doc_id'] + fields)
|
|
26
|
+
if ix_fields != expected_fields:
|
|
27
|
+
raise ValueError(f"Index schema fields {ix_fields} do not match expected {expected_fields}")
|
|
28
|
+
self.fields = fields
|
|
29
|
+
else:
|
|
30
|
+
# Use fields from existing index if not provided
|
|
31
|
+
self.fields = [f for f in self.ix.schema.names() if f != 'doc_id']
|
|
32
|
+
else:
|
|
33
|
+
if fields is None:
|
|
34
|
+
raise ValueError("Fields must be provided when creating a new index.")
|
|
35
|
+
self.schema = Schema(
|
|
36
|
+
doc_id=ID(stored=True, unique=True),
|
|
37
|
+
**{field: TEXT(stored=True) for field in fields}
|
|
38
|
+
)
|
|
39
|
+
self.ix = index.create_in(index_path, self.schema)
|
|
40
|
+
self.writer = None
|
|
41
|
+
|
|
42
|
+
def __enter__(self):
|
|
43
|
+
self.writer = self.ix.writer()
|
|
44
|
+
return self
|
|
45
|
+
|
|
46
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
47
|
+
if self.writer is not None:
|
|
48
|
+
self.writer.commit()
|
|
49
|
+
self.writer = None
|
|
50
|
+
self.ix.close()
|
|
51
|
+
|
|
52
|
+
def add_document(self, document: dict[str, Any]) -> None:
|
|
53
|
+
doc_id = str(document.get("doc_id") or uuid.uuid4())
|
|
54
|
+
doc_fields = {field: str(document.get(field, "")) for field in self.fields}
|
|
55
|
+
if self.writer is not None:
|
|
56
|
+
self.writer.update_document(doc_id=doc_id, **doc_fields)
|
|
57
|
+
else:
|
|
58
|
+
with self.ix.writer() as writer:
|
|
59
|
+
writer.update_document(doc_id=doc_id, **doc_fields)
|
|
60
|
+
|
|
61
|
+
def search(self, query: str, limit: int = 100) -> List[SearchResult]:
|
|
62
|
+
with self.ix.searcher() as searcher:
|
|
63
|
+
parser = MultifieldParser(self.fields, schema=self.ix.schema)
|
|
64
|
+
q = parser.parse(query)
|
|
65
|
+
results = searcher.search(q, limit=limit)
|
|
66
|
+
search_results = []
|
|
67
|
+
for hit in results:
|
|
68
|
+
metadata = {field: hit.get(field) for field in self.fields}
|
|
69
|
+
search_results.append(
|
|
70
|
+
SearchResult(
|
|
71
|
+
doc_id=hit['doc_id'],
|
|
72
|
+
score=hit.score,
|
|
73
|
+
snippet=None,
|
|
74
|
+
metadata=metadata
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
return search_results
|
|
78
|
+
|
|
79
|
+
def clear(self) -> None:
|
|
80
|
+
if self.writer is not None:
|
|
81
|
+
self.writer.cancel()
|
|
82
|
+
self.writer = None
|
|
83
|
+
self.ix.close()
|
|
84
|
+
for fname in os.listdir(self.index_path):
|
|
85
|
+
fpath = os.path.join(self.index_path, fname)
|
|
86
|
+
if os.path.isfile(fpath):
|
|
87
|
+
os.remove(fpath)
|
|
88
|
+
self.ix = index.create_in(self.index_path, self.schema)
|
|
89
|
+
|
|
90
|
+
@register_segment("indexWhoosh")
|
|
91
|
+
@segment()
|
|
92
|
+
def indexWhoosh(items, index_path: str, field_list: list[str] = ["_:content"], yield_doc=False):
|
|
93
|
+
"""Index documents using Whoosh full-text indexing.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
fields (list[str]): List of fields to index.
|
|
97
|
+
index_path (str): Path to the Whoosh index directory.
|
|
98
|
+
yield_doc (bool): If True, yield each indexed document. Otherwise yield the original
|
|
99
|
+
item.
|
|
100
|
+
"""
|
|
101
|
+
field_list_dict = parse_key_value_str(field_list)
|
|
102
|
+
with WhooshFullTextIndex(index_path, list(field_list_dict.values())) as idx:
|
|
103
|
+
for item in items:
|
|
104
|
+
d = toDict(item, field_list, fail_on_missing=False)
|
|
105
|
+
d['doc_id'] = str(d.get('doc_id', uuid.uuid4()))
|
|
106
|
+
d_str = {k:str(v) for k, v in d.items()}
|
|
107
|
+
idx.add_document(d_str)
|
|
108
|
+
yield d if yield_doc else item
|
|
109
|
+
|
|
110
|
+
@register_segment("searchWhoosh")
|
|
111
|
+
@segment()
|
|
112
|
+
def searchWhoosh(queries, index_path: str, limit: int = 100, all_results_at_once: bool = False):
|
|
113
|
+
"""Search documents using Whoosh full-text indexing.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
index_path (str): Path to the Whoosh index directory.
|
|
117
|
+
limit (int): Maximum number of results to return for each query. Defaults to 100.
|
|
118
|
+
all_results_at_once (bool): If True, yield all results at once. Otherwise, yield one result at a time.
|
|
119
|
+
"""
|
|
120
|
+
with WhooshFullTextIndex(index_path) as idx:
|
|
121
|
+
for query in queries:
|
|
122
|
+
results = idx.search(query, limit=limit)
|
|
123
|
+
if all_results_at_once:
|
|
124
|
+
yield results
|
|
125
|
+
else:
|
|
126
|
+
for result in results:
|
|
127
|
+
yield result
|
|
@@ -115,7 +115,7 @@ def get_all_attributes(obj: Any, skip_packages: tuple = ('pydantic',), visited:
|
|
|
115
115
|
return attributes
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
def extract_property(data: Any, prop_list: str, fail_on_missing=False
|
|
118
|
+
def extract_property(data: Any, prop_list: str, fail_on_missing=False) -> Any:
|
|
119
119
|
"""Extract a property from a nested data structure using dot notation.
|
|
120
120
|
|
|
121
121
|
Args:
|
|
@@ -142,7 +142,7 @@ def extract_property(data: Any, prop_list: str, fail_on_missing=False, default=N
|
|
|
142
142
|
if fail_on_missing:
|
|
143
143
|
raise AttributeError(f"Property '{prop_name}' not found in the input data of type '{type(data)}'")
|
|
144
144
|
else:
|
|
145
|
-
return
|
|
145
|
+
return None
|
|
146
146
|
return of_interest
|
|
147
147
|
|
|
148
148
|
|