Leo commited on
Commit
d78bd21
·
2 Parent(s): cd6adb1 c0d54f1

Merge branch 'main' into hf-main

Browse files

Clean branch without corruption from failed rebase

Files changed (9) hide show
  1. .dockerignore +20 -0
  2. .env.sample +1 -0
  3. .gitignore +161 -0
  4. Dockerfile +45 -0
  5. README.md +19 -8
  6. app.py +24 -18
  7. pyproject.toml +14 -0
  8. testload.py +12 -0
  9. uv.lock +0 -0
.dockerignore ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Prevent secrets and junk from being baked into Docker images
2
+
3
+ # Secrets
4
+ .env
5
+ .env.*
6
+
7
+ # macOS junk
8
+ .DS_Store
9
+
10
+ # Python cache
11
+ __pycache__/
12
+ *.py[cod]
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+
18
+ # Git stuff (optional)
19
+ .git
20
+ .gitignore
.env.sample ADDED
@@ -0,0 +1 @@
 
 
1
+ OPENAI_API_KEY=###
.gitignore ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ .chainlit/
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # poetry
99
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
103
+ #poetry.lock
104
+
105
+ # pdm
106
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
107
+ #pdm.lock
108
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
109
+ # in version control.
110
+ # https://pdm.fming.dev/#use-with-ide
111
+ .pdm.toml
112
+
113
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
114
+ __pypackages__/
115
+
116
+ # Celery stuff
117
+ celerybeat-schedule
118
+ celerybeat.pid
119
+
120
+ # SageMath parsed files
121
+ *.sage.py
122
+
123
+ # Environments
124
+ .env
125
+ .venv
126
+ env/
127
+ venv/
128
+ ENV/
129
+ env.bak/
130
+ venv.bak/
131
+
132
+ # Spyder project settings
133
+ .spyderproject
134
+ .spyproject
135
+
136
+ # Rope project settings
137
+ .ropeproject
138
+
139
+ # mkdocs documentation
140
+ /site
141
+
142
+ # mypy
143
+ .mypy_cache/
144
+ .dmypy.json
145
+ dmypy.json
146
+
147
+ # Pyre type checker
148
+ .pyre/
149
+
150
+ # pytype static type analyzer
151
+ .pytype/
152
+
153
+ # Cython debug symbols
154
+ cython_debug/
155
+
156
+ # PyCharm
157
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
158
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
159
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
160
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
161
+ #.idea/
Dockerfile CHANGED
@@ -1,3 +1,4 @@
 
1
  FROM python:3.9
2
  RUN useradd -m -u 1000 user
3
  USER user
@@ -11,3 +12,47 @@ COPY . .
11
  #Force install specific chainlit version
12
  RUN pip install chainlit==2.3.0
