msgflux 0.1.0a1__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.
Files changed (114) hide show
  1. msgflux-0.1.0a1/.github/CODEOWNERS +5 -0
  2. msgflux-0.1.0a1/.github/dependabot.yml +7 -0
  3. msgflux-0.1.0a1/.github/workflows/publish.yml +119 -0
  4. msgflux-0.1.0a1/.gitignore +25 -0
  5. msgflux-0.1.0a1/.pre-commit-config.yaml +19 -0
  6. msgflux-0.1.0a1/.readthedocs.yaml +12 -0
  7. msgflux-0.1.0a1/LICENSE +21 -0
  8. msgflux-0.1.0a1/PKG-INFO +45 -0
  9. msgflux-0.1.0a1/README.md +1 -0
  10. msgflux-0.1.0a1/pyproject.toml +141 -0
  11. msgflux-0.1.0a1/src/msgflux/__init__.py +37 -0
  12. msgflux-0.1.0a1/src/msgflux/_private/__init__.py +0 -0
  13. msgflux-0.1.0a1/src/msgflux/_private/client.py +91 -0
  14. msgflux-0.1.0a1/src/msgflux/_private/core.py +14 -0
  15. msgflux-0.1.0a1/src/msgflux/_private/executor.py +77 -0
  16. msgflux-0.1.0a1/src/msgflux/cache.py +50 -0
  17. msgflux-0.1.0a1/src/msgflux/data/__init__.py +0 -0
  18. msgflux-0.1.0a1/src/msgflux/data/audio.py +1 -0
  19. msgflux-0.1.0a1/src/msgflux/data/databases/__init__.py +0 -0
  20. msgflux-0.1.0a1/src/msgflux/data/databases/base.py +32 -0
  21. msgflux-0.1.0a1/src/msgflux/data/databases/database.py +125 -0
  22. msgflux-0.1.0a1/src/msgflux/data/databases/providers/__init__.py +0 -0
  23. msgflux-0.1.0a1/src/msgflux/data/databases/providers/cachetools.py +64 -0
  24. msgflux-0.1.0a1/src/msgflux/data/databases/providers/diskcache.py +60 -0
  25. msgflux-0.1.0a1/src/msgflux/data/databases/providers/faiss.py +217 -0
  26. msgflux-0.1.0a1/src/msgflux/data/databases/types.py +20 -0
  27. msgflux-0.1.0a1/src/msgflux/data/parsers/__init__.py +0 -0
  28. msgflux-0.1.0a1/src/msgflux/data/parsers/base.py +11 -0
  29. msgflux-0.1.0a1/src/msgflux/data/parsers/parser.py +88 -0
  30. msgflux-0.1.0a1/src/msgflux/data/parsers/providers/__init__.py +0 -0
  31. msgflux-0.1.0a1/src/msgflux/data/parsers/providers/openpyxl.py +166 -0
  32. msgflux-0.1.0a1/src/msgflux/data/parsers/providers/pypdf.py +49 -0
  33. msgflux-0.1.0a1/src/msgflux/data/parsers/providers/python_pptx.py +167 -0
  34. msgflux-0.1.0a1/src/msgflux/data/parsers/types.py +23 -0
  35. msgflux-0.1.0a1/src/msgflux/data/retrievers/__init__.py +0 -0
  36. msgflux-0.1.0a1/src/msgflux/data/retrievers/base.py +12 -0
  37. msgflux-0.1.0a1/src/msgflux/data/retrievers/providers/__init__.py +0 -0
  38. msgflux-0.1.0a1/src/msgflux/data/retrievers/providers/bm25.py +188 -0
  39. msgflux-0.1.0a1/src/msgflux/data/retrievers/providers/rank_bm25.py +187 -0
  40. msgflux-0.1.0a1/src/msgflux/data/retrievers/retriever.py +80 -0
  41. msgflux-0.1.0a1/src/msgflux/data/retrievers/types.py +15 -0
  42. msgflux-0.1.0a1/src/msgflux/dotdict.py +169 -0
  43. msgflux-0.1.0a1/src/msgflux/dsl/__init__.py +0 -0
  44. msgflux-0.1.0a1/src/msgflux/dsl/inline.py +524 -0
  45. msgflux-0.1.0a1/src/msgflux/dsl/signature.py +400 -0
  46. msgflux-0.1.0a1/src/msgflux/envs.py +106 -0
  47. msgflux-0.1.0a1/src/msgflux/exceptions.py +31 -0
  48. msgflux-0.1.0a1/src/msgflux/generation/__init__.py +0 -0
  49. msgflux-0.1.0a1/src/msgflux/generation/reasoning/__init__.py +6 -0
  50. msgflux-0.1.0a1/src/msgflux/generation/reasoning/cot.py +70 -0
  51. msgflux-0.1.0a1/src/msgflux/generation/reasoning/react.py +47 -0
  52. msgflux-0.1.0a1/src/msgflux/generation/reasoning/self_consistency.py +42 -0
  53. msgflux-0.1.0a1/src/msgflux/generation/reasoning/tot.py +57 -0
  54. msgflux-0.1.0a1/src/msgflux/generation/templates.py +87 -0
  55. msgflux-0.1.0a1/src/msgflux/logger.py +148 -0
  56. msgflux-0.1.0a1/src/msgflux/message.py +43 -0
  57. msgflux-0.1.0a1/src/msgflux/models/__init__.py +0 -0
  58. msgflux-0.1.0a1/src/msgflux/models/base.py +31 -0
  59. msgflux-0.1.0a1/src/msgflux/models/gateway.py +242 -0
  60. msgflux-0.1.0a1/src/msgflux/models/httpx.py +39 -0
  61. msgflux-0.1.0a1/src/msgflux/models/model.py +170 -0
  62. msgflux-0.1.0a1/src/msgflux/models/providers/__init__.py +0 -0
  63. msgflux-0.1.0a1/src/msgflux/models/providers/base.py +123 -0
  64. msgflux-0.1.0a1/src/msgflux/models/providers/ctranslate2.py +144 -0
  65. msgflux-0.1.0a1/src/msgflux/models/providers/jinaai.py +237 -0
  66. msgflux-0.1.0a1/src/msgflux/models/providers/mistral.py +1 -0
  67. msgflux-0.1.0a1/src/msgflux/models/providers/ollama.py +34 -0
  68. msgflux-0.1.0a1/src/msgflux/models/providers/openai.py +955 -0
  69. msgflux-0.1.0a1/src/msgflux/models/providers/openrouter.py +20 -0
  70. msgflux-0.1.0a1/src/msgflux/models/providers/pylate.py +0 -0
  71. msgflux-0.1.0a1/src/msgflux/models/providers/sambanova.py +32 -0
  72. msgflux-0.1.0a1/src/msgflux/models/providers/timm.py +64 -0
  73. msgflux-0.1.0a1/src/msgflux/models/providers/together.py +45 -0
  74. msgflux-0.1.0a1/src/msgflux/models/providers/torchaudio.py +74 -0
  75. msgflux-0.1.0a1/src/msgflux/models/providers/torchvision.py +120 -0
  76. msgflux-0.1.0a1/src/msgflux/models/providers/vllm.py +86 -0
  77. msgflux-0.1.0a1/src/msgflux/models/response.py +76 -0
  78. msgflux-0.1.0a1/src/msgflux/models/tool_call_agg.py +93 -0
  79. msgflux-0.1.0a1/src/msgflux/models/types.py +180 -0
  80. msgflux-0.1.0a1/src/msgflux/nn/__init__.py +7 -0
  81. msgflux-0.1.0a1/src/msgflux/nn/functional.py +472 -0
  82. msgflux-0.1.0a1/src/msgflux/nn/modules/__init__.py +23 -0
  83. msgflux-0.1.0a1/src/msgflux/nn/modules/agent.py +1005 -0
  84. msgflux-0.1.0a1/src/msgflux/nn/modules/container.py +601 -0
  85. msgflux-0.1.0a1/src/msgflux/nn/modules/designer.py +273 -0
  86. msgflux-0.1.0a1/src/msgflux/nn/modules/module.py +1958 -0
  87. msgflux-0.1.0a1/src/msgflux/nn/modules/predictor.py +116 -0
  88. msgflux-0.1.0a1/src/msgflux/nn/modules/retriever.py +245 -0
  89. msgflux-0.1.0a1/src/msgflux/nn/modules/speaker.py +140 -0
  90. msgflux-0.1.0a1/src/msgflux/nn/modules/tool.py +296 -0
  91. msgflux-0.1.0a1/src/msgflux/nn/modules/transcriber.py +181 -0
  92. msgflux-0.1.0a1/src/msgflux/nn/parameter.py +75 -0
  93. msgflux-0.1.0a1/src/msgflux/py.typed +0 -0
  94. msgflux-0.1.0a1/src/msgflux/telemetry/__init__.py +0 -0
  95. msgflux-0.1.0a1/src/msgflux/telemetry/span.py +141 -0
  96. msgflux-0.1.0a1/src/msgflux/telemetry/tracer.py +48 -0
  97. msgflux-0.1.0a1/src/msgflux/utils/__init__.py +0 -0
  98. msgflux-0.1.0a1/src/msgflux/utils/chat.py +508 -0
  99. msgflux-0.1.0a1/src/msgflux/utils/common.py +25 -0
  100. msgflux-0.1.0a1/src/msgflux/utils/convert.py +41 -0
  101. msgflux-0.1.0a1/src/msgflux/utils/encode.py +101 -0
  102. msgflux-0.1.0a1/src/msgflux/utils/hooks.py +68 -0
  103. msgflux-0.1.0a1/src/msgflux/utils/imports.py +39 -0
  104. msgflux-0.1.0a1/src/msgflux/utils/inspect.py +110 -0
  105. msgflux-0.1.0a1/src/msgflux/utils/logging.py +15 -0
  106. msgflux-0.1.0a1/src/msgflux/utils/mermaid.py +11 -0
  107. msgflux-0.1.0a1/src/msgflux/utils/msgspec.py +489 -0
  108. msgflux-0.1.0a1/src/msgflux/utils/pooling.py +45 -0
  109. msgflux-0.1.0a1/src/msgflux/utils/tenacity.py +19 -0
  110. msgflux-0.1.0a1/src/msgflux/utils/tool.py +121 -0
  111. msgflux-0.1.0a1/src/msgflux/utils/torch.py +8 -0
  112. msgflux-0.1.0a1/src/msgflux/utils/validation.py +22 -0
  113. msgflux-0.1.0a1/src/msgflux/utils/xml.py +125 -0
  114. msgflux-0.1.0a1/src/msgflux/version.py +1 -0
