Skip to main content

yemot-flow 🚀

גרסה 0.2.18 Python 3.11+ רישיון MIT

ספריית Python מודרנית עם async/await ליצירת מערכות IVR חכמות לימות המשיח

🎯 פשוט כמו Node.js yemot-router2 - כותבים קוד ליניארי עם await, והמנוע מטפל בכל השאר!

✨ חדש בגרסה 0.2.18: תמיכה מלאה ב-async/await עם המשכיות אוטומטית + תיעוד מושלם!


🌟 למה yemot-flow?

@flow.get("")
async def welcome(call: Call):
    # כותבים קוד פשוט ורציף!
    name = await call.read([('text', 'מה השם שלך?')], mode="stt", val_name="name")
    age = await call.read([('text', f'שלום {name}, כמה אתה בן?')], val_name="age", max_digits=2)
    
    call.play_message([('text', f'נעים להכיר {name} בן {age}!')])
    call.hangup()

🚀 תכונות מרכזיות

✨ תכונה פירוט
async/await קוד ליניארי וטבעי כמו ב-Node.js - ללא ניהול מצב ידני
המשכיות אוטומטית המנוע זוכר איפה עצרת וממשיך אחרי כל קלט מהמשתמש
תמיכה מלאה Flask, FastAPI, זיהוי דיבור (STT), הקלטות, כל סוגי הקלטים
פשוט להתקין pip install yemot-flow או uv add yemot-flow - מוכן לשימוש!
מהיר עם uv פיתוח מהיר פי 10 עם uv package manager
דוגמאות רבות מערכת הזמנות, תפריטים מתקדמים, בוט AI ועוד

📦 התקנה מהירה

🐍 עם pip (רגיל)

# התקנה בסיסית
pip install yemot-flow

# עם Flask (מומלץ למתחילים)
pip install yemot-flow flask

# עם FastAPI (לביצועים גבוהים)  
pip install yemot-flow fastapi uvicorn

⚡ עם uv (מומלץ - מהיר יותר!)

# התקן uv אם אין לך
curl -LsSf https://astral.sh/uv/install.sh | sh

# התקנה בסיסית
uv add yemot-flow

# עם Flask
uv add yemot-flow flask

# עם FastAPI
uv add yemot-flow fastapi uvicorn

# יצירת פרויקט חדש עם uv
uv init my-ivr-project
cd my-ivr-project
uv add yemot-flow flask

דרישות: Python 3.11+ (נבדק על 3.11, 3.12, 3.13)

🚀 למה uv?

⚡ יתרון פירוט
מהיר פי 10-100 התקנת packages מהירה בצורה דרמטית
ניהול Python מנהל גרסאות Python אוטומטית
Lock files גרסאות קבועות לכל הצוות
Virtual envs ניהול אוטומטי של סביבות וירטואליות
פשוט כל מה שצריך ב-tool אחד

🎬 התחלה מהירה עם uv

# 1. התקן uv (אם אין לך)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. צור פרויקט חדש
uv init my-ivr-system
cd my-ivr-system

# 3. הוסף yemot-flow
uv add yemot-flow flask

# 4. צור קובץ app.py
cat > app.py << 'EOF'
from flask import Flask, request, Response
from yemot_flow import Flow, Call

app = Flask(__name__)
flow = Flow(print_log=True)

@flow.get("")
async def hello(call: Call):
    name = await call.read([('text', 'מה שמך?')], mode="stt", val_name="name")
    call.play_message([('text', f'שלום {name}!')])
    call.hangup()

@app.route("/yemot", methods=["GET", "POST"])
def yemot():
    return Response(flow.handle_request(request.values.to_dict()), 
                   mimetype="text/plain; charset=utf-8")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
EOF

# 5. הרץ!
uv run python app.py

🎉 זהו! המערכת רצה על http://localhost:5000/yemot


⚡ דוגמה מהירה (5 דקות!)

🔥 הדרך החדשה - async/await

from flask import Flask, request, Response
from yemot_flow import Flow, Call

app = Flask(__name__)
flow = Flow(print_log=True)

@flow.get("")
async def welcome(call: Call):
    """שיחה פשוטה עם 3 קלטים"""
    
    # קלט 1
    input1 = await call.read([('text', 'אנא הקש 1')], 
                            val_name="input1", max_digits=1, digits_allowed="1")
    
    # קלט 2 
    input2 = await call.read([('text', 'עכשיו הקש 2')], 
                            val_name="input2", max_digits=1, digits_allowed="2")
    
    # קלט 3
    input3 = await call.read([('text', 'ולסיום הקש 3')], 
                            val_name="input3", max_digits=1, digits_allowed="3")
    
    # סיכום
    call.play_message([('text', f'קלטת: {input1}, {input2}, {input3}. תודה!')])
    call.hangup()