13
  CMD ["chainlit", "run", "app.py", "--port", "7860"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
  FROM python:3.9
3
  RUN useradd -m -u 1000 user
4
  USER user
 
12
  #Force install specific chainlit version
13
  RUN pip install chainlit==2.3.0
14
  CMD ["chainlit", "run", "app.py", "--port", "7860"]
15
+ =======
16
+ # Get a distribution that has uv already installed
17
+ FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
18
+
19
+ # Add Rust compiler installation
20
+ USER root
21
+ RUN apt-get update && apt-get install -y \
22
+ curl \
23
+ build-essential \
24
+ && rm -rf /var/lib/apt/lists/*
25
+ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
26
+ ENV PATH="/root/.cargo/bin:${PATH}"
27
+
28
+ # Add user - this is the user that will run the app
29
+ # If you do not set user, the app will run as root (undesirable)
30
+ RUN useradd -m -u 1000 user
31
+ USER user
32
+
33
+ # Set up Rust for the user
34
+ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
35
+ ENV PATH="/home/user/.cargo/bin:${PATH}"
36
+
37
+ # Set the home directory and path
38
+ ENV HOME=/home/user \
39
+ PATH=/home/user/.local/bin:$PATH
40
+
41
+ ENV UVICORN_WS_PROTOCOL=websockets
42
+
43
+ # Set the working directory
44
+ WORKDIR $HOME/app
45
+
46
+ # Copy the app to the container
47
+ COPY --chown=user . $HOME/app
48
+
49
+ # Install the dependencies
50
+ # RUN uv sync --frozen
51
+ RUN uv sync
52
+
53
+ # Expose the port
54
+ EXPOSE 7860
55
+
56
+ # Run the app
57
+ CMD ["uv", "run", "chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "7860"]
58
+ >>>>>>> main
README.md CHANGED
@@ -5,6 +5,7 @@ colorFrom: pink
5
  colorTo: yellow
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  <p align = "center" draggable=”false” ><img src="https://github.com/AI-Maker-Space/LLM-Dev-101/assets/37101144/d1343317-fa2f-41e1-8af1-1dbb18399719"
@@ -53,9 +54,19 @@ That's it! Head to the next step and start building your application!
53
  cd Beyond-ChatGPT
54
  ```
55
 
56
- 3. Install the packages required for this python envirnoment in `requirements.txt`.
57
  ``` bash
58
- pip install -r requirements.txt
 
 
 
 
 
 
 
 
 
 
59
  ```
60
 
61
  4. Open your `.env` file. Replace the `###` in your `.env` file with your OpenAI Key and save the file.
@@ -63,18 +74,18 @@ That's it! Head to the next step and start building your application!
63
  OPENAI_API_KEY=sk-###
64
  ```
65
 
66
- 5. Let's try deploying it locally. Make sure you're in the python environment where you installed Chainlit and OpenAI. Run the app using Chainlit. This may take a minute to run.
67
  ``` bash
68
- chainlit run app.py -w
69
  ```
70
 
71
- <p align = "center" draggable=”false”>
72
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/54bcccf9-12e2-4cef-ab53-585c1e2b0fb5">
73
  </p>
74
 
75
  Great work! Let's see if we can interact with our chatbot.
76
 
77
- <p align = "center" draggable=”false”>
78
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/854e4435-1dee-438a-9146-7174b39f7c61">
79
  </p>
80
 
@@ -86,7 +97,7 @@ Awesome! Time to throw it into a docker container and prepare it for shipping!
86
  <details>
87
  <summary>🐳 Containerizing our App</summary>
88
 
89
- 1. Let's build the Docker image. We'll tag our image as `llm-app` using the `-t` parameter. The `.` at the end means we want all of the files in our current directory to be added to our image.
90
 
91
  ``` bash
92
  docker build -t llm-app .
@@ -100,7 +111,7 @@ Awesome! Time to throw it into a docker container and prepare it for shipping!
100
 
101
  3. Visit http://localhost:7860 in your browser to see if the app runs correctly.
102
 
103
- <p align = "center" draggable=”false”>
104
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/2c764f25-09a0-431b-8d28-32246e0ca1b7">
105
  </p>
106
 
 
5
  colorTo: yellow
6
  sdk: docker
7
  pinned: false
8
+ app_port: 7860
9
  ---
10
 
11
  <p align = "center" draggable=”false” ><img src="https://github.com/AI-Maker-Space/LLM-Dev-101/assets/37101144/d1343317-fa2f-41e1-8af1-1dbb18399719"
 
54
  cd Beyond-ChatGPT
55
  ```
56
 
57
+ 3. Create a virtual environment and install dependencies.
58
  ``` bash
59
+ # Create a virtual environment
60
+ uv venv
61
+
62
+ # Activate the virtual environment
63
+ # On macOS/Linux:
64
+ source .venv/bin/activate
65
+ # On Windows:
66
+ # .venv\Scripts\activate
67
+
68
+ # Install dependencies from pyproject.toml
69
+ uv sync
70
  ```
71
 
72
  4. Open your `.env` file. Replace the `###` in your `.env` file with your OpenAI Key and save the file.
 
74
  OPENAI_API_KEY=sk-###
75
  ```
76
 
77
+ 5. Let's try deploying it locally. Make sure you're in the activated virtual environment. Run the app using Chainlit. This may take a minute to run.
78
  ``` bash
79
+ uv run chainlit run app.py -w
80
  ```
81
 
82
+ <p align = "center" draggable="false">
83
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/54bcccf9-12e2-4cef-ab53-585c1e2b0fb5">
84
  </p>
85
 
86
  Great work! Let's see if we can interact with our chatbot.
87
 
88
+ <p align = "center" draggable="false">
89
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/854e4435-1dee-438a-9146-7174b39f7c61">
90
  </p>
91
 
 
97
  <details>
98
  <summary>🐳 Containerizing our App</summary>
99
 
100
+ 1. Let's build the Docker image. We'll tag our image as `llm-app` using the `-t` parameter. The `.` at the end means we want all of the files in our current directory to be added to our image. Note that our Dockerfile is set up to use uv for dependency management and will install all the packages defined in our pyproject.toml file.
101
 
102
  ``` bash
103
  docker build -t llm-app .
 
111
 
112
  3. Visit http://localhost:7860 in your browser to see if the app runs correctly.
113
 
114
+ <p align = "center" draggable="false">
115
  <img src="https://github.com/AI-Maker-Space/LLMOps-Dev-101/assets/37101144/2c764f25-09a0-431b-8d28-32246e0ca1b7">
116
  </p>
117
 
app.py CHANGED
@@ -1,15 +1,14 @@
1
  # You can find this code for Chainlit python streaming here (https://docs.chainlit.io/concepts/streaming/python)
2
 
3
  # OpenAI Chat completion
 
 
 
 
 
 
4
 
5
- import openai #importing openai for API usage
6
- import chainlit as cl #importing chainlit for our app
7
- from chainlit.input_widget import Select, Switch, Slider #importing chainlit settings selection tools
8
- from chainlit.prompt import Prompt, PromptMessage #importing prompt tools
9
- from chainlit.playground.providers import ChatOpenAI #importing ChatOpenAI tools
10
-
11
- # You only need the api key inserted here if it's not in your .env file
12
- #openai.api_key = "YOUR_API_KEY"
13
 
14
  # ChatOpenAI Templates
15
  system_template = """You are a helpful assistant who always speaks in a pleasant tone!
@@ -19,7 +18,8 @@ user_template = """{input}
19
  Think through your response step by step.
20
  """
21
 
22
- @cl.on_chat_start # marks a function that will be executed at the start of a user session
 
23
  async def start_chat():
24
  settings = {
25
  "model": "gpt-3.5-turbo",
@@ -32,11 +32,15 @@ async def start_chat():
32
 
33
  cl.user_session.set("settings", settings)
34
 
35
- @cl.on_message # marks a function that should be run each time the chatbot receives a message from a user
36
- async def main(message):
37
 
 
 
38
  settings = cl.user_session.get("settings")
39
 
 
 
 
 
40
  prompt = Prompt(
41
  provider=ChatOpenAI.id,
42
  messages=[
@@ -47,12 +51,12 @@ async def main(message):
47
  ),
48
  PromptMessage(
49
  role="user",
50
- template=user_template,
51
- formatted=user_template.format(input=message),
52
- )
53
  ],
54
- inputs = {"input" : message.content},
55
- settings=settings
56
  )
57
 
58
  print([m.to_openai() for m in prompt.messages])
@@ -60,10 +64,12 @@ async def main(message):
60
  msg = cl.Message(content="")
61
 
62
  # Call OpenAI
63
- async for stream_resp in await openai.ChatCompletion.acreate(
64
  messages=[m.to_openai() for m in prompt.messages], stream=True, **settings
65
  ):
66
- token = stream_resp.choices[0]["delta"].get("content", "")
 
 
67
  await msg.stream_token(token)
68
 
69
  # Update the prompt object with the completion
 
1
  # You can find this code for Chainlit python streaming here (https://docs.chainlit.io/concepts/streaming/python)
2
 
3
  # OpenAI Chat completion
4
+ import os
5
+ from openai import AsyncOpenAI # importing openai for API usage
6
+ import chainlit as cl # importing chainlit for our app
7
+ from chainlit.prompt import Prompt, PromptMessage # importing prompt tools
8
+ from chainlit.playground.providers import ChatOpenAI # importing ChatOpenAI tools
9
+ from dotenv import load_dotenv
10
 
11
+ load_dotenv()
 
 
 
 
 
 
 
12
 
13
  # ChatOpenAI Templates
14
  system_template = """You are a helpful assistant who always speaks in a pleasant tone!
 
18
  Think through your response step by step.
19
  """
20
 
21
+
22
+ @cl.on_chat_start # marks a function that will be executed at the start of a user session
23
  async def start_chat():
24
  settings = {
25
  "model": "gpt-3.5-turbo",
 
32
 
33
  cl.user_session.set("settings", settings)
34
 
 
 
35
 
36
+ @cl.on_message # marks a function that should be run each time the chatbot receives a message from a user
37
+ async def main(message: cl.Message):
38
  settings = cl.user_session.get("settings")
39
 
40
+ client = AsyncOpenAI()
41
+
42
+ print(message.content)
43
+
44
  prompt = Prompt(
45
  provider=ChatOpenAI.id,
46
  messages=[
 
51
  ),
52
  PromptMessage(
53
  role="user",
54
+ template=user_template,
55
+ formatted=user_template.format(input=message.content),
56
+ ),
57
  ],
58
+ inputs={"input": message.content},
59
+ settings=settings,
60
  )
61
 
62
  print([m.to_openai() for m in prompt.messages])
 
64
  msg = cl.Message(content="")
65
 
66
  # Call OpenAI
67
+ async for stream_resp in await client.chat.completions.create(
68
  messages=[m.to_openai() for m in prompt.messages], stream=True, **settings
69
  ):
70
+ token = stream_resp.choices[0].delta.content
71
+ if not token:
72
+ token = ""
73
  await msg.stream_token(token)
74
 
75
  # Update the prompt object with the completion
pyproject.toml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "beyond-chatgpt"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "chainlit==0.7.700",
9
+ "cohere==4.37",
10
+ "openai==1.3.5",
11
+ "pydantic==2.10.1",
12
+ "python-dotenv==1.0.0",
13
+ "tiktoken==0.5.1",
14
+ ]
testload.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ import os
3
+
4
+ load_dotenv() # Looks for a file named ".env" in the current directory
5
+
6
+ api_key = os.getenv("OPENAI_API_KEY")
7
+
8
+ if api_key:
9
+ print("✅ API key loaded successfully.")
10
+ print("First 8 characters:", api_key[:8] + "...")
11
+ else:
12
+ print("❌ API key not found. Check your .env file formatting.")
uv.lock ADDED
The diff for this file is too large to render. See raw diff