@@ -0,0 +1,5 @@
1
+ # See https://help.github.com/articles/about-codeowners/
2
+ # for more info about CODEOWNERS file
3
+
4
+ # CODEOWNERS
5
+ * @vilsonrodrigues
@@ -0,0 +1,7 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: "uv"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
@@ -0,0 +1,119 @@
1
+ name: Release
2
+
3
+ # Dynamic run name that appears in the GitHub UI
4
+ run-name: Release version ${{ github.ref_name }} of the SDK
5
+
6
+ on:
7
+ # no explicit inputs for tag_name; rely on the selected reference from the UI
8
+ workflow_dispatch:
9
+
10
+ # ensures only a single instance of this release workflow is running at any one time
11
+ concurrency:
12
+ group: release-${{ github.ref_name }}
13
+ cancel-in-progress: true
14
+
15
+ env:
16
+ PACKAGE_NAME: "msgspec-ext"
17
+ TEST_PYPI_URL: "https://test.pypi.org/pypi"
18
+ PYPI_URL: "https://pypi.org/pypi"
19
+
20
+ jobs:
21
+ get_tag_details:
22
+ name: Get Tag Details
23
+ runs-on: msgflux-python-runner
24
+ outputs:
25
+ tag_name: ${{ steps.release.outputs.tag_name }}
26
+ new_version: ${{ steps.release.outputs.new_version }}
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ with:
30
+ fetch-depth: 0 # fetch all history
31
+
32
+ - name: Check if a tag is selected
33
+ run: |
34
+ if [ "${{ github.ref_type }}" != "tag" ]; then
35
+ echo "Error: Workflow must be triggered with a tag selected. Current ref_type is ${{ github.ref_type }}."
36
+ exit 1
37
+ fi
38
+ TAG_NAME=${{ github.ref_name }}
39
+ echo "Selected tag is $TAG_NAME"
40
+
41
+ - name: Extract version from tag
42
+ id: release
43
+ run: |
44
+ TAG_NAME=${{ github.ref_name }}
45
+ # Validate tag format
46
+ if [[ ! $TAG_NAME =~ ^v[0-9]+\.[0-9]+\.[0-9]+(a[0-9]+|b[0-9]+|rc[0-9]+)?$ ]]; then
47
+ echo "Invalid tag format. Tag must be in the format vX.Y.Z, vX.Y.ZaN, vX.Y.ZbN, or vX.Y.ZrcN."
48
+ exit 1
49
+ fi
50
+ NEW_VERSION=${TAG_NAME#v}
51
+ echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT"
52
+ echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
53
+ echo "Tag name is $TAG_NAME"
54
+ echo "Version is $NEW_VERSION"
55
+
56
+ setup_build_and_publish:
57
+ name: Build Package and Publish to PyPI
58
+ needs: [get_tag_details]
59
+ runs-on: msgflux-python-runner
60
+ permissions:
61
+ contents: read
62
+ id-token: write # Required for trusted publishing to PyPI
63
+ steps:
64
+ - name: Checkout the repository
65
+ uses: actions/checkout@v4
66
+ with:
67
+ fetch-depth: 0
68
+
69
+ - name: Set up Python
70
+ uses: actions/setup-python@v5
71
+ with:
72
+ python-version: "3.10"
73
+
74
+ - name: Install uv
75
+ uses: astral-sh/setup-uv@c7f87aa956e4c323abf06d5dec078e358f6b4d04 # v6
76
+ with:
77
+ version: "0.7.3"
78
+
79
+ - name: Install dependencies
80
+ run: uv sync --locked
81
+
82
+ - name: Build source and wheel distribution
83
+ run: |
84
+ uv build
85
+
86
+ - name: Upload build artifacts
87
+ uses: actions/upload-artifact@v4
88
+ with:
89
+ name: dist
90
+ path: dist/*
91
+ if-no-files-found: error
92
+
93
+ - name: Publish to PyPI
94
+ run: uv publish
95
+
96
+ github_release:
97
+ name: Create GitHub Release
98
+ needs: [get_tag_details, setup_build_and_publish]
99
+ runs-on: msgflux-python-runner
100
+ permissions:
101
+ contents: write
102
+ steps:
103
+ - name: Checkout Code
104
+ uses: actions/checkout@v4
105
+ with:
106
+ fetch-depth: 0
107
+
108
+ - name: Download build artifacts
109
+ uses: actions/download-artifact@v4
110
+ with:
111
+ name: dist
112
+ path: dist/
113
+
114
+ - name: Create GitHub Release
115
+ id: create_release
116
+ env:
117
+ GH_TOKEN: ${{ github.token }}
118
+ run: |
119
+ gh release create ${{ needs.get_tag_details.outputs.tag_name }} dist/* --title ${{ needs.get_tag_details.outputs.tag_name }} --generate-notes
@@ -0,0 +1,25 @@
1
+ env/
2
+ .env
3
+ venv/
4
+ .venv
5
+ .envrc
6
+ env3*/
7
+ Pipfile
8
+ *.lock
9
+ *.py[cod]
10
+ *.egg-info/
11
+ /build/
12
+ dist/
13
+ .cache/
14
+ /site/
15
+ /site.zip
16
+ .pytest_cache/
17
+ .python-version
18
+ __pycache__/
19
+ .vscode/
20
+ _build/
21
+ .auto-format
22
+ /sandbox/
23
+ /worktrees/
24
+ /.ruff_cache/
25
+ .DS_Store
@@ -0,0 +1,19 @@
1
+ default_install_hook_types: [pre-commit, pre-push]
2
+
3
+ repos:
4
+ - repo: https://github.com/gitleaks/gitleaks
5
+ rev: v8.23.1
6
+ hooks:
7
+ - id: gitleaks
8
+
9
+ - repo: https://github.com/astral-sh/uv-pre-commit
10
+ rev: 0.8.3 # uv version.
11
+ hooks:
12
+ - id: uv-lock
13
+
14
+ - repo: https://github.com/astral-sh/ruff-pre-commit
15
+ rev: v0.11.7
16
+ hooks:
17
+ - id: ruff
18
+ args: [--fix]
19
+ - id: ruff-format
@@ -0,0 +1,12 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ version: 2
5
+
6
+ build:
7
+ os: ubuntu-22.04
8
+ tools:
9
+ python: "3.12"
10
+
11
+ mkdocs:
12
+ configuration: mkdocs.yaml
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 msgflux
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.4
2
+ Name: msgflux
3
+ Version: 0.1.0a1
4
+ Summary: Messages and Dynamic AI Systems in Python powered by pretrained models
5
+ Project-URL: Homepage, https://github.com/msgflux/msgspec-ext
6
+ Project-URL: Documentation, https://github.com/msgflux/msgspec-ext
7
+ Project-URL: Repository, https://github.com/msgflux/msgspec-ext
8
+ Author-email: Vilson Rodrigues <vilson@msgflux.com>
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: MacOS :: MacOS X
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
26
+ Requires-Python: >=3.9
27
+ Requires-Dist: code2mermaid>=0.3.0
28
+ Requires-Dist: jinja2>=3.1.6
29
+ Requires-Dist: mermaid-py>=0.8.0
30
+ Requires-Dist: msgspec-ext>=0.1.0
31
+ Requires-Dist: opentelemetry-api>=1.35.0
32
+ Requires-Dist: opentelemetry-exporter-otlp>=1.35.0
33
+ Requires-Dist: opentelemetry-sdk>=1.35.0
34
+ Requires-Dist: tenacity>=9.1.2
35
+ Requires-Dist: tomli-w>=1.2.0
36
+ Requires-Dist: typing-extensions>=4.14.1
37
+ Requires-Dist: uvloop>=0.21.0
38
+ Provides-Extra: httpx
39
+ Requires-Dist: httpx>=0.28.1; extra == 'httpx'
40
+ Provides-Extra: openai
41
+ Requires-Dist: openai>=1.97.1; extra == 'openai'
42
+ Requires-Dist: opentelemetry-instrumentation-openai>=0.43.1; extra == 'openai'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # msgFlux
@@ -0,0 +1 @@
1
+ # msgFlux
@@ -0,0 +1,141 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+
6
+ [project]
7
+ name = "msgflux"
8
+ dynamic = ["version"]
9
+ description = "Messages and Dynamic AI Systems in Python powered by pretrained models"
10
+ readme = "README.md"
11
+ authors = [
12
+ { name = "Vilson Rodrigues", email = "vilson@msgflux.com" }
13
+ ]
14
+ requires-python = ">=3.9"
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Information Technology",
19
+ "Intended Audience :: Science/Research",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: MacOS :: MacOS X",
22
+ "Operating System :: POSIX :: Linux",
23
+ "Operating System :: Microsoft :: Windows",
24
+ "Programming Language :: Python",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
31
+ "Topic :: Scientific/Engineering :: Information Analysis"
32
+ ]
33
+ dependencies = [
34
+ "code2mermaid>=0.3.0",
35
+ "jinja2>=3.1.6",
36
+ "mermaid-py>=0.8.0",
37
+ "msgspec-ext>=0.1.0",
38
+ "opentelemetry-api>=1.35.0",
39
+ "opentelemetry-exporter-otlp>=1.35.0",
40
+ "opentelemetry-sdk>=1.35.0",
41
+ "tenacity>=9.1.2",
42
+ "tomli-w>=1.2.0",
43
+ "typing-extensions>=4.14.1",
44
+ "uvloop>=0.21.0",
45
+ ]
46
+
47
+ [tool.hatch.version]
48
+ path = "src/msgflux/version.py"
49
+
50
+ [dependency-groups]
51
+ dev = [
52
+ "pytest>=8.4.1",
53
+ "pytest-asyncio>=1.1.0",
54
+ "pytest-cov>=6.2.1",
55
+ "ruff>=0.12.5",
56
+ ]
57
+
58
+ [project.urls]
59
+ Homepage = "https://github.com/msgflux/msgspec-ext"
60
+ Documentation = "https://github.com/msgflux/msgspec-ext"
61
+ Repository = "https://github.com/msgflux/msgspec-ext"
62
+
63
+ [project.optional-dependencies]
64
+ openai = [
65
+ "openai>=1.97.1",
66
+ "opentelemetry-instrumentation-openai>=0.43.1",
67
+ ]
68
+ httpx = [
69
+ "httpx>=0.28.1",
70
+ ]
71
+
72
+ [tool.ruff]
73
+ target-version = "py39"
74
+ line-length = 88
75
+
76
+ [tool.ruff.lint]
77
+ select = [
78
+ "A",
79
+ "ARG",
80
+ "B",
81
+ "C",
82
+ "D",
83
+ "DTZ",
84
+ "E",
85
+ "EM",
86
+ "F",
87
+ "FBT",
88
+ "I",
89
+ "ICN",
90
+ "ISC",
91
+ "N",
92
+ "PLC",
93
+ "PLE",
94
+ "PLR",
95
+ "PLW",
96
+ "Q",
97
+ "RUF",
98
+ "S",
99
+ "T",
100
+ "TID",
101
+ "UP",
102
+ "W",
103
+ "YTT",
104
+ ]
105
+ ignore = [
106
+ "D100", # Allow missing docstring in top level module
107
+ "D104", # Allow missing docstring in public package
108
+ "D105", # Allow missing docstring in magic method
109
+ "D203", # Allow docstring directly below class definition (as enforced by D211)
110
+ "D213", # Allow multi-line-summary on first line of docstring (as enforced by D212)
111
+ "D401", # Allow non imperative mood in docstring
112
+ "D413", # Allow no new line at end of docstring.
113
+ "EM101", # Allow `raise ValueError(msg)`
114
+ "EM102", # Allow f strings in `raise` statements
115
+ "FBT003", # Allow boolean positional values in function calls, like `dict.get(... True)`
116
+ "TID252", # Allow relative imports
117
+ "UP007", # Allow `from typing import Optional` instead of `X | None`
118
+ "UP035", # Allow `from typing import Sequence` instead of `Sequence[X]`
119
+ "PLR0913",
120
+ ]
121
+ unfixable = ["F401"]
122
+
123
+ [tool.ruff.lint.isort]
124
+ known-first-party = ["msgflux"]
125
+
126
+ [tool.ruff.lint.flake8-tidy-imports]
127
+ ban-relative-imports = "all"
128
+
129
+ [tool.ruff.lint.per-file-ignores]
130
+ "tests/**/*" = [
131
+ "D",
132
+ "PLR0911",
133
+ "PLR0912",
134
+ "PLR0915",
135
+ "PLR2004",
136
+ "S101",
137
+ "S105",
138
+ "S106",
139
+ "S107",
140
+ "TID252",
141
+ ]
@@ -0,0 +1,37 @@
1
+ from .cache import response_cache
2
+ from .data.databases.database import DataBase
3
+ from .data.retrievers.retriever import Retriever
4
+ from .dotdict import dotdict
5
+ from .dsl.inline import inline
6
+ from .dsl.signature import InputField, OutputField, Signature
7
+ from .envs import set_envs
8
+ from .message import Message
9
+ from .models.gateway import ModelGateway
10
+ from .models.model import Model
11
+ from .utils.chat import ChatML
12
+ from .utils.inspect import get_fn_name
13
+ from .utils.msgspec import load, save
14
+ from .utils.tool import tool_config
15
+ from .telemetry.span import instrument
16
+
17
+
18
+ __all__ = [
19
+ "ChatML",
20
+ "DataBase",
21
+ "InputField",
22
+ "Message",
23
+ "Model",
24
+ "ModelGateway",
25
+ "OutputField",
26
+ "Retriever",
27
+ "Signature",
28
+ "dotdict",
29
+ "get_fn_name",
30
+ "inline",
31
+ "instrument",
32
+ "load",
33
+ "response_cache",
34
+ "save",
35
+ "set_envs",
36
+ "tool_config"
37
+ ]
File without changes
@@ -0,0 +1,91 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict
3
+ from msgflux._private.core import Core
4
+
5
+
6
+ class BaseClient(ABC, Core):
7
+ """
8
+ BaseClient is an abstract base class that defines the interface and common behavior
9
+ for client classes in the msgflux system.
10
+
11
+ This class inherits from `Core` to leverage its state management capabilities and
12
+ extends it with additional functionality specific to clients. It requires subclasses
13
+ to implement certain methods, ensuring a consistent interface across different client
14
+ implementations.
15
+
16
+ Subclasses must implement the `_initialize` and `__call__` methods, which are
17
+ essential for client initialization and operation, respectively. Additionally, this
18
+ class provides methods for serialization and deserialization, allowing client instances
19
+ to be easily saved and restored.
20
+
21
+ Attributes:
22
+ to_ignore ([optional[list[str]]): A list of attribute keys to be ignored during serialization.
23
+ msgflux_type (str): A string identifying the type of the client in the msgflux system.
24
+ provider (optional[str]): The provider associated with the client, if applicable.
25
+ instance_type (optional[callable]): A method or callable that returns additional
26
+ instance-specific data to be included during serialization.
27
+ """
28
+
29
+ @abstractmethod
30
+ def __call__(self):
31
+ """
32
+ Execute the client's main functionality. This method must be implemented by subclasses.
33
+
34
+ This method defines the primary behavior of the client and is called when the instance
35
+ is invoked as a function.
36
+
37
+ Raises:
38
+ NotImplementedError: If the method is not implemented by the subclass.
39
+ """
40
+ raise NotImplementedError
41
+
42
+ async def acall(self, *args, **kwargs):
43
+ """ Async interface to __call__ """
44
+ return self.__call__(*args, **kwargs)
45
+
46
+ def serialize(self) -> Dict[str, Any]:
47
+ """
48
+ Serialize the client instance into a dictionary.
49
+
50
+ This method prepares the client's state for serialization by removing unnecessary
51
+ attributes and including additional metadata such as the client type and provider.
52
+
53
+ Returns:
54
+ Dict[str, Any]: A dictionary containing the serialized state of the client,
55
+ including metadata and the client's internal state.
56
+ """
57
+ state = self.__getstate__()
58
+ if hasattr(self, "to_ignore"):
59
+ for key in self.to_ignore:
60
+ state.pop(key, None)
61
+ data = {"msgflux_type": self.msgflux_type}
62
+ if hasattr(self, "provider"):
63
+ data["provider"] = self.provider
64
+ if hasattr(self, "instance_type"):
65
+ instance_type = self.instance_type()
66
+ data.update(instance_type)
67
+ data["state"] = state
68
+ return data
69
+
70
+ @classmethod
71
+ def from_serialized(cls, state: Dict[str, Any]):
72
+ """
73
+ Deserialize a client instance from a dictionary.
74
+
75
+ This method creates a new instance of the client and restores its state from the
76
+ provided dictionary. It also ensures that the client is properly initialized
77
+ after deserialization.
78
+
79
+ Args:
80
+ state (Dict[str, Any]): A dictionary containing the serialized state of the client.
81
+
82
+ Returns:
83
+ BaseClient: A new instance of the client with its state restored.
84
+ """
85
+ if "msgflux_type" in state:
86
+ state.pop("msgflux_type")
87
+ instance = cls()
88
+ instance.__setstate__(state)
89
+ if hasattr(instance, "_initialize"):
90
+ instance._initialize()
91
+ return instance
@@ -0,0 +1,14 @@
1
+ class Core:
2
+ """
3
+ Core is a set of methods that are common among some classes in msgflux.
4
+
5
+ This class provides basic functionality for state management, allowing instances
6
+ to be serialized and deserialized. It is intended to be inherited by other classes
7
+ that require these common features.
8
+ """
9
+ def __getstate__(self):
10
+ state = self.__dict__.copy()
11
+ return state
12
+
13
+ def __setstate__(self, state):
14
+ self.__dict__.update(state)
@@ -0,0 +1,77 @@
1
+ import asyncio
2
+ import threading
3
+ from concurrent.futures import ThreadPoolExecutor
4
+ from typing import Callable
5
+ import uvloop
6
+ from msgflux.envs import envs
7
+
8
+
9
+ class AsyncWorker:
10
+ def __init__(self):
11
+ """Initializes a worker with its own event loop in a separate thread."""
12
+ self.loop = uvloop.new_event_loop()
13
+ self.thread = threading.Thread(target=self.loop.run_forever)
14
+ self.thread.start()
15
+
16
+ def submit(self, coro):
17
+ """Submits a coroutine to the worker's event loop."""
18
+ return asyncio.run_coroutine_threadsafe(coro, self.loop)
19
+
20
+ def shutdown(self):
21
+ """Terminates the event loop and worker thread."""
22
+ self.loop.call_soon_threadsafe(self.loop.stop)
23
+ self.thread.join()
24
+
25
+
26
+ class Executor:
27
+ """
28
+ Async pool to manage the execution of synchronous and asynchronous code.
29
+ Executor distributes tasks among a ThreadPool or among Async Workers.
30
+ """
31
+ _instance = None
32
+ _lock = threading.Lock()
33
+
34
+ def __init__(self):
35
+ self.num_threads = envs.executor_num_threads
36
+ self.num_async_workers = envs.executor_num_async_workers
37
+ self.async_worker_index = 0
38
+ self.thread_pool = ThreadPoolExecutor(max_workers=self.num_threads)
39
+ self.async_workers = [AsyncWorker() for _ in range(self.num_async_workers)]
40
+
41
+ @classmethod
42
+ def get_instance(cls):
43
+ """Returns the singleton instance in a thread-safe manner."""
44
+ if cls._instance is None:
45
+ with cls._lock:
46
+ if cls._instance is None:
47
+ cls._instance = cls()
48
+ return cls._instance
49
+
50
+ def submit(self, f: Callable, *args, **kwargs):
51
+ """
52
+ Submits a task to the appropriate pool based on the function type.
53
+ Returns a Future to track the result.
54
+ """
55
+ if hasattr(f, "acall"):
56
+ coro = f.acall(*args, **kwargs)
57
+ return self._submit_to_async_worker(coro)
58
+ elif asyncio.iscoroutinefunction(f):
59
+ coro = f(*args, **kwargs)
60
+ return self._submit_to_async_worker(coro)
61
+ else:
62
+ return self.thread_pool.submit(f, *args, **kwargs)
63
+
64
+ def _submit_to_async_worker(self, coro):
65
+ """Distribute a coroutine to an asynchronous worker using round-robin."""
66
+ worker = self.async_workers[self.async_worker_index]
67
+ self.async_worker_index = (self.async_worker_index + 1) % self.num_async_workers
68
+ return worker.submit(coro)
69
+
70
+ def shutdown(self):
71
+ """Shutdown the executor, closing the pools."""
72
+ self.thread_pool.shutdown()
73
+ for worker in self.async_workers:
74
+ worker.shutdown()
75
+
76
+ def __del__(self):
77
+ self.shutdown()
@@ -0,0 +1,50 @@
1
+ from functools import wraps
2
+ from typing import Optional
3
+ from msgflux.data.databases.base import BaseDB
4
+ from msgflux.message import Message
5
+ from msgflux.models.types import TextEmbedderModel
6
+
7
+
8
+ def response_cache(
9
+ db: BaseDB,
10
+ task_inputs: Optional[str] = None,
11
+ response_mode: Optional[str] = None,
12
+ model: Optional[TextEmbedderModel] = None,
13
+ ):
14
+ def decorator(func):
15
+ @wraps(func)
16
+ def wrapper(msg):
17
+ if isinstance(msg, Message):
18
+ if task_inputs is None:
19
+ raise ValueError(
20
+ "`task_inputs` is required when input "
21
+ "is a Message instance"
22
+ )
23
+ key = msg.get(task_inputs)
24
+ else:
25
+ key = msg
26
+
27
+ if model:
28
+ key = model(key)
29
+
30
+ cached_response = db(key)
31
+
32
+ if cached_response is not None:
33
+ if isinstance(msg, Message):
34
+ if response_mode is None:
35
+ raise ValueError(
36
+ "`response_mode` is required when "
37
+ "input is a Message instance"
38
+ )
39
+ msg.set(response_mode, cached_response)
40
+ return msg
41
+ return cached_response
42
+
43
+ response = func(msg)
44
+
45
+ if response is not None:
46
+ db.add(key, response)
47
+
48
+ return response
49
+ return wrapper
50
+ return decorator
File without changes
@@ -0,0 +1 @@
1
+ #https://github.com/openai/openai-python/blob/384e6b23ce0366d6b2f31cc98d35525da5b22c10/src/openai/helpers/local_audio_player.py#L19
File without changes