diff --git a/.env b/.env new file mode 100644 index 0000000..2f2c0b4 --- /dev/null +++ b/.env @@ -0,0 +1,17 @@ +OPENAI_API_KEY=ADD-YOUR-OPENAI_API_KEY-HERE +REPO_NAME=agentic-ai-workflow +DOCKERHUB_USERNAME=lpm0073 + +# These settings are probably fine to leave as-is. +ENVIRONMENT=local +DOCKERHUB_ACCESS_TOKEN=ADD-YOUR-DOCKERHUB_ACCESS_TOKEN-HERE +LLM_TOOL_CHOICE=required +LOGGING_LEVEL=20 +MYSQL_HOST=sql.lawrencemcdaniel.com +MYSQL_PORT=3306 +MYSQL_USER=smarter_test_user +MYSQL_PASSWORD=smarter_test_user +MYSQL_DATABASE=smarter_test_db +MYSQL_CHARSET=utf8mb4 +PYTHONPATH=./venv:./ +CODECOV_TOKEN=ADD-YOUR-CODECOV_TOKEN-HERE diff --git a/.github/workflows/testsPython.yml b/.github/workflows/testsPython.yml index 452f71d..21d0285 100644 --- a/.github/workflows/testsPython.yml +++ b/.github/workflows/testsPython.yml @@ -69,11 +69,54 @@ jobs: notifications: needs: python-unit-tests runs-on: ubuntu-latest + if: always() # ← ensures this job runs even when tests fail steps: - - name: Notify on test results - run: | - if [ "${{ needs.python-unit-tests.result }}" == "success" ]; then - echo "success notifications go here" - else - echo "failure notifications go here" - fi + - name: Notify Slack on success + if: needs.python-unit-tests.result == 'success' + uses: slackapi/slack-github-action@v1.27.0 + with: + payload: | + { + "text": "*Tests Passed!*", + "attachments": [ + { + "color": "#36A64F", + "fields": [ + { "title": "Repository", "value": "${{ github.repository }}", "short": true }, + { "title": "Branch", "value": "${{ github.ref_name }}", "short": true }, + { "title": "Python Version", "value": "${{ env.python-version }}", "short": true }, + { "title": "Triggered by", "value": "${{ github.actor }}", "short": true }, + { "title": "Commit", "value": "${{ github.sha }}", "short": false }, + { "title": "View Run", "value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "short": false } + ] + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + + - name: Notify Slack on failure + if: needs.python-unit-tests.result != 'success' + uses: slackapi/slack-github-action@v1.27.0 + with: + payload: | + { + "text": "*Tests Failed!*", + "attachments": [ + { + "color": "#FF0000", + "fields": [ + { "title": "Repository", "value": "${{ github.repository }}", "short": true }, + { "title": "Branch", "value": "${{ github.ref_name }}", "short": true }, + { "title": "Python Version", "value": "${{ env.python-version }}", "short": true }, + { "title": "Triggered by", "value": "${{ github.actor }}", "short": true }, + { "title": "Commit", "value": "${{ github.sha }}", "short": false }, + { "title": "View Run", "value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "short": false } + ] + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.gitignore b/.gitignore index 1434880..4df6e1a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ dist *.tfstate *.tfstate.* .terraform/ -.env +#.env lambda_dist_pkg *.zip __pycache__ diff --git a/.vscode/settings.json b/.vscode/settings.json index 3a4d3c9..9bba064 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,6 @@ "cornflakes.linter.executablePath": "venv/bin/flake8", "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" - } + }, + "python-envs.defaultEnvManager": "ms-python.python:venv" } diff --git a/README.md b/README.md index 28065c8..e02fe1e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Agentic AI Workflow Example +# Agentic AI Workflow Example by Salma Lalji e [![FullStackWithLawrence](https://a11ybadges.com/badge?text=FullStackWithLawrence&badgeColor=orange&logo=youtube&logoColor=282828)](https://www.youtube.com/@FullStackWithLawrence)
[![OpenAI](https://a11ybadges.com/badge?logo=openai)](https://platform.openai.com/) @@ -15,6 +15,7 @@ A Python command-line application that demonstrates how to use OpenAI Api functi - how to use Docker Compose to containerize your project - how to leverage Pydantic for constructing complex JSON objects +- Docker debugging Python code is [located here](./app/) diff --git a/app/openai_test.py b/app/openai_test.py new file mode 100644 index 0000000..3d740f9 --- /dev/null +++ b/app/openai_test.py @@ -0,0 +1,52 @@ +import os +from openai import OpenAI +from dotenv import load_dotenv + +load_dotenv() + + +client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) + +messages = [ + { + "role": "system", + "content": "You are a helpful assistant that can call tools." + }, + { + "role": "user", + "content": "Give me a list of available AI courses." + } +] + +response = client.chat.completions.create( + model="gpt-4.1-mini", + messages=messages, + temperature=0.7 +) +print(response.choices[0].message.content) + +from pydantic import BaseModel, Field +from typing import List, Optional, Literal + +class GetCoursesRequest(BaseModel): + topics: List[str] = Field(..., description="List of course topics to retrieve") + max_cost: float = Field(0.0, ge=0, description="Maximum budget for the courses") + difficulty: Optional[Literal["beginner", "intermediate", "advanced"]] = Field( + None, + description="Optional difficulty level of the courses" + ) + + + +print(GetCoursesRequest.model_json_schema()) +def make_get_courses_tool(): + return { + "type": "function", + "function": { + "name": "get_courses", + "description": "Retrieve a list of courses that match given topics.", + "parameters": GetCoursesRequest.model_json_schema(), + }, + } + +print(make_get_courses_tool())