Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Lab 1: Calling, Building, and Securing APIs

In homework I1 you will use third-party LLM APIs, and in the group project you will develop your own APIs. In this lab you will experiment with both: connecting to an LLM of your choice, and providing your own API endpoint.

To receive credit for this lab, show your work to the TA during recitation.

Deliverables

  • Use an API key to invoke an LLM API and generate a schema-enforced JSON travel itinerary.
  • Run the API endpoint with the LLM call implemented and demonstrate that it works using an example invocation.
  • Commit your code without committing your credentials. Explain to the TA why hard-coding credentials is a bad idea, and explain any remedial steps you might take should credentials accidentally be leaked.

Getting started

Clone the starter code from this Git repository

The code implements a Flask web application that exposes an API endpoint for generating a structured travel itinerary for a given destination. The API accepts a destination string and returns a JSON response containing high-level travel information.

To generate this response, you will need to call an LLM. We suggest using Meta's Llama, hosted by Groq, using LiteLLM to abstract client-specific details.

Install the dependencies listed in requirements.txt using pip or a similar tool. The Flask server can be started with:

python3 app.py

Once running, the API will be available at:

http://localhost:8000/api/v1/itinerary

Generate an LLM API Key

For this we suggest using an API key from Groq but you are certainly free to use other API keys, such as those from OpenAI, Anthropic, etc., Instructions for using those keys can be found here. The instructions below are shown for getting an API key from Groq.

  1. Sign into your Groq account and navigate to the API keys console
  2. Generate a new API key
  3. Update the code in analyze.py with the API key retrieved from Groq and test it.

Secure your Credentials

The starter code hardcodes credentials in the code. This is a bad practice.

Research and discuss best practices, such as never hard-code credentials, never commit credentials to Git, rotate secrets regularly, encrypt your secrets at rest/in-transit if possible, practice least-access privilege on machines where your credentials are stored as environment variables or within local files.

Rewrite the code to load credentials from a file or an environment variable and commit the code without the credentials.

Implement the call to the LLM

Using LiteLLM, implement the logic in analyze.py to call a an LLM. We suggest groq/llama-3.3-70b-versatile but you are free to use others.

Your implementation should

  • Make at least one LLM call using LiteLLM
  • Request a structured JSON response
  • Enforce (or validate) the structure of the response against a predefined schema. The schema should include the following fields:
    • destination
    • price_range
    • ideal_visit_times
    • top_attractions

The response from your implemented API call should look something like what is shown below:

{
"destination": "...",
"ideal_visit_times": [
...
],
"price_range": ...,"top_attractions": [
...
]
}

Calling your own API

The Flask server serves a simple documentation page at:

http://localhost:8000/

It also exposes the API endpoint:

GET http://localhost:8000/api/v1/itinerary

The endpoint expects a required query parameter:

  • destination: the destination to generate an itinerary for

You can use tools like curl or Postman to ensure your API endpoint is functioning appropriately.

The file mlip-api-lab-collection.json has a sample request to test calls to your API with Postman. Consider using Postman test scripts to test the response of your API endpoints (status codes, response structure, etc.,).

Additional resources

About

Repository for Recitation Lab 1 - Machine Learning in Production - Spring 2026 (Eames Shi - boxuans)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages