Spaces:
Sleeping
Sleeping
Soroush commited on
Commit ·
e9e7c9c
1
Parent(s): b775d7c
phonetic mcp
Browse files- .dockerignore +91 -0
- .gemini/settings.json +10 -0
- .gitignore +219 -0
- .python-version +1 -0
- Dockerfile +20 -0
- GEMINI.md +45 -0
- README.md +95 -1
- app.py +41 -0
- pyproject.toml +19 -0
- src/phonetics_mcp/__init__.py +0 -0
- src/phonetics_mcp/phoneference.py +140 -0
- src/phonetics_mcp/py.typed +0 -0
- uv.lock +0 -0
.dockerignore
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Git
|
| 2 |
+
.git
|
| 3 |
+
.gitignore
|
| 4 |
+
.gitattributes
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
# CI
|
| 8 |
+
.codeclimate.yml
|
| 9 |
+
.travis.yml
|
| 10 |
+
.taskcluster.yml
|
| 11 |
+
|
| 12 |
+
# Docker
|
| 13 |
+
docker-compose.yml
|
| 14 |
+
Dockerfile
|
| 15 |
+
.docker
|
| 16 |
+
.dockerignore
|
| 17 |
+
|
| 18 |
+
# Byte-compiled / optimized / DLL files
|
| 19 |
+
**/__pycache__/
|
| 20 |
+
**/*.py[cod]
|
| 21 |
+
|
| 22 |
+
# C extensions
|
| 23 |
+
*.so
|
| 24 |
+
|
| 25 |
+
# Distribution / packaging
|
| 26 |
+
.Python
|
| 27 |
+
env/
|
| 28 |
+
build/
|
| 29 |
+
develop-eggs/
|
| 30 |
+
dist/
|
| 31 |
+
downloads/
|
| 32 |
+
eggs/
|
| 33 |
+
lib/
|
| 34 |
+
lib64/
|
| 35 |
+
parts/
|
| 36 |
+
sdist/
|
| 37 |
+
var/
|
| 38 |
+
*.egg-info/
|
| 39 |
+
.installed.cfg
|
| 40 |
+
*.egg
|
| 41 |
+
|
| 42 |
+
# PyInstaller
|
| 43 |
+
# Usually these files are written by a python script from a template
|
| 44 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 45 |
+
*.manifest
|
| 46 |
+
*.spec
|
| 47 |
+
|
| 48 |
+
# Installer logs
|
| 49 |
+
pip-log.txt
|
| 50 |
+
pip-delete-this-directory.txt
|
| 51 |
+
|
| 52 |
+
# Unit test / coverage reports
|
| 53 |
+
htmlcov/
|
| 54 |
+
.tox/
|
| 55 |
+
.coverage
|
| 56 |
+
.cache
|
| 57 |
+
nosetests.xml
|
| 58 |
+
coverage.xml
|
| 59 |
+
|
| 60 |
+
# Translations
|
| 61 |
+
*.mo
|
| 62 |
+
*.pot
|
| 63 |
+
|
| 64 |
+
# Django stuff:
|
| 65 |
+
*.log
|
| 66 |
+
|
| 67 |
+
# Sphinx documentation
|
| 68 |
+
docs/_build/
|
| 69 |
+
|
| 70 |
+
# PyBuilder
|
| 71 |
+
target/
|
| 72 |
+
|
| 73 |
+
# Virtual environment
|
| 74 |
+
.env
|
| 75 |
+
.venv/
|
| 76 |
+
venv/
|
| 77 |
+
|
| 78 |
+
# PyCharm
|
| 79 |
+
.idea
|
| 80 |
+
|
| 81 |
+
# Python mode for VIM
|
| 82 |
+
.ropeproject
|
| 83 |
+
**/.ropeproject
|
| 84 |
+
|
| 85 |
+
# Vim swap files
|
| 86 |
+
**/*.swp
|
| 87 |
+
|
| 88 |
+
# VS Code
|
| 89 |
+
.vscode/
|
| 90 |
+
|
| 91 |
+
tmp
|
.gemini/settings.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"mcpServers": {
|
| 3 |
+
"playwright": {
|
| 4 |
+
"command": "npx",
|
| 5 |
+
"args": [
|
| 6 |
+
"@playwright/mcp@latest"
|
| 7 |
+
]
|
| 8 |
+
}
|
| 9 |
+
}
|
| 10 |
+
}
|
.gitignore
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[codz]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
*.so
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
lib/
|
| 18 |
+
lib64/
|
| 19 |
+
parts/
|
| 20 |
+
sdist/
|
| 21 |
+
var/
|
| 22 |
+
wheels/
|
| 23 |
+
share/python-wheels/
|
| 24 |
+
*.egg-info/
|
| 25 |
+
.installed.cfg
|
| 26 |
+
*.egg
|
| 27 |
+
MANIFEST
|
| 28 |
+
|
| 29 |
+
# PyInstaller
|
| 30 |
+
# Usually these files are written by a python script from a template
|
| 31 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 32 |
+
*.manifest
|
| 33 |
+
*.spec
|
| 34 |
+
|
| 35 |
+
# Installer logs
|
| 36 |
+
pip-log.txt
|
| 37 |
+
pip-delete-this-directory.txt
|
| 38 |
+
|
| 39 |
+
# Unit test / coverage reports
|
| 40 |
+
htmlcov/
|
| 41 |
+
.tox/
|
| 42 |
+
.nox/
|
| 43 |
+
.coverage
|
| 44 |
+
.coverage.*
|
| 45 |
+
.cache
|
| 46 |
+
nosetests.xml
|
| 47 |
+
coverage.xml
|
| 48 |
+
*.cover
|
| 49 |
+
*.py.cover
|
| 50 |
+
.hypothesis/
|
| 51 |
+
.pytest_cache/
|
| 52 |
+
cover/
|
| 53 |
+
|
| 54 |
+
# Translations
|
| 55 |
+
*.mo
|
| 56 |
+
*.pot
|
| 57 |
+
|
| 58 |
+
# Django stuff:
|
| 59 |
+
*.log
|
| 60 |
+
local_settings.py
|
| 61 |
+
db.sqlite3
|
| 62 |
+
db.sqlite3-journal
|
| 63 |
+
|
| 64 |
+
# Flask stuff:
|
| 65 |
+
instance/
|
| 66 |
+
.webassets-cache
|
| 67 |
+
|
| 68 |
+
# Scrapy stuff:
|
| 69 |
+
.scrapy
|
| 70 |
+
|
| 71 |
+
# Sphinx documentation
|
| 72 |
+
docs/_build/
|
| 73 |
+
|
| 74 |
+
# PyBuilder
|
| 75 |
+
.pybuilder/
|
| 76 |
+
target/
|
| 77 |
+
|
| 78 |
+
# Jupyter Notebook
|
| 79 |
+
.ipynb_checkpoints
|
| 80 |
+
|
| 81 |
+
# IPython
|
| 82 |
+
profile_default/
|
| 83 |
+
ipython_config.py
|
| 84 |
+
|
| 85 |
+
# pyenv
|
| 86 |
+
# For a library or package, you might want to ignore these files since the code is
|
| 87 |
+
# intended to run in multiple environments; otherwise, check them in:
|
| 88 |
+
# .python-version
|
| 89 |
+
|
| 90 |
+
# pipenv
|
| 91 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
| 92 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 93 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 94 |
+
# install all needed dependencies.
|
| 95 |
+
# Pipfile.lock
|
| 96 |
+
|
| 97 |
+
# UV
|
| 98 |
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
| 99 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 100 |
+
# commonly ignored for libraries.
|
| 101 |
+
# uv.lock
|
| 102 |
+
|
| 103 |
+
# poetry
|
| 104 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
| 105 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 106 |
+
# commonly ignored for libraries.
|
| 107 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
| 108 |
+
# poetry.lock
|
| 109 |
+
# poetry.toml
|
| 110 |
+
|
| 111 |
+
# pdm
|
| 112 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
| 113 |
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
| 114 |
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
| 115 |
+
# pdm.lock
|
| 116 |
+
# pdm.toml
|
| 117 |
+
.pdm-python
|
| 118 |
+
.pdm-build/
|
| 119 |
+
|
| 120 |
+
# pixi
|
| 121 |
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
| 122 |
+
# pixi.lock
|
| 123 |
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
| 124 |
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
| 125 |
+
.pixi
|
| 126 |
+
|
| 127 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
| 128 |
+
__pypackages__/
|
| 129 |
+
|
| 130 |
+
# Celery stuff
|
| 131 |
+
celerybeat-schedule
|
| 132 |
+
celerybeat.pid
|
| 133 |
+
|
| 134 |
+
# Redis
|
| 135 |
+
*.rdb
|
| 136 |
+
*.aof
|
| 137 |
+
*.pid
|
| 138 |
+
|
| 139 |
+
# RabbitMQ
|
| 140 |
+
mnesia/
|
| 141 |
+
rabbitmq/
|
| 142 |
+
rabbitmq-data/
|
| 143 |
+
|
| 144 |
+
# ActiveMQ
|
| 145 |
+
activemq-data/
|
| 146 |
+
|
| 147 |
+
# SageMath parsed files
|
| 148 |
+
*.sage.py
|
| 149 |
+
|
| 150 |
+
# Environments
|
| 151 |
+
.env
|
| 152 |
+
.envrc
|
| 153 |
+
.venv
|
| 154 |
+
env/
|
| 155 |
+
venv/
|
| 156 |
+
ENV/
|
| 157 |
+
env.bak/
|
| 158 |
+
venv.bak/
|
| 159 |
+
|
| 160 |
+
# Spyder project settings
|
| 161 |
+
.spyderproject
|
| 162 |
+
.spyproject
|
| 163 |
+
|
| 164 |
+
# Rope project settings
|
| 165 |
+
.ropeproject
|
| 166 |
+
|
| 167 |
+
# mkdocs documentation
|
| 168 |
+
/site
|
| 169 |
+
|
| 170 |
+
# mypy
|
| 171 |
+
.mypy_cache/
|
| 172 |
+
.dmypy.json
|
| 173 |
+
dmypy.json
|
| 174 |
+
|
| 175 |
+
# Pyre type checker
|
| 176 |
+
.pyre/
|
| 177 |
+
|
| 178 |
+
# pytype static type analyzer
|
| 179 |
+
.pytype/
|
| 180 |
+
|
| 181 |
+
# Cython debug symbols
|
| 182 |
+
cython_debug/
|
| 183 |
+
|
| 184 |
+
# PyCharm
|
| 185 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
| 186 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
| 187 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
| 188 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
| 189 |
+
# .idea/
|
| 190 |
+
|
| 191 |
+
# Abstra
|
| 192 |
+
# Abstra is an AI-powered process automation framework.
|
| 193 |
+
# Ignore directories containing user credentials, local state, and settings.
|
| 194 |
+
# Learn more at https://abstra.io/docs
|
| 195 |
+
.abstra/
|
| 196 |
+
|
| 197 |
+
# Visual Studio Code
|
| 198 |
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
| 199 |
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
| 200 |
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
| 201 |
+
# you could uncomment the following to ignore the entire vscode folder
|
| 202 |
+
# .vscode/
|
| 203 |
+
|
| 204 |
+
# Ruff stuff:
|
| 205 |
+
.ruff_cache/
|
| 206 |
+
|
| 207 |
+
# PyPI configuration file
|
| 208 |
+
.pypirc
|
| 209 |
+
|
| 210 |
+
# Marimo
|
| 211 |
+
marimo/_static/
|
| 212 |
+
marimo/_lsp/
|
| 213 |
+
__marimo__/
|
| 214 |
+
|
| 215 |
+
# Streamlit
|
| 216 |
+
.streamlit/secrets.toml
|
| 217 |
+
|
| 218 |
+
tmp
|
| 219 |
+
.gemini/
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.13
|
Dockerfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#FROM 3.13.9-trixie
|
| 2 |
+
FROM ghcr.io/astral-sh/uv:trixie-slim
|
| 3 |
+
|
| 4 |
+
RUN apt-get update && apt-get install -y \
|
| 5 |
+
git \
|
| 6 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 7 |
+
|
| 8 |
+
RUN useradd -m -u 1000 user
|
| 9 |
+
USER user
|
| 10 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 11 |
+
|
| 12 |
+
WORKDIR /app
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
#COPY --chown=user ./requirements.txt requirements.txt
|
| 16 |
+
COPY --chown=user ./ .
|
| 17 |
+
RUN uv sync --dev --no-cache
|
| 18 |
+
|
| 19 |
+
COPY --chown=user . /app
|
| 20 |
+
CMD ["uv", "run", "python", "app.py"]
|
GEMINI.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Project Overview
|
| 2 |
+
|
| 3 |
+
This is a Python-based web application that uses the Gradio framework to create a user interface for a machine learning model. The project includes LiteLLM, which suggests it interacts with various Large Language Model (LLM) APIs. The application is containerized using Docker and is likely intended for deployment on a platform like Hugging Face Spaces.
|
| 4 |
+
|
| 5 |
+
**Key Technologies:**
|
| 6 |
+
|
| 7 |
+
* **Python:** The core programming language.
|
| 8 |
+
* **Gradio:** Used to build the web-based UI for the machine learning model.
|
| 9 |
+
* **LiteLLM:** A library to simplify calls to various LLM APIs.
|
| 10 |
+
* **Uvicorn:** An ASGI server used to run the Gradio application.
|
| 11 |
+
* **Docker:** Used for containerizing the application for deployment.
|
| 12 |
+
* **uv:** A fast Python package installer and resolver, used for dependency management.
|
| 13 |
+
|
| 14 |
+
# Building and Running
|
| 15 |
+
|
| 16 |
+
The project is set up to be run as a Docker container.
|
| 17 |
+
|
| 18 |
+
**Running the Application:**
|
| 19 |
+
|
| 20 |
+
The `Dockerfile` specifies the command to run the application using `uvicorn`:
|
| 21 |
+
|
| 22 |
+
```bash
|
| 23 |
+
uvicorn app:app --host 0.0.0.0 --port 7860
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
This command starts the Uvicorn server, which serves the Gradio application defined in `app.py`.
|
| 27 |
+
|
| 28 |
+
**Dependencies:**
|
| 29 |
+
|
| 30 |
+
Project dependencies are managed in the `pyproject.toml` file and installed using `uv`. The main dependencies are:
|
| 31 |
+
|
| 32 |
+
* `gradio`
|
| 33 |
+
* `litellm`
|
| 34 |
+
|
| 35 |
+
To install dependencies, you can use the following command:
|
| 36 |
+
|
| 37 |
+
```bash
|
| 38 |
+
uv sync --dev
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
# Development Conventions
|
| 42 |
+
|
| 43 |
+
* **Application Entrypoint:** The main application logic is expected to be in `app.py`. The Gradio application instance should be named `app`.
|
| 44 |
+
* **Dependency Management:** Dependencies are managed with `uv` and the `pyproject.toml` file.
|
| 45 |
+
* **Containerization:** The application is designed to be built and run as a Docker container. The `Dockerfile` in the root of the project defines the container image.
|
README.md
CHANGED
|
@@ -7,4 +7,98 @@ sdk: docker
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
+
# Phonetics MCP
|
| 11 |
+
|
| 12 |
+
This is a Gradio application that provides two tools for working with phonetics:
|
| 13 |
+
|
| 14 |
+
1. **Text to Phonetics:** Converts a given text into a dictionary of possible phonetic pronunciations and their probabilities.
|
| 15 |
+
2. **Phonetics to Text:** Converts an International Phonetic Alphabet (IPA) expression into a list of possible dictations.
|
| 16 |
+
|
| 17 |
+
## MCP Tools
|
| 18 |
+
|
| 19 |
+
This application is designed to be used as a Model-centric Programming (MCP) service on Hugging Face Spaces. The following tools are available:
|
| 20 |
+
|
| 21 |
+
### `text_to_phonetics`
|
| 22 |
+
|
| 23 |
+
This tool takes a string of text and a language code and returns a dictionary of possible phonetic pronunciations and their probabilities.
|
| 24 |
+
|
| 25 |
+
**Inputs:**
|
| 26 |
+
|
| 27 |
+
* `text` (string): The text to convert.
|
| 28 |
+
* `language` (string): The 2-letter language code of the text (e.g., 'en' for English).
|
| 29 |
+
|
| 30 |
+
**Output:**
|
| 31 |
+
|
| 32 |
+
* `pronunciations` (dict): A dictionary where keys are phonetic pronunciations and values are their probabilities.
|
| 33 |
+
|
| 34 |
+
**Example:**
|
| 35 |
+
|
| 36 |
+
```json
|
| 37 |
+
{
|
| 38 |
+
"text": "hello",
|
| 39 |
+
"language": "en"
|
| 40 |
+
}
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
```json
|
| 44 |
+
{
|
| 45 |
+
"hello": 0.99,
|
| 46 |
+
"hel": 0.01
|
| 47 |
+
}
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
### `phonetics_to_text`
|
| 51 |
+
|
| 52 |
+
This tool takes an International Phonetic Alphabet (IPA) expression and a language and returns a list of all possible dictations of it in that language.
|
| 53 |
+
|
| 54 |
+
**Inputs:**
|
| 55 |
+
|
| 56 |
+
* `ipa` (string): The IPA expression to convert.
|
| 57 |
+
* `language` (string): The 2-letter language code of the expression (e.g., 'en' for English).
|
| 58 |
+
|
| 59 |
+
**Output:**
|
| 60 |
+
|
| 61 |
+
* `dictations` (list): A list of possible dictations.
|
| 62 |
+
|
| 63 |
+
**Example:**
|
| 64 |
+
|
| 65 |
+
```json
|
| 66 |
+
{
|
| 67 |
+
"ipa": "həˈloʊ",
|
| 68 |
+
"language": "en"
|
| 69 |
+
}
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
```json
|
| 73 |
+
[
|
| 74 |
+
"dictation one",
|
| 75 |
+
"dictation two"
|
| 76 |
+
]
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
## Development
|
| 80 |
+
|
| 81 |
+
This project is set up to be run as a Docker container.
|
| 82 |
+
|
| 83 |
+
**Running the Application:**
|
| 84 |
+
|
| 85 |
+
The `Dockerfile` specifies the command to run the application using `uvicorn`:
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
uvicorn app:app --host 0.0.0.0 --port 7860
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
This command starts the Uvicorn server, which serves the Gradio application defined in `app.py`.
|
| 92 |
+
|
| 93 |
+
**Dependencies:**
|
| 94 |
+
|
| 95 |
+
Project dependencies are managed in the `pyproject.toml` file and installed using `uv`. The main dependencies are:
|
| 96 |
+
|
| 97 |
+
* `gradio`
|
| 98 |
+
* `litellm`
|
| 99 |
+
|
| 100 |
+
To install dependencies, you can use the following command:
|
| 101 |
+
|
| 102 |
+
```bash
|
| 103 |
+
uv sync --dev
|
| 104 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from src.phonetics_mcp.phoneference import LANGUAGES, text_to_phonetics, phonetics_to_text
|
| 3 |
+
|
| 4 |
+
# Create a list of tuples for the dropdown choices
|
| 5 |
+
language_choices = list(LANGUAGES.items())
|
| 6 |
+
|
| 7 |
+
with gr.Blocks() as demo:
|
| 8 |
+
gr.Markdown("# Phonetics MCP")
|
| 9 |
+
|
| 10 |
+
with gr.Tab("Text to Phonetics"):
|
| 11 |
+
with gr.Row():
|
| 12 |
+
text_input = gr.Textbox(label="Text")
|
| 13 |
+
language_input_ttp = gr.Dropdown(choices=language_choices, label="Language")
|
| 14 |
+
|
| 15 |
+
phonetics_output = gr.JSON(label="Phonetic Pronunciations")
|
| 16 |
+
|
| 17 |
+
ttp_button = gr.Button("Convert to Phonetics")
|
| 18 |
+
ttp_button.click(
|
| 19 |
+
fn=text_to_phonetics,
|
| 20 |
+
inputs=[text_input, language_input_ttp],
|
| 21 |
+
outputs=phonetics_output,
|
| 22 |
+
api_name="text_to_phonetics"
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
with gr.Tab("Phonetics to Text"):
|
| 26 |
+
with gr.Row():
|
| 27 |
+
ipa_input = gr.Textbox(label="IPA Expression")
|
| 28 |
+
language_input_ptt = gr.Dropdown(choices=language_choices, label="Language")
|
| 29 |
+
|
| 30 |
+
dictation_output = gr.JSON(label="Possible Dictations")
|
| 31 |
+
|
| 32 |
+
ptt_button = gr.Button("Convert to Text")
|
| 33 |
+
ptt_button.click(
|
| 34 |
+
fn=phonetics_to_text,
|
| 35 |
+
inputs=[ipa_input, language_input_ptt],
|
| 36 |
+
outputs=dictation_output,
|
| 37 |
+
api_name="phonetics_to_text"
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
if __name__ == "__main__":
|
| 41 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, mcp_server=True)
|
pyproject.toml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "phonetics-mcp"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Add your description here"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
authors = [
|
| 7 |
+
{ name = "Soroush", email = "soroush@example.com" }
|
| 8 |
+
]
|
| 9 |
+
requires-python = ">=3.13"
|
| 10 |
+
dependencies = [
|
| 11 |
+
"gradio[mcp]>=6.0.1",
|
| 12 |
+
"litellm>=1.80.7",
|
| 13 |
+
"pydantic>=2.12.4",
|
| 14 |
+
"python-dotenv>=1.2.1",
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
[build-system]
|
| 18 |
+
requires = ["uv_build>=0.9.13,<0.10.0"]
|
| 19 |
+
build-backend = "uv_build"
|
src/phonetics_mcp/__init__.py
ADDED
|
File without changes
|
src/phonetics_mcp/phoneference.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
import litellm
|
| 4 |
+
from typing import Dict, List
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
load_dotenv()
|
| 8 |
+
|
| 9 |
+
litellm.api_key = os.getenv("NEBIUS_API_KEY")
|
| 10 |
+
litellm.base_url = "https://llm.api.cloud.yandex.net/v1"
|
| 11 |
+
|
| 12 |
+
TEXT_TO_PHONETICS_MODEL = os.getenv("TEXT_TO_PHONETICS_MODEL")
|
| 13 |
+
TEXT_TO_PHONETICS_TEMPERATURE = float(os.getenv("TEXT_TO_PHONETICS_TEMPERATURE", 0.8))
|
| 14 |
+
PHONETICS_TO_TEXT_MODEL = os.getenv("PHONETICS_TO_TEXT_MODEL")
|
| 15 |
+
PHONETICS_TO_TEXT_MODEL_TEMPERATURE = float(os.getenv("PHONETICS_TO_TEXT_MODEL_TEMPERATURE", 0.6))
|
| 16 |
+
|
| 17 |
+
LANGUAGES = {
|
| 18 |
+
"English": "en", "Mandarin Chinese": "zh", "Hindi": "hi", "Spanish": "es", "French": "fr",
|
| 19 |
+
"Standard Arabic": "ar", "Bengali": "bn", "Russian": "ru", "Portuguese": "pt", "Urdu": "ur",
|
| 20 |
+
"Indonesian": "id", "German": "de", "Japanese": "ja", "Swahili": "sw", "Marathi": "mr",
|
| 21 |
+
"Telugu": "te", "Turkish": "tr", "Tamil": "ta", "Punjabi": "pa", "Korean": "ko",
|
| 22 |
+
"Vietnamese": "vi", "Italian": "it", "Thai": "th", "Gujarati": "gu", "Persian": "fa",
|
| 23 |
+
"Bhojpuri": "bh", "Polish": "pl", "Odia": "or", "Maithili": "mai", "Ukrainian": "uk",
|
| 24 |
+
"Burmese": "my", "Romanian": "ro", "Dutch": "nl", "Pashto": "ps", "Kannada": "kn",
|
| 25 |
+
"Malayalam": "ml", "Sindhi": "sd", "Cambodian": "km", "Somali": "so", "Nepali": "ne",
|
| 26 |
+
"Assamese": "as", "Sinhalese": "si", "Cebuano": "ceb", "Kurdish": "ku", "Uzbek": "uz",
|
| 27 |
+
"Greek": "el", "Czech": "cs", "Swedish": "sv", "Hungarian": "hu", "Azerbaijani": "az"
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
async def text_to_phonetics(text: str, language_code: str) -> dict:
|
| 32 |
+
"""
|
| 33 |
+
Converts text to a dictionary of possible phonetic pronunciations and their probabilities.
|
| 34 |
+
"""
|
| 35 |
+
if not text:
|
| 36 |
+
return {}
|
| 37 |
+
|
| 38 |
+
try:
|
| 39 |
+
print(f"text_to_phonetics called with text: '{text}', language_code: '{language_code}'")
|
| 40 |
+
system_prompt = """
|
| 41 |
+
You are an expert linguist and phonetician. Your task is to provide a detailed breakdown of possible phonetic pronunciations for a given text in a specified language.
|
| 42 |
+
The output should be a JSON object where the keys are the phonetic representations in the International Phonetic Alphabet (IPA), and the values are the probabilities of that pronunciation being the correct one.
|
| 43 |
+
Consider all possible nuances, dialects, and variations in pronunciation. For example, the word 'advocate' in English can be a noun or a verb, and its pronunciation changes accordingly.
|
| 44 |
+
"""
|
| 45 |
+
user_prompt = f"""
|
| 46 |
+
Please provide the phonetic pronunciations for the text: '{text}'
|
| 47 |
+
Language: {language_code}
|
| 48 |
+
|
| 49 |
+
Return the result as a JSON object with a 'pronunciations' key, which is a dictionary of IPA strings to their probabilities.
|
| 50 |
+
For example for the word "advocate":
|
| 51 |
+
{{
|
| 52 |
+
"pronunciations": {{
|
| 53 |
+
"/ˈæd.və.kət/": 0.7,
|
| 54 |
+
"/ˈæd.və.keɪt/": 0.3
|
| 55 |
+
}}
|
| 56 |
+
}}
|
| 57 |
+
|
| 58 |
+
For a word with a single pronunciation like "her", the output should be:
|
| 59 |
+
{{
|
| 60 |
+
"pronunciations": {{
|
| 61 |
+
"/hɜːr/": 1.0
|
| 62 |
+
}}
|
| 63 |
+
}}
|
| 64 |
+
"""
|
| 65 |
+
print(f"Model: {TEXT_TO_PHONETICS_MODEL}, Temperature: {TEXT_TO_PHONETICS_TEMPERATURE}")
|
| 66 |
+
response = await litellm.acompletion(
|
| 67 |
+
model=TEXT_TO_PHONETICS_MODEL,
|
| 68 |
+
messages=[{
|
| 69 |
+
"role": "system",
|
| 70 |
+
"content": system_prompt
|
| 71 |
+
}, {
|
| 72 |
+
"role": "user",
|
| 73 |
+
"content": user_prompt
|
| 74 |
+
}],
|
| 75 |
+
temperature=TEXT_TO_PHONETICS_TEMPERATURE,
|
| 76 |
+
response_format={"type": "json_object"}
|
| 77 |
+
)
|
| 78 |
+
print("LiteLLM raw response:", response)
|
| 79 |
+
|
| 80 |
+
response_content = response.choices[0].message.content
|
| 81 |
+
print("LiteLLM message content:", response_content)
|
| 82 |
+
|
| 83 |
+
# The response from the LLM should be a JSON string.
|
| 84 |
+
# Let's parse it to get the dictionary.
|
| 85 |
+
data = json.loads(response_content)
|
| 86 |
+
return data.get("pronunciations", {})
|
| 87 |
+
|
| 88 |
+
except Exception as e:
|
| 89 |
+
print(f"An error occurred in text_to_phonetics: {e}")
|
| 90 |
+
return {}
|
| 91 |
+
|
| 92 |
+
async def phonetics_to_text(ipa: str, language_code: str) -> list:
|
| 93 |
+
"""
|
| 94 |
+
Converts an International Phonetic Alphabet (IPA) expression to a list of possible dictations.
|
| 95 |
+
"""
|
| 96 |
+
if not ipa:
|
| 97 |
+
return []
|
| 98 |
+
|
| 99 |
+
try:
|
| 100 |
+
print(f"phonetics_to_text called with ipa: '{ipa}', language_code: '{language_code}'")
|
| 101 |
+
system_prompt = """
|
| 102 |
+
You are an expert linguist and phonetician. Your task is to provide a list of possible words or phrases (dictations) that match a given International Phonetic Alphabet (IPA) expression in a specified language.
|
| 103 |
+
Consider all possible homophones and variations in spelling.
|
| 104 |
+
"""
|
| 105 |
+
user_prompt = f"""
|
| 106 |
+
Please provide the possible dictations for the IPA expression: '{ipa}'
|
| 107 |
+
Language: {language_code}
|
| 108 |
+
|
| 109 |
+
Return the result as a JSON object with a 'dictations' key, which is a list of strings.
|
| 110 |
+
For example for the IPA "/həˈloʊ/":
|
| 111 |
+
{{
|
| 112 |
+
"dictations": [
|
| 113 |
+
"hello",
|
| 114 |
+
"hallo"
|
| 115 |
+
]
|
| 116 |
+
}}
|
| 117 |
+
"""
|
| 118 |
+
print(f"Model: {PHONETICS_TO_TEXT_MODEL}, Temperature: {PHONETICS_TO_TEXT_MODEL_TEMPERATURE}")
|
| 119 |
+
response = await litellm.acompletion(
|
| 120 |
+
model=PHONETICS_TO_TEXT_MODEL,
|
| 121 |
+
messages=[{
|
| 122 |
+
"role": "system",
|
| 123 |
+
"content": system_prompt
|
| 124 |
+
}, {
|
| 125 |
+
"role": "user",
|
| 126 |
+
"content": user_prompt
|
| 127 |
+
}],
|
| 128 |
+
temperature=PHONETICS_TO_TEXT_MODEL_TEMPERATURE,
|
| 129 |
+
response_format={"type": "json_object"}
|
| 130 |
+
)
|
| 131 |
+
print("LiteLLM raw response:", response)
|
| 132 |
+
|
| 133 |
+
response_content = response.choices[0].message.content
|
| 134 |
+
print("LiteLLM message content:", response_content)
|
| 135 |
+
|
| 136 |
+
data = json.loads(response_content)
|
| 137 |
+
return data.get("dictations", [])
|
| 138 |
+
except Exception as e:
|
| 139 |
+
print(f"An error occurred in phonetics_to_text: {e}")
|
| 140 |
+
return []
|
src/phonetics_mcp/py.typed
ADDED
|
File without changes
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|