@app.route("/yemot", methods=["GET", "POST"])
def yemot_entry():
    return Response(
        flow.handle_request(request.values.to_dict()),
        mimetype="text/plain; charset=utf-8"
    )

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

🚀 הפעלה

# עם Python רגיל
python app.py

# עם uv (מומלץ)
uv run app.py

# המערכת רצה על: http://localhost:5000/yemot

🔗 הגדרה בימות: כתובת API ← http://your-server-ip:5000/yemot

📱 הדרך הישנה (sync) - עדיין נתמכת

@flow.get("")
def old_style(call):
    call.play_message([("text", "שלום וברכה! הקש 1")])
    call.read([("text", "הקש 1 להמשך")], max_digits=1, digits_allowed="1")
    if call.params.get("Digits") == "1":
        call.goto("thanks")

@flow.get("thanks") 
def thanks(call):
    call.play_message([("text", "תודה ולהתראות")])
    call.hangup()

🎯 דוגמאות מתקדמות

🗣️ זיהוי דיבור (STT)

@flow.get("stt")
async def speech_demo(call: Call):
    name = await call.read([('text', 'אמור את שמך')], 
                          mode="stt", val_name="name", lang="he-IL")
    
    call.play_message([('text', f'שלום {name}, נעים להכיר!')])
    call.hangup()

🎙️ הקלטה

@flow.get("record")
async def recording_demo(call: Call):
    recording = await call.read([('text', 'תתחיל הקלטה אחרי הצפצוף')], 
                               mode="record", val_name="recording", 
                               max_length=30, path="/recordings")
    
    call.play_message([('text', 'תודה על ההקלטה')])
    call.hangup()

🍕 מערכת הזמנות מסעדה

@flow.get("")
async def restaurant(call: Call):
    # בחירת פיצה
    pizza = await call.read([
        ('text', 'ברוכים הבאים לפיצה שמח!'),
        ('text', 'הקש 1 למרגריטה, 2 לפפרוני, 3 לירקות')
    ], val_name="pizza", max_digits=1, digits_allowed="123")
    
    pizza_names = {"1": "מרגריטה", "2": "פפרוני", "3": "ירקות"}
    
    # בחירת גודל
    size = await call.read([
        ('text', f'בחרת פיצה {pizza_names[pizza]}'),
        ('text', 'הקש 1 לקטנה, 2 לבינונית, 3 לגדולה')
    ], val_name="size", max_digits=1, digits_allowed="123")
    
    sizes = {"1": "קטנה", "2": "בינונית", "3": "גדולה"}
    
    # פרטי משלוח
    phone = await call.read([('text', 'אמור מספר טלפון למשלוח')], 
                           mode="stt", val_name="phone", lang="he-IL")
    
    address = await call.read([('text', 'אמור כתובת למשלוח')], 
                             mode="stt", val_name="address", lang="he-IL")
    
    # אישור הזמנה
    call.play_message([
        ('text', f'אישור הזמנה: פיצה {pizza_names[pizza]} {sizes[size]}'),
        ('text', f'טלפון: {phone}'),
        ('text', f'כתובת: {address}'),
        ('text', 'ההזמנה תגיע תוך 30 דקות. תודה!')
    ])
    call.hangup()

📚 API מלא

Flow - המנוע הראשי

flow = Flow(timeout=30000, print_log=True)

# רישום handlers
@flow.get("")          # שלוחה ראשית
@flow.get("sales")     # שלוחת מכירות  
@flow.get("support")   # שלוחת תמיכה

# ניהול בקשות
response = flow.handle_request(params_dict)

Call - אובייקט השיחה

🎵 play_message - השמעת הודעות

call.play_message([
    ("text", "שלום וברכה"),           # טקסט
    ("file", "welcome"),              # קובץ שמע
    ("digits", "12345"),             # ספרות
    ("number", "150"),               # מספר (מאה וחמישים)
    ("alpha", "abc"),                # אותיות
])

🎹 read - קבלת קלטים

# הקשות מקלדת
result = await call.read([('text', 'הקש מספר')], 
                        val_name="user_input",
                        max_digits=3,
                        min_digits=1,
                        digits_allowed="123456789",
                        sec_wait=10)

# זיהוי דיבור
speech = await call.read([('text', 'דבר עכשיו')], 
                        mode="stt",
                        val_name="speech",
                        lang="he-IL")

# הקלטה
recording = await call.read([('text', 'תתחיל הקלטה')], 
                           mode="record",
                           val_name="recording",
                           max_length=60,
                           path="/recordings/")

🔄 ניווט

call.goto("sales")      # מעבר לשלוחה
call.goto("")           # חזרה לראשית  
call.hangup()           # ניתוק השיחה

🌐 FastAPI Support

from fastapi import FastAPI, Request, Response
from yemot_flow import Flow, Call

app = FastAPI()
flow = Flow()

