Spaces:
Sleeping
Sleeping
Commit ·
3345ea7
0
Parent(s):
Add initial project setup with email proposal generation functionality
Browse files- .env.example +6 -0
- .gitattributes +35 -0
- .gitignore +140 -0
- Dockerfile +25 -0
- README.md +13 -0
- custom-gpt-action.yaml +109 -0
- instructions.json +16 -0
- instructions.md +74 -0
- poetry.lock +358 -0
- pyproject.toml +19 -0
- src/__init__.py +29 -0
- src/app.py +71 -0
- src/proposal_template.md +167 -0
- src/utils/__init__.py +5 -0
- src/utils/_email_client.py +50 -0
.env.example
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
SMTP_SERVER=
|
| 2 |
+
SMTP_PORT=
|
| 3 |
+
SMTP_USERNAME=
|
| 4 |
+
SMTP_PASSWORD=
|
| 5 |
+
SENDER_EMAIL=
|
| 6 |
+
RECIPIENT_EMAIL=
|
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 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 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
| 98 |
+
__pypackages__/
|
| 99 |
+
|
| 100 |
+
# Celery stuff
|
| 101 |
+
celerybeat-schedule
|
| 102 |
+
celerybeat.pid
|
| 103 |
+
|
| 104 |
+
# SageMath parsed files
|
| 105 |
+
*.sage.py
|
| 106 |
+
|
| 107 |
+
# Environments
|
| 108 |
+
.env
|
| 109 |
+
.venv
|
| 110 |
+
env/
|
| 111 |
+
venv/
|
| 112 |
+
ENV/
|
| 113 |
+
env.bak/
|
| 114 |
+
venv.bak/
|
| 115 |
+
|
| 116 |
+
# Spyder project settings
|
| 117 |
+
.spyderproject
|
| 118 |
+
.spyproject
|
| 119 |
+
|
| 120 |
+
# Rope project settings
|
| 121 |
+
.ropeproject
|
| 122 |
+
|
| 123 |
+
# mkdocs documentation
|
| 124 |
+
/site
|
| 125 |
+
|
| 126 |
+
# mypy
|
| 127 |
+
.mypy_cache/
|
| 128 |
+
.dmypy.json
|
| 129 |
+
dmypy.json
|
| 130 |
+
|
| 131 |
+
# Pyre type checker
|
| 132 |
+
.pyre/
|
| 133 |
+
|
| 134 |
+
# pytype static type analyzer
|
| 135 |
+
.pytype/
|
| 136 |
+
|
| 137 |
+
# Cython debug symbols
|
| 138 |
+
cython_debug/
|
| 139 |
+
|
| 140 |
+
.vscode
|
Dockerfile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.12
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
RUN pip install poetry
|
| 6 |
+
|
| 7 |
+
RUN poetry config virtualenvs.create false
|
| 8 |
+
|
| 9 |
+
COPY pyproject.toml poetry.lock /app/
|
| 10 |
+
|
| 11 |
+
RUN poetry install --only main --no-root
|
| 12 |
+
|
| 13 |
+
RUN useradd -m -u 1000 user
|
| 14 |
+
|
| 15 |
+
RUN chown -R user /app
|
| 16 |
+
|
| 17 |
+
USER user
|
| 18 |
+
|
| 19 |
+
COPY --chown=user src /app/src
|
| 20 |
+
|
| 21 |
+
EXPOSE 7860
|
| 22 |
+
|
| 23 |
+
ENV PYTHONUNBUFFERED=1
|
| 24 |
+
|
| 25 |
+
CMD ["uvicorn", "src.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Proposal Generator
|
| 3 |
+
emoji: 🌍
|
| 4 |
+
colorFrom: yellow
|
| 5 |
+
colorTo: gray
|
| 6 |
+
sdk: docker
|
| 7 |
+
# sdk: streamlit
|
| 8 |
+
sdk_version: 1.41.1
|
| 9 |
+
app_file: app.py
|
| 10 |
+
pinned: false
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
custom-gpt-action.yaml
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
openapi: 3.1.0
|
| 2 |
+
info:
|
| 3 |
+
title: Proposal Generation API
|
| 4 |
+
description: This API generates project proposals based on user input.
|
| 5 |
+
version: 1.0.0
|
| 6 |
+
servers:
|
| 7 |
+
- url: https://sifars-proposal-generator.hf.space
|
| 8 |
+
description: Main server for proposal generation.
|
| 9 |
+
paths:
|
| 10 |
+
/proposals/:
|
| 11 |
+
post:
|
| 12 |
+
operationId: generateProposal
|
| 13 |
+
summary: Generates a project proposal
|
| 14 |
+
requestBody:
|
| 15 |
+
required: true
|
| 16 |
+
content:
|
| 17 |
+
application/json:
|
| 18 |
+
schema:
|
| 19 |
+
$ref: "#/components/schemas/ProposalRequest"
|
| 20 |
+
responses:
|
| 21 |
+
"200":
|
| 22 |
+
description: Successfully generated proposal
|
| 23 |
+
content:
|
| 24 |
+
application/json:
|
| 25 |
+
schema:
|
| 26 |
+
type: object
|
| 27 |
+
properties:
|
| 28 |
+
proposal:
|
| 29 |
+
type: string
|
| 30 |
+
example: "Generated proposal content here."
|
| 31 |
+
"500":
|
| 32 |
+
description: Internal server error
|
| 33 |
+
content:
|
| 34 |
+
application/json:
|
| 35 |
+
schema:
|
| 36 |
+
type: object
|
| 37 |
+
properties:
|
| 38 |
+
detail:
|
| 39 |
+
type: string
|
| 40 |
+
example: "Internal Server Error."
|
| 41 |
+
components:
|
| 42 |
+
schemas:
|
| 43 |
+
ProposalRequest:
|
| 44 |
+
type: object
|
| 45 |
+
required:
|
| 46 |
+
- project_name
|
| 47 |
+
- project_overview
|
| 48 |
+
- project_introduction
|
| 49 |
+
- about_us
|
| 50 |
+
- background_of_the_project
|
| 51 |
+
- scope_of_work
|
| 52 |
+
- technical_approach
|
| 53 |
+
- deployment_and_integration
|
| 54 |
+
- timeline
|
| 55 |
+
- team_structure
|
| 56 |
+
- platform
|
| 57 |
+
- licensing_model
|
| 58 |
+
- risk_analysis
|
| 59 |
+
- past_projects
|
| 60 |
+
properties:
|
| 61 |
+
project_name:
|
| 62 |
+
type: string
|
| 63 |
+
description: "Generate a name of the project. In response, provide only the name and do not include any other information."
|
| 64 |
+
project_overview:
|
| 65 |
+
type: string
|
| 66 |
+
description: "Generate an overview section that improves the project overview from the client requirements. Keep the text up to 15 lines and write the text without using pronouns."
|
| 67 |
+
project_introduction:
|
| 68 |
+
type: string
|
| 69 |
+
description: "Address the client formally and thank them for considering Sifars for the project. Briefly describe Sifars, mentioning its mission, values, and focus on delivering state-of-the-art AI or software solutions."
|
| 70 |
+
about_us:
|
| 71 |
+
type: string
|
| 72 |
+
description: "Provide a short introduction to Sifars, focusing on our team's expertise, technologies, and successful solutions we have developed. Mention how long Sifars has been in operation and our experience with similar projects."
|
| 73 |
+
background_of_the_project:
|
| 74 |
+
type: string
|
| 75 |
+
description: "Describe the key challenge the client is facing in their industry (replace with the client's field, e.g., healthcare, finance). Present the problem and how Sifars will address it using advanced technologies (AI, software development, automation, etc.)."
|
| 76 |
+
scope_of_work:
|
| 77 |
+
type: string
|
| 78 |
+
description: "Detail the tasks that will be performed. Example structure: Data Collection and Preprocessing, Solution Development (e.g., AI model, software system), Integration and API development, Testing and validation, Deployment on scalable infrastructure."
|
| 79 |
+
technical_approach:
|
| 80 |
+
type: string
|
| 81 |
+
description: "Explain the approach in detail. Include methodologies like content-based and collaborative filtering if relevant, or other techniques used by Sifars. Customize this to reflect the [Techstack] that's going to be used by Sifars."
|
| 82 |
+
deployment_and_integration:
|
| 83 |
+
type: string
|
| 84 |
+
description: "Specify the deployment method, such as using cloud services like AWS, GCP, or any other infrastructure that Sifars uses or defined in the [Techstack]. Mention how Sifars ensures seamless integration with the client’s platform using APIs."
|
| 85 |
+
timeline:
|
| 86 |
+
timeline:
|
| 87 |
+
type: string
|
| 88 |
+
description: "Create a timeline with project milestones in the following table format, like:
|
| 89 |
+
| Week | Milestone | Estimated Pricing |
|
| 90 |
+
|------|------------------------------------|-------------------------|
|
| 91 |
+
| 1 | Initial Setup and Data Collection | $1,000 |
|
| 92 |
+
| 2-3 | Development of Core Components | $2,000 |
|
| 93 |
+
| 4 | Final Deployment and Testing | $1,500 |
|
| 94 |
+
Add estimated pricing in a flexible structure, allowing payments at each milestone."
|
| 95 |
+
team_structure:
|
| 96 |
+
type: string
|
| 97 |
+
description: "Generate a detailed breakdown of a project team's structure, including roles and responsibilities. The team may consist of members like Project Manager, UI/UX Designer, Full Stack Developers, AI Developers, Quality Assurance Specialists, DevOps Engineers, etc. For each role, provide the number of members and describe their key responsibilities. Ensure that the responsibilities align with typical tasks for each role in a software development project. Use clear, professional language and ensure that the descriptions are concise yet comprehensive."
|
| 98 |
+
platform:
|
| 99 |
+
type: string
|
| 100 |
+
description: "Generate text explaining each [Techstack] the application will be built upon."
|
| 101 |
+
licensing_model:
|
| 102 |
+
type: string
|
| 103 |
+
description: "Based on the [Techstack] and other potential tooling that will be involved to build the project, generate the Licensing Model section."
|
| 104 |
+
risk_analysis:
|
| 105 |
+
type: string
|
| 106 |
+
description: "List potential risks (e.g., data availability, bias in the system) and propose mitigations."
|
| 107 |
+
past_projects:
|
| 108 |
+
type: string
|
| 109 |
+
description: "Provide case studies of similar projects Sifars has worked on, showcasing the impact and results achieved. Refer to the knowledge files to find 2 relevant projects that could be similar to the provided requirements."
|
instructions.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"project_name": "Generate a name of the project. In response provide only name and do not include any other information.",
|
| 3 |
+
"project_overview": "Generate an overview section that just improves the project overview from the client requirements. Keep the text up to 15 lines and Please write the text without using pronouns.",
|
| 4 |
+
"project_introduction": "Address the client formally and thank them for considering Sifars for the project. Briefly describe Sifars, mentioning its mission, values, and focus on delivering state-of-the-art AI or software solutions.",
|
| 5 |
+
"about_us": "Provide a short introduction to Sifars, focusing on our team's expertise, technologies, and the successful solutions we have developed. Mention how long Sifars has been in operation and our experience with similar projects.",
|
| 6 |
+
"background_of_the_project": "Describe the key challenge the client is facing in their industry (replace with the client's field, e.g., healthcare, finance). Present the problem and how Sifars will address it using advanced technologies (AI, software development, automation, etc.).",
|
| 7 |
+
"scope_of_work": "Detail the tasks that will be performed. Example structure: Data Collection and Preprocessing. Solution Development (e.g., AI model, software system). Integration and API development. Testing and validation. Deployment on scalable infrastructure.",
|
| 8 |
+
"technical_approach": "Explain the approach in detail. Include methodologies like content-based and collaborative filtering if relevant, or other techniques used by Sifars. Customize this to reflect the [ Techstack ] that's going to be used by Sifars.",
|
| 9 |
+
"deployment_and_integration": "Specify the deployment method, such as using cloud services like AWS, GCP, or any other infrastructure that Sifars uses or defined in the [ Techstack ]. Mention how Sifars ensures seamless integration with the client’s platform using APIs.",
|
| 10 |
+
"timeline": "Create a timeline with project milestones in the following table format, like: Week 1: Initial Setup and Data Collection. Week 2-3: Development of Core Components. Week 4: Final Deployment and Testing. Add estimated pricing in a flexible structure, allowing payments at each milestone.",
|
| 11 |
+
"team_structure": "Generate a detailed breakdown of a project team's structure, including roles and responsibilities. The team may consists of members like Project Manager, UI/UX Designer, Full Stack Developers, AI Developers, Quality Assurance Specialists, DevOps Engineers, etc. For each role, provide the number of members and describe their key responsibilities. Ensure that the responsibilities align with typical tasks for each role in a software development project. Use clear, professional language and ensure that the descriptions are concise yet comprehensive.",
|
| 12 |
+
"platform": "Generate text explaining each [ techstack ] the application will be built upon.",
|
| 13 |
+
"licensing_model": "Based on the [ Techstack ] and other potential tooling that will be involved to build the project, generate the Licensing Model section. ",
|
| 14 |
+
"risk_analysis": "List potential risks (e.g., data availability, bias in the system) and propose mitigations.",
|
| 15 |
+
"past_projects": "Provide case studies of similar projects Sifars has worked on, showcasing the impact and results achieved. Refer to the knowledge files to find 2 relevant projects that could be similar to the provided requirements."
|
| 16 |
+
}
|
instructions.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
You are an AI-powered proposal generator for Sifars, responsible for crafting professional, structured, and tailored project proposals. Follow these instructions carefully to generate a compelling and precise document:
|
| 2 |
+
|
| 3 |
+
### **1. Project Name**
|
| 4 |
+
|
| 5 |
+
Generate a concise, relevant project name. Provide only the name, without additional details or explanations.
|
| 6 |
+
|
| 7 |
+
### **2. Project Overview**
|
| 8 |
+
|
| 9 |
+
Refine the client's project overview while maintaining their core requirements. Improve clarity and readability within a limit of 15 lines. Avoid using pronouns.
|
| 10 |
+
|
| 11 |
+
### **3. Project Introduction**
|
| 12 |
+
|
| 13 |
+
Address the client formally and thank them for considering Sifars. Briefly introduce Sifars, highlighting its mission, values, and expertise in AI and software solutions.
|
| 14 |
+
|
| 15 |
+
### **4. About Us**
|
| 16 |
+
|
| 17 |
+
Summarize Sifars' background, including team expertise, technology focus, and past successes. Mention years of experience and relevant industry accomplishments.
|
| 18 |
+
|
| 19 |
+
### **5. Background of the Project**
|
| 20 |
+
|
| 21 |
+
Describe the client’s key industry challenge and how Sifars’ advanced technologies (AI, automation, software development, etc.) will address it. Clearly outline the problem and Sifars' tailored solution.
|
| 22 |
+
|
| 23 |
+
### **6. Scope of Work**
|
| 24 |
+
|
| 25 |
+
Define project tasks in a structured format, including but not limited to:
|
| 26 |
+
|
| 27 |
+
- Data Collection & Preprocessing
|
| 28 |
+
- Solution Development (AI model/software)
|
| 29 |
+
- Integration & API Development
|
| 30 |
+
- Testing & Validation
|
| 31 |
+
- Deployment on scalable infrastructure
|
| 32 |
+
|
| 33 |
+
### **7. Technical Approach**
|
| 34 |
+
|
| 35 |
+
Describe the technical methodologies and strategies that will be used. Align the approach with the specified [Techstack] and include techniques such as AI/ML models, collaborative filtering, or other relevant methods.
|
| 36 |
+
|
| 37 |
+
### **8. Deployment and Integration**
|
| 38 |
+
|
| 39 |
+
Detail the deployment strategy, specifying cloud infrastructure (AWS, GCP, etc.) and integration methods. Ensure that API integration is seamless and aligns with Sifars' best practices.
|
| 40 |
+
|
| 41 |
+
### **9. Timeline & Pricing**
|
| 42 |
+
|
| 43 |
+
Generate a project timeline with milestone-based breakdowns. Provide a flexible pricing structure linked to milestone completions in markdown table format. Ensure the timeline and pricing are realistic and competitive.
|
| 44 |
+
|
| 45 |
+
### **10. Team Structure**
|
| 46 |
+
|
| 47 |
+
Define project roles and responsibilities, ensuring alignment with typical software development tasks. The team may include:
|
| 48 |
+
|
| 49 |
+
- Project Manager
|
| 50 |
+
- UI/UX Designer
|
| 51 |
+
- Full Stack Developers
|
| 52 |
+
- AI Developers
|
| 53 |
+
- Quality Assurance Specialists
|
| 54 |
+
- DevOps Engineers
|
| 55 |
+
|
| 56 |
+
For each role, specify the number of members and their core responsibilities. Use clear, professional language.
|
| 57 |
+
|
| 58 |
+
### **11. Platform**
|
| 59 |
+
|
| 60 |
+
Describe the [Techstack] used for the project, explaining its relevance and benefits.
|
| 61 |
+
|
| 62 |
+
### **12. Licensing Model**
|
| 63 |
+
|
| 64 |
+
Generate the appropriate licensing model based on the [Techstack] and other tools required.
|
| 65 |
+
|
| 66 |
+
### **13. Risk Analysis**
|
| 67 |
+
|
| 68 |
+
Identify key project risks (e.g., data availability, security concerns, AI biases) and propose mitigation strategies.
|
| 69 |
+
|
| 70 |
+
### **14. Past Projects**
|
| 71 |
+
|
| 72 |
+
Select two relevant case studies from Sifars’ past projects that align with the client’s requirements. Highlight their impact and results.
|
| 73 |
+
|
| 74 |
+
Ensure the proposal maintains a professional, clear, and structured format. Keep responses concise, factual, and aligned with Sifars' expertise.
|
poetry.lock
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
| 2 |
+
|
| 3 |
+
[[package]]
|
| 4 |
+
name = "aiosmtplib"
|
| 5 |
+
version = "3.0.2"
|
| 6 |
+
description = "asyncio SMTP client"
|
| 7 |
+
optional = false
|
| 8 |
+
python-versions = ">=3.8"
|
| 9 |
+
files = [
|
| 10 |
+
{file = "aiosmtplib-3.0.2-py3-none-any.whl", hash = "sha256:8783059603a34834c7c90ca51103c3aa129d5922003b5ce98dbaa6d4440f10fc"},
|
| 11 |
+
{file = "aiosmtplib-3.0.2.tar.gz", hash = "sha256:08fd840f9dbc23258025dca229e8a8f04d2ccf3ecb1319585615bfc7933f7f47"},
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
[package.extras]
|
| 15 |
+
docs = ["furo (>=2023.9.10)", "sphinx (>=7.0.0)", "sphinx-autodoc-typehints (>=1.24.0)", "sphinx-copybutton (>=0.5.0)"]
|
| 16 |
+
uvloop = ["uvloop (>=0.18)"]
|
| 17 |
+
|
| 18 |
+
[[package]]
|
| 19 |
+
name = "annotated-types"
|
| 20 |
+
version = "0.7.0"
|
| 21 |
+
description = "Reusable constraint types to use with typing.Annotated"
|
| 22 |
+
optional = false
|
| 23 |
+
python-versions = ">=3.8"
|
| 24 |
+
files = [
|
| 25 |
+
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
| 26 |
+
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
| 27 |
+
]
|
| 28 |
+
|
| 29 |
+
[[package]]
|
| 30 |
+
name = "anyio"
|
| 31 |
+
version = "4.8.0"
|
| 32 |
+
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
| 33 |
+
optional = false
|
| 34 |
+
python-versions = ">=3.9"
|
| 35 |
+
files = [
|
| 36 |
+
{file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"},
|
| 37 |
+
{file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"},
|
| 38 |
+
]
|
| 39 |
+
|
| 40 |
+
[package.dependencies]
|
| 41 |
+
idna = ">=2.8"
|
| 42 |
+
sniffio = ">=1.1"
|
| 43 |
+
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
|
| 44 |
+
|
| 45 |
+
[package.extras]
|
| 46 |
+
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
|
| 47 |
+
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
|
| 48 |
+
trio = ["trio (>=0.26.1)"]
|
| 49 |
+
|
| 50 |
+
[[package]]
|
| 51 |
+
name = "click"
|
| 52 |
+
version = "8.1.8"
|
| 53 |
+
description = "Composable command line interface toolkit"
|
| 54 |
+
optional = false
|
| 55 |
+
python-versions = ">=3.7"
|
| 56 |
+
files = [
|
| 57 |
+
{file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
|
| 58 |
+
{file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
|
| 59 |
+
]
|
| 60 |
+
|
| 61 |
+
[package.dependencies]
|
| 62 |
+
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
| 63 |
+
|
| 64 |
+
[[package]]
|
| 65 |
+
name = "colorama"
|
| 66 |
+
version = "0.4.6"
|
| 67 |
+
description = "Cross-platform colored terminal text."
|
| 68 |
+
optional = false
|
| 69 |
+
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
| 70 |
+
files = [
|
| 71 |
+
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
| 72 |
+
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
| 73 |
+
]
|
| 74 |
+
|
| 75 |
+
[[package]]
|
| 76 |
+
name = "fastapi"
|
| 77 |
+
version = "0.115.7"
|
| 78 |
+
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
| 79 |
+
optional = false
|
| 80 |
+
python-versions = ">=3.8"
|
| 81 |
+
files = [
|
| 82 |
+
{file = "fastapi-0.115.7-py3-none-any.whl", hash = "sha256:eb6a8c8bf7f26009e8147111ff15b5177a0e19bb4a45bc3486ab14804539d21e"},
|
| 83 |
+
{file = "fastapi-0.115.7.tar.gz", hash = "sha256:0f106da6c01d88a6786b3248fb4d7a940d071f6f488488898ad5d354b25ed015"},
|
| 84 |
+
]
|
| 85 |
+
|
| 86 |
+
[package.dependencies]
|
| 87 |
+
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
| 88 |
+
starlette = ">=0.40.0,<0.46.0"
|
| 89 |
+
typing-extensions = ">=4.8.0"
|
| 90 |
+
|
| 91 |
+
[package.extras]
|
| 92 |
+
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
|
| 93 |
+
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
|
| 94 |
+
|
| 95 |
+
[[package]]
|
| 96 |
+
name = "h11"
|
| 97 |
+
version = "0.14.0"
|
| 98 |
+
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
| 99 |
+
optional = false
|
| 100 |
+
python-versions = ">=3.7"
|
| 101 |
+
files = [
|
| 102 |
+
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
| 103 |
+
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
| 104 |
+
]
|
| 105 |
+
|
| 106 |
+
[[package]]
|
| 107 |
+
name = "idna"
|
| 108 |
+
version = "3.10"
|
| 109 |
+
description = "Internationalized Domain Names in Applications (IDNA)"
|
| 110 |
+
optional = false
|
| 111 |
+
python-versions = ">=3.6"
|
| 112 |
+
files = [
|
| 113 |
+
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
|
| 114 |
+
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
|
| 115 |
+
]
|
| 116 |
+
|
| 117 |
+
[package.extras]
|
| 118 |
+
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
|
| 119 |
+
|
| 120 |
+
[[package]]
|
| 121 |
+
name = "loguru"
|
| 122 |
+
version = "0.7.3"
|
| 123 |
+
description = "Python logging made (stupidly) simple"
|
| 124 |
+
optional = false
|
| 125 |
+
python-versions = "<4.0,>=3.5"
|
| 126 |
+
files = [
|
| 127 |
+
{file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"},
|
| 128 |
+
{file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"},
|
| 129 |
+
]
|
| 130 |
+
|
| 131 |
+
[package.dependencies]
|
| 132 |
+
colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
|
| 133 |
+
win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
|
| 134 |
+
|
| 135 |
+
[package.extras]
|
| 136 |
+
dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"]
|
| 137 |
+
|
| 138 |
+
[[package]]
|
| 139 |
+
name = "pydantic"
|
| 140 |
+
version = "2.10.6"
|
| 141 |
+
description = "Data validation using Python type hints"
|
| 142 |
+
optional = false
|
| 143 |
+
python-versions = ">=3.8"
|
| 144 |
+
files = [
|
| 145 |
+
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
|
| 146 |
+
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
|
| 147 |
+
]
|
| 148 |
+
|
| 149 |
+
[package.dependencies]
|
| 150 |
+
annotated-types = ">=0.6.0"
|
| 151 |
+
pydantic-core = "2.27.2"
|
| 152 |
+
typing-extensions = ">=4.12.2"
|
| 153 |
+
|
| 154 |
+
[package.extras]
|
| 155 |
+
email = ["email-validator (>=2.0.0)"]
|
| 156 |
+
timezone = ["tzdata"]
|
| 157 |
+
|
| 158 |
+
[[package]]
|
| 159 |
+
name = "pydantic-core"
|
| 160 |
+
version = "2.27.2"
|
| 161 |
+
description = "Core functionality for Pydantic validation and serialization"
|
| 162 |
+
optional = false
|
| 163 |
+
python-versions = ">=3.8"
|
| 164 |
+
files = [
|
| 165 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"},
|
| 166 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"},
|
| 167 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"},
|
| 168 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"},
|
| 169 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"},
|
| 170 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"},
|
| 171 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"},
|
| 172 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"},
|
| 173 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"},
|
| 174 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"},
|
| 175 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"},
|
| 176 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"},
|
| 177 |
+
{file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"},
|
| 178 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"},
|
| 179 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"},
|
| 180 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"},
|
| 181 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"},
|
| 182 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"},
|
| 183 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"},
|
| 184 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"},
|
| 185 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"},
|
| 186 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"},
|
| 187 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"},
|
| 188 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"},
|
| 189 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"},
|
| 190 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"},
|
| 191 |
+
{file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"},
|
| 192 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"},
|
| 193 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"},
|
| 194 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"},
|
| 195 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"},
|
| 196 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"},
|
| 197 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"},
|
| 198 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"},
|
| 199 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"},
|
| 200 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"},
|
| 201 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"},
|
| 202 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"},
|
| 203 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"},
|
| 204 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"},
|
| 205 |
+
{file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"},
|
| 206 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"},
|
| 207 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"},
|
| 208 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"},
|
| 209 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"},
|
| 210 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"},
|
| 211 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"},
|
| 212 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"},
|
| 213 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"},
|
| 214 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"},
|
| 215 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"},
|
| 216 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"},
|
| 217 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"},
|
| 218 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"},
|
| 219 |
+
{file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"},
|
| 220 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"},
|
| 221 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"},
|
| 222 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"},
|
| 223 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"},
|
| 224 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"},
|
| 225 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"},
|
| 226 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"},
|
| 227 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"},
|
| 228 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"},
|
| 229 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"},
|
| 230 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"},
|
| 231 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"},
|
| 232 |
+
{file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"},
|
| 233 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"},
|
| 234 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"},
|
| 235 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"},
|
| 236 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"},
|
| 237 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"},
|
| 238 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"},
|
| 239 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"},
|
| 240 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"},
|
| 241 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"},
|
| 242 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"},
|
| 243 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"},
|
| 244 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"},
|
| 245 |
+
{file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"},
|
| 246 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"},
|
| 247 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"},
|
| 248 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"},
|
| 249 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"},
|
| 250 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"},
|
| 251 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"},
|
| 252 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"},
|
| 253 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"},
|
| 254 |
+
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"},
|
| 255 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"},
|
| 256 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"},
|
| 257 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"},
|
| 258 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"},
|
| 259 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"},
|
| 260 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"},
|
| 261 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"},
|
| 262 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"},
|
| 263 |
+
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"},
|
| 264 |
+
{file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"},
|
| 265 |
+
]
|
| 266 |
+
|
| 267 |
+
[package.dependencies]
|
| 268 |
+
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
| 269 |
+
|
| 270 |
+
[[package]]
|
| 271 |
+
name = "python-dotenv"
|
| 272 |
+
version = "1.0.1"
|
| 273 |
+
description = "Read key-value pairs from a .env file and set them as environment variables"
|
| 274 |
+
optional = false
|
| 275 |
+
python-versions = ">=3.8"
|
| 276 |
+
files = [
|
| 277 |
+
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
| 278 |
+
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
| 279 |
+
]
|
| 280 |
+
|
| 281 |
+
[package.extras]
|
| 282 |
+
cli = ["click (>=5.0)"]
|
| 283 |
+
|
| 284 |
+
[[package]]
|
| 285 |
+
name = "sniffio"
|
| 286 |
+
version = "1.3.1"
|
| 287 |
+
description = "Sniff out which async library your code is running under"
|
| 288 |
+
optional = false
|
| 289 |
+
python-versions = ">=3.7"
|
| 290 |
+
files = [
|
| 291 |
+
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
| 292 |
+
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
| 293 |
+
]
|
| 294 |
+
|
| 295 |
+
[[package]]
|
| 296 |
+
name = "starlette"
|
| 297 |
+
version = "0.45.3"
|
| 298 |
+
description = "The little ASGI library that shines."
|
| 299 |
+
optional = false
|
| 300 |
+
python-versions = ">=3.9"
|
| 301 |
+
files = [
|
| 302 |
+
{file = "starlette-0.45.3-py3-none-any.whl", hash = "sha256:dfb6d332576f136ec740296c7e8bb8c8a7125044e7c6da30744718880cdd059d"},
|
| 303 |
+
{file = "starlette-0.45.3.tar.gz", hash = "sha256:2cbcba2a75806f8a41c722141486f37c28e30a0921c5f6fe4346cb0dcee1302f"},
|
| 304 |
+
]
|
| 305 |
+
|
| 306 |
+
[package.dependencies]
|
| 307 |
+
anyio = ">=3.6.2,<5"
|
| 308 |
+
|
| 309 |
+
[package.extras]
|
| 310 |
+
full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
|
| 311 |
+
|
| 312 |
+
[[package]]
|
| 313 |
+
name = "typing-extensions"
|
| 314 |
+
version = "4.12.2"
|
| 315 |
+
description = "Backported and Experimental Type Hints for Python 3.8+"
|
| 316 |
+
optional = false
|
| 317 |
+
python-versions = ">=3.8"
|
| 318 |
+
files = [
|
| 319 |
+
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
| 320 |
+
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
| 321 |
+
]
|
| 322 |
+
|
| 323 |
+
[[package]]
|
| 324 |
+
name = "uvicorn"
|
| 325 |
+
version = "0.34.0"
|
| 326 |
+
description = "The lightning-fast ASGI server."
|
| 327 |
+
optional = false
|
| 328 |
+
python-versions = ">=3.9"
|
| 329 |
+
files = [
|
| 330 |
+
{file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"},
|
| 331 |
+
{file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"},
|
| 332 |
+
]
|
| 333 |
+
|
| 334 |
+
[package.dependencies]
|
| 335 |
+
click = ">=7.0"
|
| 336 |
+
h11 = ">=0.8"
|
| 337 |
+
|
| 338 |
+
[package.extras]
|
| 339 |
+
standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
|
| 340 |
+
|
| 341 |
+
[[package]]
|
| 342 |
+
name = "win32-setctime"
|
| 343 |
+
version = "1.2.0"
|
| 344 |
+
description = "A small Python utility to set file creation time on Windows"
|
| 345 |
+
optional = false
|
| 346 |
+
python-versions = ">=3.5"
|
| 347 |
+
files = [
|
| 348 |
+
{file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"},
|
| 349 |
+
{file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"},
|
| 350 |
+
]
|
| 351 |
+
|
| 352 |
+
[package.extras]
|
| 353 |
+
dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
|
| 354 |
+
|
| 355 |
+
[metadata]
|
| 356 |
+
lock-version = "2.0"
|
| 357 |
+
python-versions = "3.12.*"
|
| 358 |
+
content-hash = "347e22360bbf6bffd7da2466e4c3ef4ec5d60bbc03a8257b64ce72165f7653e7"
|
pyproject.toml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[tool.poetry]
|
| 2 |
+
name = "proposal-generator"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = ""
|
| 5 |
+
authors = ["Kanha Upadhyay <kanha.upadhyay@sifars.com>"]
|
| 6 |
+
readme = "README.md"
|
| 7 |
+
|
| 8 |
+
[tool.poetry.dependencies]
|
| 9 |
+
python = "3.12.*"
|
| 10 |
+
fastapi = "^0.115.7"
|
| 11 |
+
uvicorn = "^0.34.0"
|
| 12 |
+
loguru = "^0.7.3"
|
| 13 |
+
python-dotenv = "^1.0.1"
|
| 14 |
+
aiosmtplib = "^3.0.2"
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
[build-system]
|
| 18 |
+
requires = ["poetry-core"]
|
| 19 |
+
build-backend = "poetry.core.masonry.api"
|
src/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
|
| 5 |
+
from .app import app
|
| 6 |
+
|
| 7 |
+
load_dotenv()
|
| 8 |
+
|
| 9 |
+
if not os.getenv("SMTP_SERVER"):
|
| 10 |
+
raise ValueError("SMTP_SERVER environment not set.")
|
| 11 |
+
|
| 12 |
+
if not os.getenv("SMTP_PORT"):
|
| 13 |
+
raise ValueError("SMTP_PORT environment not set.")
|
| 14 |
+
|
| 15 |
+
if not os.getenv("SMTP_USERNAME"):
|
| 16 |
+
raise ValueError("SMTP_USERNAME environment not set.")
|
| 17 |
+
|
| 18 |
+
if not os.getenv("SMTP_PASSWORD"):
|
| 19 |
+
raise ValueError("SMTP_PASSWORD environment not set.")
|
| 20 |
+
|
| 21 |
+
if not os.getenv("SENDER_EMAIL"):
|
| 22 |
+
raise ValueError("SENDER_EMAIL environment not set.")
|
| 23 |
+
|
| 24 |
+
if not os.getenv("RECIPIENT_EMAIL"):
|
| 25 |
+
raise ValueError("RECIPIENT_EMAIL environment not set.")
|
| 26 |
+
|
| 27 |
+
__all__ = ["app"]
|
| 28 |
+
__version__ = "0.1.0"
|
| 29 |
+
__author__ = "Kanha Upadhyay"
|
src/app.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import re
|
| 3 |
+
import tempfile
|
| 4 |
+
|
| 5 |
+
from fastapi import FastAPI, HTTPException
|
| 6 |
+
from pydantic import BaseModel
|
| 7 |
+
|
| 8 |
+
from src.utils import EmailClient
|
| 9 |
+
|
| 10 |
+
app = FastAPI()
|
| 11 |
+
|
| 12 |
+
TEMPLATE = ""
|
| 13 |
+
with open("src/proposal_template.md", "r") as file:
|
| 14 |
+
TEMPLATE = file.read()
|
| 15 |
+
|
| 16 |
+
TEMPLATE = TEMPLATE.replace("`", "")
|
| 17 |
+
VARIABLES = re.findall(r"\{(.*?)\}", TEMPLATE)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class ProposalRequest(BaseModel):
|
| 21 |
+
project_name: str
|
| 22 |
+
project_overview: str
|
| 23 |
+
project_introduction: str
|
| 24 |
+
about_us: str
|
| 25 |
+
background_of_the_project: str
|
| 26 |
+
scope_of_work: str
|
| 27 |
+
technical_approach: str
|
| 28 |
+
deployment_and_integration: str
|
| 29 |
+
timeline: str
|
| 30 |
+
team_structure: str
|
| 31 |
+
platform: str
|
| 32 |
+
licensing_model: str
|
| 33 |
+
risk_analysis: str
|
| 34 |
+
past_projects: str
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
async def generate_proposal(data: dict):
|
| 38 |
+
proposal = TEMPLATE
|
| 39 |
+
for variable in VARIABLES:
|
| 40 |
+
proposal = proposal.replace(
|
| 41 |
+
f"{{{variable}}}",
|
| 42 |
+
data.get(variable, f"DATA NOT FOUND FOR {variable}. FIXME."),
|
| 43 |
+
)
|
| 44 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".md") as temp_file:
|
| 45 |
+
temp_file.write(proposal.encode())
|
| 46 |
+
attachments = [temp_file.name]
|
| 47 |
+
recipient_email = os.getenv("RECIPIENT_EMAIL")
|
| 48 |
+
subject = f"Proposal for {data.get('project_name')}"
|
| 49 |
+
body = f"Hello,\n\nPlease find the proposal attached.\n\nBest,\nProposal Bot"
|
| 50 |
+
async with EmailClient() as email_client:
|
| 51 |
+
await email_client.send_email(
|
| 52 |
+
subject=subject,
|
| 53 |
+
body=body,
|
| 54 |
+
to_emails=[recipient_email],
|
| 55 |
+
attachments=attachments,
|
| 56 |
+
)
|
| 57 |
+
return {"message": "Proposal sent successfully"}
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
@app.get("/")
|
| 61 |
+
async def check_health():
|
| 62 |
+
return {"response": "Service is healthy!"}
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
@app.post("/proposals/")
|
| 66 |
+
async def generate_proposal_endpoint(request: ProposalRequest):
|
| 67 |
+
try:
|
| 68 |
+
proposal = await generate_proposal(data=request.model_dump())
|
| 69 |
+
return {"proposal": proposal}
|
| 70 |
+
except Exception as e:
|
| 71 |
+
raise HTTPException(status_code=500, detail=f"{e}")
|
src/proposal_template.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# `{project_name}` Proposal
|
| 2 |
+
|
| 3 |
+
## Table of Contents
|
| 4 |
+
|
| 5 |
+
| Section |
|
| 6 |
+
| ---------------------------------------------------------------- |
|
| 7 |
+
| [Introduction](#1-introduction) |
|
| 8 |
+
| [Project Timeline and Pricing](#2-project-timeline--pricing) |
|
| 9 |
+
| [Platform](#3-platform) |
|
| 10 |
+
| [Licensing Model](#4-licensing-model) |
|
| 11 |
+
| [Risk Analysis](#5-risk-analysis) |
|
| 12 |
+
| [Past Projects](#6-past-projects) |
|
| 13 |
+
| [Service Level Matrix](#7-service-level-matrix) |
|
| 14 |
+
| [Future Requirements](#8-future-requirements) |
|
| 15 |
+
| [Ownership](#9-ownership) |
|
| 16 |
+
| [Additional Information](#10-additional-information) |
|
| 17 |
+
| [Dependencies and Assumptions](#11-dependencies-and-assumptions) |
|
| 18 |
+
| [Change Management](#12-change-management) |
|
| 19 |
+
| [Terms and Conditions](#13-terms--conditions) |
|
| 20 |
+
| [Estimation Disclaimer](#14-estimation-disclaimer) |
|
| 21 |
+
|
| 22 |
+
# 1. Introduction
|
| 23 |
+
|
| 24 |
+
### Company Overview
|
| 25 |
+
|
| 26 |
+
Sifars is pleased to present a comprehensive proposal for the development and implementation of the `{project_name}`. As a leading provider of innovative software solutions, Sifars brings a wealth of experience and expertise to this project. With a proven track record of delivering tailored solutions that address our clients' unique needs, we are confident in our ability to successfully execute this project and exceed expectations.
|
| 27 |
+
|
| 28 |
+
### Project Overview
|
| 29 |
+
|
| 30 |
+
`{project_overview}`
|
| 31 |
+
|
| 32 |
+
### Inroduction
|
| 33 |
+
|
| 34 |
+
`{project_introduction}`
|
| 35 |
+
|
| 36 |
+
### About Us
|
| 37 |
+
|
| 38 |
+
`{about_us}`
|
| 39 |
+
|
| 40 |
+
### Background of the Project
|
| 41 |
+
|
| 42 |
+
`{background_of_the_project}`
|
| 43 |
+
|
| 44 |
+
### Scope of Work
|
| 45 |
+
|
| 46 |
+
`{scope_of_work}`
|
| 47 |
+
|
| 48 |
+
### Technical Approach
|
| 49 |
+
|
| 50 |
+
`{technical_approach}`
|
| 51 |
+
|
| 52 |
+
### Deployment and Integration
|
| 53 |
+
|
| 54 |
+
`{deployment_and_integration}`
|
| 55 |
+
|
| 56 |
+
# 2. Project Timeline & Pricing
|
| 57 |
+
|
| 58 |
+
The successful implementation of the `{project_name}` will follow a structured timeline, ensuring timely delivery of milestones and alignment with project objectives. Below is the proposed timeline outlining key milestones and their respective durations.
|
| 59 |
+
|
| 60 |
+
Efforts (Man Days): The number of days it will take for a single person to deliver the milestone, with a working day consisting of 8 hours.
|
| 61 |
+
|
| 62 |
+
Time (Days): The duration required for our team to deliver the milestone, considering a working day of 8 hours and involving multiple team members.
|
| 63 |
+
|
| 64 |
+
### Timeline
|
| 65 |
+
|
| 66 |
+
`{timeline}`
|
| 67 |
+
|
| 68 |
+
| S.No. | Milestone | Efforts (ManDays) | Time (Days) | Price |
|
| 69 |
+
| ----- | ---------------------------- | ----------------- | ----------- | ----- |
|
| 70 |
+
| 1 | High-Level Design Document | | | |
|
| 71 |
+
| 2 | Low-Level Design Document | | | |
|
| 72 |
+
| 3 | Proof of Concept | | | |
|
| 73 |
+
| 4 | Minimum Viable Product (MVP) | | | |
|
| 74 |
+
| 5 | Release of Application | | | |
|
| 75 |
+
| | **Total** | | | |
|
| 76 |
+
|
| 77 |
+
### Team Structure
|
| 78 |
+
|
| 79 |
+
`{team_structure}`
|
| 80 |
+
|
| 81 |
+
# 3. Platform
|
| 82 |
+
|
| 83 |
+
`{platform}`
|
| 84 |
+
|
| 85 |
+
# 4. Licensing Model
|
| 86 |
+
|
| 87 |
+
`{licensing_model}`
|
| 88 |
+
|
| 89 |
+
As the project progresses and potential additional tools or services are incorporated, there may be further licensing considerations based on specific needs and agreements with respective vendors. Therefore, the Licensing Model for the project will evolve accordingly to accommodate any future requirements and ensure compliance with all relevant licenses and regulations.
|
| 90 |
+
|
| 91 |
+
# 5. Risk Analysis
|
| 92 |
+
|
| 93 |
+
`{risk_analysis}`
|
| 94 |
+
|
| 95 |
+
# 6. Past Projects
|
| 96 |
+
|
| 97 |
+
`{past_projects}`
|
| 98 |
+
|
| 99 |
+
# 7. Service Level Matrix
|
| 100 |
+
|
| 101 |
+
Respond to service-related incidents submitted by customers within the following time frames. Please note that these only cover any bugs or service-related incidents. In case, there is a major change/upgrade required such as training the AI models on new data, or improving performance, we would need to set up a separate contract for it.
|
| 102 |
+
|
| 103 |
+
We provide one-month complimentary support once the project concludes.
|
| 104 |
+
|
| 105 |
+
| Severity Level | Description of risk level | Maximu m respons e time | Maximum solution to the problem |
|
| 106 |
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- | ------------------------------- |
|
| 107 |
+
| Level One (S1) | 1. Severe problems that cause the system to stop functioning, preventing users from interacting with the system. 2. There is a problem that causes an error in the validity or accuracy of the data processed by the system. | 1 hour | 2 hour |
|
| 108 |
+
| Level Two (S2) | 1. There is a highly important problem that affects the workflow in the system, but does not stop or prevent the completion of interactions and does not affect the validity or accuracy of the data. | 4 hours | 1 day |
|
| 109 |
+
| Level Three (S3) | 1. There is a problem of moderate importance that does not affect the functioning of the system. 2. It stops or prevents the completion of the interaction but does not affect the validity or accuracy of the data and has no financial impact. | 2 days | 5 days |
|
| 110 |
+
| Level Four (S4) | 1. The presence of a minor problem related to cosmetic matters helps improve a user’s interaction with the system. 2. Or need to improve the overall accuracy of the system | 5 days | 10 days |
|
| 111 |
+
|
| 112 |
+
# 8. Future Requirements
|
| 113 |
+
|
| 114 |
+
We understand the importance of futureproofing your investment in the `{project_name}`, and we're committed to ensuring that the solution remains adaptable and scalable to meet your evolving needs. As part of our development approach, we'll build the system with modularity and flexibility in mind, allowing for seamless integration of new features and enhancements as your requirements change over time.
|
| 115 |
+
|
| 116 |
+
1. Scalability: As your organization grows or your `{project_name}` needs expand, the system should be able to accommodate increased user loads and data volumes without sacrificing performance. We'll design the architecture with scalability in mind, utilizing cloud technologies or scalable infrastructure where applicable.
|
| 117 |
+
2. Customization: Your workflows and processes may evolve over time, necessitating customizations or additional features within the system. We'll ensure that the architecture supports easy customization and extension, allowing for the incorporation of new modules or functionality as needed.
|
| 118 |
+
3. Integration: As your IT ecosystem evolves, you may require integration with other systems or platforms to streamline operations and improve data flow. We'll design the system with integration capabilities, making it easier to connect with third-party applications such as CRM systems, accounting software, or external databases.
|
| 119 |
+
|
| 120 |
+
Throughout our partnership, we'll maintain open lines of communication to discuss your evolving needs and explore opportunities for further development. Our goal is to build a long-term partnership focused on delivering solutions that drive your organization's success.
|
| 121 |
+
|
| 122 |
+
# 9. Ownership
|
| 123 |
+
|
| 124 |
+
Ensuring clear ownership of the source code is a crucial aspect of our partnership. We believe in transparency and empowering our clients with full control over their intellectual property. Upon completion of the project and full payment of fees, you will retain full ownership of the source code developed for the `{project_name}`. This means you will have the right to modify, enhance, and distribute the code as you see fit without any restrictions from our end. In addition to providing you with the source code, we will also document the architecture, design decisions, and any relevant technical documentation to facilitate future maintenance and development efforts. Our goal is to ensure that you have the necessary resources and knowledge to independently manage and evolve the system over time. Furthermore, we're committed to fostering a collaborative relationship where you have the freedom to engage with other vendors or developers for ongoing support or further enhancements if desired. We believe in building long-term partnerships based on trust, mutual respect, and a shared commitment to your success.
|
| 125 |
+
|
| 126 |
+
# 10. Additional Information
|
| 127 |
+
|
| 128 |
+
In addition to the technical aspects mentioned above, there are several other factors worth considering ensuring the success and smooth execution of the `{project_name}` development
|
| 129 |
+
|
| 130 |
+
- **Data Migration and Integration:** If you're migrating from an existing system or integrating with other platforms, careful planning and execution are required to ensure seamless data migration and integration. We'll work closely with your team to assess data requirements, identify any potential challenges, and develop a strategy to mitigate risks. This process may necessitate substantial effort and expenditure beyond the proposed budget.
|
| 131 |
+
- **Regulatory Compliance:** Depending on your industry and geographic location, there may be specific regulatory requirements that the `{project_name}` needs to comply with. It's important to factor in compliance considerations from the outset to avoid costly delays or setbacks later. It's crucial that you inform us about any regulatory requirements upfront.
|
| 132 |
+
|
| 133 |
+
# 11. Dependencies and Assumptions
|
| 134 |
+
|
| 135 |
+
- **Third-Party API Integration:** To enhance functionality, we may require third-party integrations. We'll request access to necessary accounts for these integrations from the client during the development process to ensure seamless implementation and operation.
|
| 136 |
+
- **Environment Access:** Access to development, testing, and production environments is assumed throughout the project. The client will provide necessary infrastructure resources such as servers and domains for setting up these environments.
|
| 137 |
+
|
| 138 |
+
# 12. Change Management
|
| 139 |
+
|
| 140 |
+
- **What is a change request** - A change request is a proposal to alter a product or system, often brought up by the client or another team member. During a project, this can happen when a client wants to change or alter the agreed upon deliverables.
|
| 141 |
+
- **Change requests** - can also be initiated internally as well and can include things like changing or upgrading software. In general, there are two types of change requests: those that are within the scope and those that are outside the scope of the project.
|
| 142 |
+
- **Within the scope** – change requests that are inside the scope involve small corrections to an existing requirement. They usually have minimal impact on the budget or the rest of the team.
|
| 143 |
+
- **Outside the scope** – on the other hand, change requests that are outside the scope take a considerable amount of time to implement and have a more sizable impact on the budget. Change requests must be dealt with in an appropriate and timely manner.
|
| 144 |
+
|
| 145 |
+
# 13. Terms & Conditions
|
| 146 |
+
|
| 147 |
+
- The scope will be contained to the line items mentioned in milestones. While creating the proposal, it has been assumed that the requirements given by the client form the complete scope of the application. Any requirement, not explicitly mentioned in this document, does not form a part of this estimate.
|
| 148 |
+
- Client shall provide all third-party software and hardware components. This includes hosting details, hardware environment etc. The cost of all these components will be borne by the client and does not form the part of the proposed estimated cost.
|
| 149 |
+
- If required, the client shall provide all the test data to run the test cases. The client shall be available to solve the queries, which the development team may have, to ensure that project timelines are met.
|
| 150 |
+
- Client shall perform timely review of the deliveries, as per the schedule of deliveries defined at the project initiation. Any delays from the client end would lead to subsequent delays in development of the project, which will be communicated at that time itself.
|
| 151 |
+
- All quotations and estimates provided by Sifars are valid for a period of 30 days from the date of issue. Quotations not accepted within this timeframe need to be re-issued.
|
| 152 |
+
- Upon acceptance, Sifars will perform the services described in the quotation. Any additional services that are later requested by the client and/or not defined under the scope-of-work in this quotation may incur additional charges.
|
| 153 |
+
- The services will be completed, and/or delivery of products will be made according to the estimated timeline, agreed upon mutually by both parties. Sifars reserves the right to modify timelines in response to unforeseen circumstances or changes in project requirements.
|
| 154 |
+
- Changes to the delivery and performance of any products or services, including quantity, specifications, and scheduling, do not become binding until approved in writing by both parties. Any changes may result in additional or increased charges.
|
| 155 |
+
- All information related to the project will be considered confidential, and may only be released if necessary after mutual approval by the client and Sifars.
|
| 156 |
+
- Once the project formally starts, the client or Sifars may terminate the agreement at any time by providing written notice via email or certified mail to the other party. In the event of termination, Sifars may issue a final invoice according to terms of the contract for any unbilled time or work.
|
| 157 |
+
- An advance payment of 10% of the proposed project cost is to be made before the first milestone. This will be adjusted towards the last milestone/deliverable.
|
| 158 |
+
- Each milestone’s payment will be made after the completion.
|
| 159 |
+
- Payment terms will be NET15.
|
| 160 |
+
|
| 161 |
+
# 14. Estimation Disclaimer
|
| 162 |
+
|
| 163 |
+
This proposal provides a time and cost estimate based on a range of days required to complete the project. These estimates are derived from initial discussions and assumptions about the project scope. While we strive for accuracy, it's important to note that software development inherently involves many variables and unforeseen complexities. As such, this estimate cannot be 100% precise. However, we have a high degree of confidence that the final cost will remain within the provided estimate.
|
| 164 |
+
|
| 165 |
+
Once the low-level design document of the project is ready, we will revisit the pricing, allowing us to refine our estimates and provide a more accurate projection. This detailed document will be exceptionally valuable, as it surfaces all the essential questions and details about the project, ensuring that every aspect is thoroughly understood and planned for.
|
| 166 |
+
|
| 167 |
+
Engaging in this comprehensive estimation process not only helps us deliver a realistic understanding of the project's timeline and budget but also provides you with valuable insights into the project's development phases. This empowers you to make informed decisions, ensuring the best use of your resources and investments.
|
src/utils/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ._email_client import EmailClient
|
| 2 |
+
|
| 3 |
+
__all__ = ["EmailClient"]
|
| 4 |
+
__version__ = "0.1.0"
|
| 5 |
+
__author__ = "Kanha Upadhyay"
|
src/utils/_email_client.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from email.message import EmailMessage
|
| 3 |
+
|
| 4 |
+
import aiosmtplib
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class EmailClient:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
self.smtp_server = os.getenv("SMTP_SERVER")
|
| 10 |
+
self.smtp_port = int(os.getenv("SMTP_PORT"))
|
| 11 |
+
self.username = os.getenv("SMTP_USERNAME")
|
| 12 |
+
self.password = os.getenv("SMTP_PASSWORD")
|
| 13 |
+
|
| 14 |
+
async def __aenter__(self):
|
| 15 |
+
return self
|
| 16 |
+
|
| 17 |
+
async def __aexit__(self, exc_type, exc, tb):
|
| 18 |
+
pass
|
| 19 |
+
|
| 20 |
+
async def send_email(
|
| 21 |
+
self,
|
| 22 |
+
subject: str,
|
| 23 |
+
body: str,
|
| 24 |
+
to_emails: list,
|
| 25 |
+
attachments: list = None,
|
| 26 |
+
):
|
| 27 |
+
message = EmailMessage()
|
| 28 |
+
message["From"] = os.getenv("SENDER_EMAIL")
|
| 29 |
+
message["To"] = ", ".join(to_emails)
|
| 30 |
+
message["Subject"] = subject
|
| 31 |
+
message.set_content(body)
|
| 32 |
+
if attachments:
|
| 33 |
+
for attachment in attachments:
|
| 34 |
+
with open(attachment, "rb") as file:
|
| 35 |
+
file_data = file.read()
|
| 36 |
+
file_name = file.name
|
| 37 |
+
message.add_attachment(
|
| 38 |
+
file_data,
|
| 39 |
+
maintype="application",
|
| 40 |
+
subtype="octet-stream",
|
| 41 |
+
filename=file_name,
|
| 42 |
+
)
|
| 43 |
+
await aiosmtplib.send(
|
| 44 |
+
message,
|
| 45 |
+
hostname=self.smtp_server,
|
| 46 |
+
port=self.smtp_port,
|
| 47 |
+
username=self.username,
|
| 48 |
+
password=self.password,
|
| 49 |
+
start_tls=True,
|
| 50 |
+
)
|