@flow.get("")
async def root(call: Call):
    name = await call.read([('text', 'מה שמך?')], mode="stt", val_name="name")
    call.play_message([('text', f'שלום {name} מ-FastAPI!')])
    call.hangup()

@app.api_route("/yemot", methods=["GET", "POST"])
async def yemot_entry(request: Request):
    if request.method == "POST":
        params = await request.form()
    else:
        params = request.query_params
    
    resp = flow.handle_request(dict(params))
    return Response(resp, media_type="text/plain; charset=utf-8")

# הפעלה עם uvicorn רגיל
# uvicorn main:app --host 0.0.0.0 --port 8000

# הפעלה עם uv (מומלץ)  
# uv run uvicorn main:app --host 0.0.0.0 --port 8000

🧪 דוגמאות נוספות

ראה תיקיית examples/ לדוגמאות מלאות:

  • minimal_example.py - דוגמה פשוטה ביותר
  • flask_basic_example.py - Flask מתקדם עם תפריטים
  • fastapi_basic_example.py - FastAPI עם async handlers
  • restaurant_ordering_system.py - מערכת הזמנות מסעדה מלאה
  • hebrew_no_encoding_example.py - עברית ללא בעיות קידוד

🛠️ פיתוח ותרומה

🐍 עם pip

# Clone + setup
git clone https://github.com/davidTheDeveloperY/yemot-flow
cd yemot-flow
pip install -e .

# הרצת בדיקות
pytest tests/

# בדיקת examples
python examples/minimal_example.py

⚡ עם uv (מומלץ למפתחים)

# Clone + setup
git clone https://github.com/davidTheDeveloperY/yemot-flow
cd yemot-flow
uv sync

# הרצת בדיקות
uv run pytest tests/

# בדיקת examples
uv run python examples/minimal_example.py

# פיתוח עם hot reload
uv run python examples/flask_basic_example.py

# בנייה ופרסום
uv build
uv publish

🐛 פתרון בעיות נפוצות

❌ שגיאת חיבור

  • וודא שהשרת רץ על IP חיצוני (host="0.0.0.0")
  • בדוק firewall/router settings
  • השתמש בטרמינל: curl "http://your-server:5000/yemot?ApiCallId=test"

❌ עברית לא עובדת

  • הוסף charset=utf-8 ל-Response
  • השתמש ב-url_encode=True ב-play_message אם יש בעיות

❌ השיחה נתקעת

  • בדוק שיש val_name ייחודי לכל read()
  • ודא ש-digits_allowed מכיל את הספרות הנכונות
  • הוסף print_log=True ל-Flow לראות מה קורה

📋 Changelog

v0.2.18 (נוכחי)

  • 📚 README מושלם ומפורט
  • 🎯 דוגמאות async/await מלאות
  • 🔧 תיקוני תיעוד וסדר

v0.2.17

  • ✨ תמיכה מלאה ב-async/await
  • 🔧 המשכיות אוטומטית של handlers
  • 🚀 ביצועים משופרים
  • 📚 דוגמאות מעודכנות

v0.2.16

  • 🐛 תיקוני באגים ביציבות
  • 📝 שיפורי תיעוד

🤝 תמיכה ועזרה

  • GitHub Issues: yemot-flow/issues
  • דוגמאות: ראה תיקיית examples/
  • פורום ימות: חפש "yemot-flow"

📄 רישיון

MIT License - חופשי לשימוש מסחרי ואישי


💝 נהנת מהספרייה? תן לנו ⭐ ב-GitHub!
Made with ❤️ by davidTheDeveloper

Metadata

Release files for yemot-flow 0.2.20

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yemot-flow 0.2.20
File Size Uploaded Provenance Actions
yemot_flow-0.2.20.tar.gz 30.1 kB Without provenance Details for yemot_flow-0.2.20.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for yemot-flow 0.2.20
File Interpreter ABI Platform Actions
yemot_flow-0.2.20-py3-none-any.whl Python 3 none any Details for yemot_flow-0.2.20-py3-none-any.whl

Total release size: 45.4 kB

Release files / yemot_flow-0.2.20.tar.gz

Download URL yemot_flow-0.2.20.tar.gz
Size 30.1 kB
Tags Source
SHA-256 checksum
How to use checksums
b466faea493a922483e77d09ede403e07a1b74999014b97576164706f5acfa11
BLAKE2b-256 checksum
How to use checksums
6f495e7b5ca23f683ff1e9a127a6f739c184a1320615ee5ad3802be970d33cc0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Release files / yemot_flow-0.2.20-py3-none-any.whl

Download URL yemot_flow-0.2.20-py3-none-any.whl
Size 15.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eb4675de0b6496f3c64075ec2107d2216594c51004d2999f75a01c3dd1832b61
BLAKE2b-256 checksum
How to use checksums
23e0ebb7d91b0fa96b495f6b781ee0ded2f543b393ba874f26df700692cb8eb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.13

Security for yemot-flow 0.2.20

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page