From 9d9e8b7aa45ccd3a0f245132a27bca98ab415145 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Thu, 28 Sep 2023 21:20:03 +0000 Subject: [PATCH 01/15] add lesson template --- 6-building-chat-applications/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 6-building-chat-applications/README.md diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md new file mode 100644 index 000000000..233eb30b3 --- /dev/null +++ b/6-building-chat-applications/README.md @@ -0,0 +1,20 @@ +# Building Chat Applications + +## Introduction (h2) +This lesson will cover: +Concept 1 +Concept 2 +Concept 3 + +## Learning Goals (h2) +After completing this lesson you will know how to/understand: +Goal 1 +Goal 2 +Goal 3 + +## Concept 1 (h2) + +## Concept 2 (h2) + + +## Concept 3 (h2) From 2c2df435fe3fec0f57eac9518e233aa9038e6c68 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Thu, 28 Sep 2023 21:53:40 +0000 Subject: [PATCH 02/15] ads topics --- 6-building-chat-applications/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 233eb30b3..bbef971d0 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -8,13 +8,13 @@ Concept 3 ## Learning Goals (h2) After completing this lesson you will know how to/understand: -Goal 1 -Goal 2 -Goal 3 +- Techniques for efficiently buliding and integerating chat applications +- How to apply customization and fine tuning to applications +- Startegies and considerations to effectively monitor high quality chat applications -## Concept 1 (h2) +## Integrating Generative AI into Chat Applications -## Concept 2 (h2) +## Customization and Fine tuning -## Concept 3 (h2) +## Metrics for Responsible AI-Driven Chat From d5ad93ea7d8679e72db8dc300538ba01c2ad50d7 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Fri, 29 Sep 2023 20:46:23 +0000 Subject: [PATCH 03/15] chatbot vs application --- 6-building-chat-applications/README.md | 31 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index bbef971d0..18ab1a031 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -1,19 +1,36 @@ # Building Chat Applications -## Introduction (h2) -This lesson will cover: -Concept 1 -Concept 2 -Concept 3 -## Learning Goals (h2) + +## Introduction +- Techniques for efficiently buliding and integerating chat applications +- How to apply customization and fine tuning to applications +- Strategies and considerations to effectively monitor high quality chat applications + +## Learning Goals After completing this lesson you will know how to/understand: - Techniques for efficiently buliding and integerating chat applications - How to apply customization and fine tuning to applications -- Startegies and considerations to effectively monitor high quality chat applications +- Strategies and considerations to effectively monitor high quality chat applications ## Integrating Generative AI into Chat Applications +### Chatbot or Chat application? + +In the ever evolving world of digital communication, it's easy to conflate terms like 'chatbots' and 'AI-powered chat applications,' but they serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. While it may host one or several chatbots for specialized tasks, its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. + +The table below outlines the key differences and similarities to help us understand their unique roles in digital communication. + +| Chatbot | Generative AI-Powered Chat Application | +| ------------------------------------- | -------------------------------------- | +| Task-Focused and rule based | Dynamic, Context-Aware, & Versatile | +| Limited to Programmed functions | Hosts One or Multiple Chatbots | +| Often Integrated into larger systems | Incorporates Generative AI Models | +| Specialized & structured interactions | Capable of Open-Domain Discussions | + + + + ## Customization and Fine tuning From 4ff4ccf86c2dac127be5f25757cd1904f8145413 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Fri, 29 Sep 2023 21:59:44 +0000 Subject: [PATCH 04/15] intro and additional section copy --- 6-building-chat-applications/README.md | 29 ++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 18ab1a031..15a645d4d 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -1,23 +1,30 @@ -# Building Chat Applications +# Building Generative AI-Powered Chat Applications +In the age of digitized communication, chat applications have become integrated into our daily lives, offering more than just a means of casual conversation. They are integral parts of customer service, technical support, and even sophisticated advisory systems. It's likely that you've gotten some help from a chat application not too long ago. As we integrate more advanced technologies like generative AI into these platforms, the complexity increases and so does the challenges. How do we efficiently build and seamlessly integrate these AI-powered applications for specific use cases? Once deployed, how can we monitor and ensure that the applications are operating at the highest level of quality, both in terms of functionality and adhering to the [six pillars of responsible AI]()? +As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the foundational architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. -## Introduction -- Techniques for efficiently buliding and integerating chat applications -- How to apply customization and fine tuning to applications -- Strategies and considerations to effectively monitor high quality chat applications +This lesson covers: +- Techniques for efficiently buliding and integerating chat applications. +- How to apply customization and fine tuning to applications. +- Strategies and considerations to effectively monitor high quality chat applications. ## Learning Goals -After completing this lesson you will know how to/understand: -- Techniques for efficiently buliding and integerating chat applications -- How to apply customization and fine tuning to applications -- Strategies and considerations to effectively monitor high quality chat applications +By the end of this lesson, you will be: + +- Equipped with the technical know-how to efficiently build and integrate chat applications into existing systems or as stand-alone platform. +- Possess the skills to customize chat applications for specific use-cases and understand how to fine-tune generative AI models for optimized performance and relevance. +- Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications, ensuring they meet or exceed operational and ethical standards. + + ## Integrating Generative AI into Chat Applications + + ### Chatbot or Chat application? -In the ever evolving world of digital communication, it's easy to conflate terms like 'chatbots' and 'AI-powered chat applications,' but they serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. While it may host one or several chatbots for specialized tasks, its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. +It's easy to conflate terms like 'chatbots' and 'AI-powered chat applications,' but they serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. While it may host one or several chatbots for specialized tasks, its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. The table below outlines the key differences and similarities to help us understand their unique roles in digital communication. @@ -31,7 +38,7 @@ The table below outlines the key differences and similarities to help us underst -## Customization and Fine tuning +## Customization and Fine tuning ## Metrics for Responsible AI-Driven Chat From 269ccf14b4de9c7ee80117b39bb0e45d02598f41 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Fri, 29 Sep 2023 22:12:38 +0000 Subject: [PATCH 05/15] first section intro --- 6-building-chat-applications/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 15a645d4d..5c4084b41 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -16,11 +16,11 @@ By the end of this lesson, you will be: - Possess the skills to customize chat applications for specific use-cases and understand how to fine-tune generative AI models for optimized performance and relevance. - Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications, ensuring they meet or exceed operational and ethical standards. - - ## Integrating Generative AI into Chat Applications - + What elevates a chat platform from simple text exchanges to dynamic conversations by integrating generative AI? We're talking about building something that isn't just functional but is also fast, scalable, and user-friendly. Elevating these applications through generative AI isn't merely about making them smarter; it's about optimizing their architecture, performance, and user interface to deliver an unparalleled user experience. This involves diving deep into various aspects, from the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex integration landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. + +By the end of this section, you'll be equipped with the technical expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. ### Chatbot or Chat application? From 3d3153468bbeecd6d0f6f4a5a7b26b784a7c3cd8 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 3 Oct 2023 03:32:47 +0000 Subject: [PATCH 06/15] revise section 1 --- 6-building-chat-applications/README.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 5c4084b41..cb2a70bf0 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -1,30 +1,32 @@ # Building Generative AI-Powered Chat Applications -In the age of digitized communication, chat applications have become integrated into our daily lives, offering more than just a means of casual conversation. They are integral parts of customer service, technical support, and even sophisticated advisory systems. It's likely that you've gotten some help from a chat application not too long ago. As we integrate more advanced technologies like generative AI into these platforms, the complexity increases and so does the challenges. How do we efficiently build and seamlessly integrate these AI-powered applications for specific use cases? Once deployed, how can we monitor and ensure that the applications are operating at the highest level of quality, both in terms of functionality and adhering to the [six pillars of responsible AI]()? +Chat applications have become integrated into our daily lives, offering more than just a means of casual conversation. They're integral parts of customer service, technical support, and even sophisticated advisory systems. It's likely that you've gotten some help from a chat application not too long ago. As we integrate more advanced technologies like generative AI into these platforms, the complexity increases and so does the challenges. How do we efficiently build and seamlessly integrate these AI-powered applications for specific use cases? Once deployed, how can we monitor and ensure that the applications are operating at the highest level of quality, both in terms of functionality and adhering to the [six principles of responsible AI](https://www.microsoft.com/ai/responsible-ai)? As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the foundational architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. This lesson covers: - Techniques for efficiently buliding and integerating chat applications. - How to apply customization and fine tuning to applications. -- Strategies and considerations to effectively monitor high quality chat applications. +- Strategies and considerations to effectively monitor chat applications. ## Learning Goals -By the end of this lesson, you will be: +By the end of this lesson, you'll be able to: -- Equipped with the technical know-how to efficiently build and integrate chat applications into existing systems or as stand-alone platform. -- Possess the skills to customize chat applications for specific use-cases and understand how to fine-tune generative AI models for optimized performance and relevance. -- Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications, ensuring they meet or exceed operational and ethical standards. +- Understand how to build and integrate chat applications into existing systems or as stand-alone platform. +- Customize chat applications for specific use-cases. +- Understand how to fine-tune generative AI models for optimized performance and relevance. +- Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications. +- Ensuring chat applications leverage AI responsibly. ## Integrating Generative AI into Chat Applications - What elevates a chat platform from simple text exchanges to dynamic conversations by integrating generative AI? We're talking about building something that isn't just functional but is also fast, scalable, and user-friendly. Elevating these applications through generative AI isn't merely about making them smarter; it's about optimizing their architecture, performance, and user interface to deliver an unparalleled user experience. This involves diving deep into various aspects, from the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex integration landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. + Elevating chat applications through generative AI isn't only centered around making them smarter; it's about optimizing their architecture, performance, and user interface to deliver an unparalleled user experience. This involves investigating the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. By the end of this section, you'll be equipped with the technical expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. ### Chatbot or Chat application? -It's easy to conflate terms like 'chatbots' and 'AI-powered chat applications,' but they serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. While it may host one or several chatbots for specialized tasks, its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. +Before we dive into building chat applications, let's compare 'chatbots' against 'AI-powered chat applications,' which serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. Its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. The table below outlines the key differences and similarities to help us understand their unique roles in digital communication. @@ -36,6 +38,9 @@ The table below outlines the key differences and similarities to help us underst | Specialized & structured interactions | Capable of Open-Domain Discussions | +# Leveraging pre-built functionalities with SDKs and APIs + + ## Customization and Fine tuning From f6cc48eac0786849e388728696bf451c353f3d86 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 3 Oct 2023 06:09:49 +0000 Subject: [PATCH 07/15] section 1 complete --- 6-building-chat-applications/README.md | 58 ++++++++++++++++++++------ 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index cb2a70bf0..3bae8d4cc 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -5,45 +5,79 @@ Chat applications have become integrated into our daily lives, offering more tha As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the foundational architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. This lesson covers: -- Techniques for efficiently buliding and integerating chat applications. -- How to apply customization and fine tuning to applications. +- Techniques for efficiently building and integrating chat applications. +- How to apply customization and fine-tuning to applications. - Strategies and considerations to effectively monitor chat applications. ## Learning Goals By the end of this lesson, you'll be able to: -- Understand how to build and integrate chat applications into existing systems or as stand-alone platform. +- Describe considerations for how building and integrating chat applications into existing systems. - Customize chat applications for specific use-cases. -- Understand how to fine-tune generative AI models for optimized performance and relevance. - Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications. - Ensuring chat applications leverage AI responsibly. ## Integrating Generative AI into Chat Applications - Elevating chat applications through generative AI isn't only centered around making them smarter; it's about optimizing their architecture, performance, and user interface to deliver an unparalleled user experience. This involves investigating the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. +Elevating chat applications through generative AI isn't only centered around making them smarter; it's about optimizing their architecture, performance, and user interface to deliver a quality user experience. This involves investigating the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. By the end of this section, you'll be equipped with the technical expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. ### Chatbot or Chat application? -Before we dive into building chat applications, let's compare 'chatbots' against 'AI-powered chat applications,' which serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. Its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat applicaion can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. +Before we dive into building chat applications, let's compare 'chatbots' against 'AI-powered chat applications,' which serve distinct roles and functionalities. A chatbot's main purpose is to automate specific conversational tasks, such as answering frequently asked questions or tracking a package. It's typically governed by rule-based logic or complex AI algorithms. In contrast, an AI-powered chat application is a far more expansive environment designed to facilitate various forms of digital communication, such as text, voice, and video chats among human users. Its defining feature is the integration of generative AI model that simulate nuanced, human-like conversations, generating responses based on a wide variety of input and contextual cues. A generative AI powered chat application can engage in open-domain discussions, adapt to evolving conversational contexts, and even produce creative or complex dialogue. The table below outlines the key differences and similarities to help us understand their unique roles in digital communication. | Chatbot | Generative AI-Powered Chat Application | | ------------------------------------- | -------------------------------------- | -| Task-Focused and rule based | Dynamic, Context-Aware, & Versatile | -| Limited to Programmed functions | Hosts One or Multiple Chatbots | -| Often Integrated into larger systems | Incorporates Generative AI Models | -| Specialized & structured interactions | Capable of Open-Domain Discussions | +| Task-Focused and rule based | Context-aware | +| Limited to Programmed functions | May host one or multiple chatbots | +| Often integrated into larger systems | Incorporates generative AI models | +| Specialized & structured interactions | Capable of open-domain discussions | -# Leveraging pre-built functionalities with SDKs and APIs +### Leveraging pre-built functionalities with SDKs and APIs + +When building a chat application, it's best to assess what is already out there. Using SDKs and APIs to build chat application is an advantageous strategy for building chat applications for a variety of reasons. + +- **Expedites the development process and reduces overhead**: Relying on pre-built functionalities instead of the expensive process of building them yourself allows you to focus on other aspects of your application that you may find more important, such as business logic. +- **Better performance**: When building functionality from scratch, you'll eventually ask yourself "How does it scale? Is this application capable of handling a sudden influx of users?" Well maintained SDK and APIs often have built in solutions for these concerns. +- **Easier maintenance**: Updates and improvements are easier to manage as most APIs and SDKs simply require an update to a library when a newer version is released. +- **Access to cutting edge technology**: Leveraging models that have been fined tuned and trained on extensive dataset provides your application with natural language capabilities. + +By integrating well-documented SDKs and APIs, you're strategically positioning your application for long-term success, addressing scalability and maintenance concerns. + +### User Experience (UX) + +General UX principles apply for chat applications, but here's some additional considerations that become particularly important due to the machine learning components involved. + +- **Mechanism for addressing ambiguity**: Generative AI models can sometimes produce ambiguous responses. Providing a chat application with the ability for the user to ask for clarification. +- **Context retention**: Advanced generative AI models have the ability to remember context within a conversation, which can be a necessary asset to the user experience. Giving users the ability to control and manage context improves the user experience, but introduces the risk of retaining sensitive user information. Considerations for how long this information is stored, such as introducing a retention policy, can balance the need for context against privacy. +- **Personalization**: With the ability to learn and adapt, AI models can provide offer an individualized experience for a user. Tailoring the user experience through features like user profiles not only makes the user feel understood, but it also helps their pursuit in finding specific answers, creating a more efficient and satisfying interaction. + +One such example is the "Custom instructions" settings in ChatGPT [IMAGE]() + +### Accessibility + + Whether a user has visual, auditory, motor, or cognitive impairments, a well-designed chat application should be usable by all. The following list breaks down specific features aimed at enhancing accessibility for various user impairments. + +- **Features for Visual Impairment**: High contrast themes and resizable text, screen reader compatibility. +- **Features for Auditory Impairment**: Text-to-speech and speech-to-text functions, visual cues for audio notifications. +- **Features for Motor Impairment**: Keyboard navigation support, voice commands. +- **Features for Cognitive Impairment**: Simplified language options. + +## Customization and Fine-tuning + -## Customization and Fine tuning ## Metrics for Responsible AI-Driven Chat + + +References + +[Fine-Tuning language models from human preferences]() https://arxiv.org/pdf/1909.08593.pdf \ No newline at end of file From 49e1928db456950f65f703971790eceeab86a75b Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 3 Oct 2023 09:22:16 +0000 Subject: [PATCH 08/15] first draft --- 6-building-chat-applications/README.md | 58 +++++++++++++++++++++----- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 3bae8d4cc..e21353335 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -12,7 +12,7 @@ This lesson covers: ## Learning Goals By the end of this lesson, you'll be able to: -- Describe considerations for how building and integrating chat applications into existing systems. +- Describe considerations for building and integrating chat applications into existing systems. - Customize chat applications for specific use-cases. - Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications. - Ensuring chat applications leverage AI responsibly. @@ -21,7 +21,7 @@ By the end of this lesson, you'll be able to: Elevating chat applications through generative AI isn't only centered around making them smarter; it's about optimizing their architecture, performance, and user interface to deliver a quality user experience. This involves investigating the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. -By the end of this section, you'll be equipped with the technical expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. +By the end of this section, you'll be equipped with the expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. ### Chatbot or Chat application? @@ -32,31 +32,30 @@ The table below outlines the key differences and similarities to help us underst | Chatbot | Generative AI-Powered Chat Application | | ------------------------------------- | -------------------------------------- | | Task-Focused and rule based | Context-aware | -| Limited to Programmed functions | May host one or multiple chatbots | -| Often integrated into larger systems | Incorporates generative AI models | +| Often integrated into larger systems | May host one or multiple chatbots | +| Limited to programmed functions | Incorporates generative AI models | | Specialized & structured interactions | Capable of open-domain discussions | ### Leveraging pre-built functionalities with SDKs and APIs -When building a chat application, it's best to assess what is already out there. Using SDKs and APIs to build chat application is an advantageous strategy for building chat applications for a variety of reasons. +When building a chat application, it's best to assess what is already out there. Using SDKs and APIs to build chat application is an advantageous strategy for building chat applications for a variety of reasons. By integrating well-documented SDKs and APIs, you're strategically positioning your application for long-term success, addressing scalability and maintenance concerns. - **Expedites the development process and reduces overhead**: Relying on pre-built functionalities instead of the expensive process of building them yourself allows you to focus on other aspects of your application that you may find more important, such as business logic. - **Better performance**: When building functionality from scratch, you'll eventually ask yourself "How does it scale? Is this application capable of handling a sudden influx of users?" Well maintained SDK and APIs often have built in solutions for these concerns. - **Easier maintenance**: Updates and improvements are easier to manage as most APIs and SDKs simply require an update to a library when a newer version is released. - **Access to cutting edge technology**: Leveraging models that have been fined tuned and trained on extensive dataset provides your application with natural language capabilities. -By integrating well-documented SDKs and APIs, you're strategically positioning your application for long-term success, addressing scalability and maintenance concerns. ### User Experience (UX) General UX principles apply for chat applications, but here's some additional considerations that become particularly important due to the machine learning components involved. -- **Mechanism for addressing ambiguity**: Generative AI models can sometimes produce ambiguous responses. Providing a chat application with the ability for the user to ask for clarification. +- **Mechanism for addressing ambiguity**: Generative AI models occasionally generate ambiguous answers. A feature that allows users to ask for clarification can be helpful should they come across this problem. - **Context retention**: Advanced generative AI models have the ability to remember context within a conversation, which can be a necessary asset to the user experience. Giving users the ability to control and manage context improves the user experience, but introduces the risk of retaining sensitive user information. Considerations for how long this information is stored, such as introducing a retention policy, can balance the need for context against privacy. - **Personalization**: With the ability to learn and adapt, AI models can provide offer an individualized experience for a user. Tailoring the user experience through features like user profiles not only makes the user feel understood, but it also helps their pursuit in finding specific answers, creating a more efficient and satisfying interaction. -One such example is the "Custom instructions" settings in ChatGPT [IMAGE]() +One such example of personalization is the "Custom instructions" settings in OpenAI's ChatGPT ![IMAGE]() ### Accessibility @@ -67,17 +66,54 @@ One such example is the "Custom instructions" settings in ChatGPT [IMAGE]() - **Features for Motor Impairment**: Keyboard navigation support, voice commands. - **Features for Cognitive Impairment**: Simplified language options. -## Customization and Fine-tuning +## Customization and Fine-tuning for Domain-Specific Language Models +Imagine a chat application that understands your company's jargon and anticipates the specific queries its user base commonly has. Domain-specific language models (DSL Models) have the capacity to enhance user engagement and by providing specialized, contextually relevant interactions. It's a model that is trained or fine-tuned to understand and generate text related to a specific field, industry, or subject. Options for using a DSL model can vary from training one from scratch, to using pre-existing ones through SDKs and APIs. Another option is fine-tuning, which involves taking an existing pre-trained model and adapting it for a specific domain. +Fine-tuning is often considered when a pre-trained model falls short in a specialized domain or specific task. For instance, medical queries are complex and require a lot of context. When a medical professional diagnoses a patient it's based on a variety of factors such as lifestyle or pre-existing conditions, and may even rely on recent medical journals to validate their diagnosis. In such nuanced scenarios, a general-purpose AI chat application cannot be a reliable source. Consider a chat application designed to assist medical practitioners by providing quick references to treatment guidelines, drug interactions, or recent research findings. While the original, general-purpose model might be adequate for answering basic medical questions or providing general advice, it may struggle with highly specific or complex cases. For example, a neurologist might ask the application, "What are the current best practices for managing drug-resistant epilepsy in pediatric patients?" A general-purpose model could struggle to provide a current answer that incorporates the most recent advancements in neurology and pharmacology. In instances such as these, fine-tuning the model with a specialized medical dataset can significantly improve its ability to handle these intricate medical inquiries more accurately and reliably. This requires access to a large and relevant dataset that represents the domain-specific challenges and questions that need to be addressed. +## Considerations for a High Quality AI-Driven Chat Experience +Below are some considerations for + +### Key Metrics + +To maintain the high-quality performance an application, it's essential to keep track of key metrics and considerations. These measurements not only ensure the functionality of the application but also assess the quality of the AI model and user experience. Below is a list that covers basic, AI, and user experience metrics to consider. + +| Metric | Definition | Considerations for Chat Developer | +| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| **Uptime** | Measures the time the application is operational and accessible by users. | How will you minimize downtime? | +| **Response Time** | The time taken by the application to reply to a user's query. | How can you optimize query processing to improve response time? | +| **Precision** | The ratio of true positive predictions to the total number of positive predictions | How will you validate the precision of your model? | +| **Recall (Sensitivity)** | The ratio of true positive predictions to the actual number of positives | How will you measure and improve recall? | +| **F1 Score** | The harmonic mean of precision and recall, that balances the trade-off between both. | What is your target F1 Score? How will you balance precision and recall? | +| **Perplexity** | Measures how well the probability distribution predicted by the model aligns with the actual distribution of the data. | How will you minimize perplexity? | +| **User Satisfaction Metrics** | Measures the user's perception of the application. Often captured through surveys. | How often will you collect user feedback? How will you adapt based on it? | +| **Error Rate** | The rate at which the model makes mistakes in understanding or output. | What strategies do you have in place to reduce error rates? | +| **Retraining Cycles** | The frequency with which the model is updated to incorporate new data and insights. | How often will you retrain the model? What triggers a retraining cycle? | +| **Anomaly Detection** | Tools and techniques for identifying unusual patterns that do not conform to expected behavior. | How will you respond to anomalies? | + + +## Implementing Responsible AI Practices in Chat Applications + +Microsoft's approach to Responsible AI has identified six principles that should guide AI development and use. Below are the principles, their definition, and things a chat developer should consider any why they should take them seriously. + + +| Principles | Microsoft's Definition | Considerations for Chat Developer | Why It's Important | +| ---------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| Fairness | AI systems should treat all people fairly. | Ensure the chat application does not discriminate based on user data. | To build trust and inclusivity among users; avoids legal ramifications. | +| Reliability and Safety | AI systems should perform reliably and safely. | Implement testing and fail-safes to minimize errors and risks. | Ensures user satisfaction and prevents potential harm. | +| Privacy and Security | AI systems should be secure and respect privacy. | Implement strong encryption and data protection measures. | To safeguard sensitive user data and comply with privacy laws. | +| Inclusiveness | AI systems should empower everyone and engage people. | Design UI/UX that is accessible and easy-to-use for diverse audiences. | Ensures a wider range of people can use the application effectively. | +| Transparency | AI systems should be understandable. | Provide clear documentation and reasoning for AI responses. | Users are more likely to trust a system if they can understand how decisions are made. | +| Accountability | People should be accountable for AI systems. | Establish a clear process for auditing and improving AI decisions. | Enables ongoing improvement and corrective measures in case of mistakes. | -## Metrics for Responsible AI-Driven Chat References -[Fine-Tuning language models from human preferences]() https://arxiv.org/pdf/1909.08593.pdf \ No newline at end of file +[Fine-Tuning language models from human preferences](https://arxiv.org/pdf/1909.08593.pdf) + +[OpenAI Fine Tuning](https://platform.openai.com/docs/guides/fine-tuning/when-to-use-fine-tuning) \ No newline at end of file From a906324b8c437d6ca08ca0ee5ed45870528cebc2 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 3 Oct 2023 09:30:19 +0000 Subject: [PATCH 09/15] first draft edits --- 6-building-chat-applications/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index e21353335..ee602c540 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -2,7 +2,7 @@ Chat applications have become integrated into our daily lives, offering more than just a means of casual conversation. They're integral parts of customer service, technical support, and even sophisticated advisory systems. It's likely that you've gotten some help from a chat application not too long ago. As we integrate more advanced technologies like generative AI into these platforms, the complexity increases and so does the challenges. How do we efficiently build and seamlessly integrate these AI-powered applications for specific use cases? Once deployed, how can we monitor and ensure that the applications are operating at the highest level of quality, both in terms of functionality and adhering to the [six principles of responsible AI](https://www.microsoft.com/ai/responsible-ai)? -As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the foundational architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. +As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the aspects of architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. This lesson covers: - Techniques for efficiently building and integrating chat applications. @@ -15,13 +15,13 @@ By the end of this lesson, you'll be able to: - Describe considerations for building and integrating chat applications into existing systems. - Customize chat applications for specific use-cases. - Identify key metrics and considerations to effectively monitor and maintain the quality of AI-powered chat applications. -- Ensuring chat applications leverage AI responsibly. +- Ensure chat applications leverage AI responsibly. ## Integrating Generative AI into Chat Applications Elevating chat applications through generative AI isn't only centered around making them smarter; it's about optimizing their architecture, performance, and user interface to deliver a quality user experience. This involves investigating the architectural foundations, API integrations, and user interface considerations. This section aims to offer you a comprehensive roadmap for navigating these complex landscapes, whether you're plugging them into existing systems or building them as stand-alone platforms. -By the end of this section, you'll be equipped with the expertise needed to efficiently construct and incorporate chat applications, either as enhancements to existing systems or as stand-alone solutions. +By the end of this section, you'll be equipped with the expertise needed to efficiently construct and incorporate chat applications. ### Chatbot or Chat application? @@ -39,7 +39,7 @@ The table below outlines the key differences and similarities to help us underst ### Leveraging pre-built functionalities with SDKs and APIs -When building a chat application, it's best to assess what is already out there. Using SDKs and APIs to build chat application is an advantageous strategy for building chat applications for a variety of reasons. By integrating well-documented SDKs and APIs, you're strategically positioning your application for long-term success, addressing scalability and maintenance concerns. +When building a chat application, a great first step is to assess what is already out there. Using SDKs and APIs to build chat applications is an advantageous strategy for a variety of reasons. By integrating well-documented SDKs and APIs, you're strategically positioning your application for long-term success, addressing scalability and maintenance concerns. - **Expedites the development process and reduces overhead**: Relying on pre-built functionalities instead of the expensive process of building them yourself allows you to focus on other aspects of your application that you may find more important, such as business logic. - **Better performance**: When building functionality from scratch, you'll eventually ask yourself "How does it scale? Is this application capable of handling a sudden influx of users?" Well maintained SDK and APIs often have built in solutions for these concerns. @@ -95,7 +95,7 @@ To maintain the high-quality performance an application, it's essential to keep | **Anomaly Detection** | Tools and techniques for identifying unusual patterns that do not conform to expected behavior. | How will you respond to anomalies? | -## Implementing Responsible AI Practices in Chat Applications +### Implementing Responsible AI Practices in Chat Applications Microsoft's approach to Responsible AI has identified six principles that should guide AI development and use. Below are the principles, their definition, and things a chat developer should consider any why they should take them seriously. From 08f13dc7f3a60c4733d1a78e052091fdf9b87e62 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 10 Oct 2023 14:52:46 +0000 Subject: [PATCH 10/15] apply immediate edits --- 6-building-chat-applications/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index ee602c540..951c3cf0e 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -2,7 +2,7 @@ Chat applications have become integrated into our daily lives, offering more than just a means of casual conversation. They're integral parts of customer service, technical support, and even sophisticated advisory systems. It's likely that you've gotten some help from a chat application not too long ago. As we integrate more advanced technologies like generative AI into these platforms, the complexity increases and so does the challenges. How do we efficiently build and seamlessly integrate these AI-powered applications for specific use cases? Once deployed, how can we monitor and ensure that the applications are operating at the highest level of quality, both in terms of functionality and adhering to the [six principles of responsible AI](https://www.microsoft.com/ai/responsible-ai)? -As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the aspects of architecture that supports these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. +As we move further into an age defined by automation and seamless human-machine interactions, understanding how generative AI transforms the scope, depth, and adaptability of chat applications becomes essential. This lesson will investigate the aspects of architecture that support these intricate systems, delve into the methodologies for fine-tuning them for domain-specific tasks, and evaluate the metrics and considerations pertinent to ensuring responsible AI deployment. This lesson covers: - Techniques for efficiently building and integrating chat applications. @@ -49,11 +49,11 @@ When building a chat application, a great first step is to assess what is alread ### User Experience (UX) -General UX principles apply for chat applications, but here's some additional considerations that become particularly important due to the machine learning components involved. +General UX principles apply to chat applications, but here's some additional considerations that become particularly important due to the machine learning components involved. - **Mechanism for addressing ambiguity**: Generative AI models occasionally generate ambiguous answers. A feature that allows users to ask for clarification can be helpful should they come across this problem. - **Context retention**: Advanced generative AI models have the ability to remember context within a conversation, which can be a necessary asset to the user experience. Giving users the ability to control and manage context improves the user experience, but introduces the risk of retaining sensitive user information. Considerations for how long this information is stored, such as introducing a retention policy, can balance the need for context against privacy. -- **Personalization**: With the ability to learn and adapt, AI models can provide offer an individualized experience for a user. Tailoring the user experience through features like user profiles not only makes the user feel understood, but it also helps their pursuit in finding specific answers, creating a more efficient and satisfying interaction. +- **Personalization**: With the ability to learn and adapt, AI models offer an individualized experience for a user. Tailoring the user experience through features like user profiles not only makes the user feel understood, but it also helps their pursuit in finding specific answers, creating a more efficient and satisfying interaction. One such example of personalization is the "Custom instructions" settings in OpenAI's ChatGPT ![IMAGE]() @@ -68,7 +68,7 @@ One such example of personalization is the "Custom instructions" settings in Ope ## Customization and Fine-tuning for Domain-Specific Language Models -Imagine a chat application that understands your company's jargon and anticipates the specific queries its user base commonly has. Domain-specific language models (DSL Models) have the capacity to enhance user engagement and by providing specialized, contextually relevant interactions. It's a model that is trained or fine-tuned to understand and generate text related to a specific field, industry, or subject. Options for using a DSL model can vary from training one from scratch, to using pre-existing ones through SDKs and APIs. Another option is fine-tuning, which involves taking an existing pre-trained model and adapting it for a specific domain. +Imagine a chat application that understands your company's jargon and anticipates the specific queries its user base commonly has. Domain-specific language models (DSL Models) can enhance user engagement and by providing specialized, contextually relevant interactions. It's a model that is trained or fine-tuned to understand and generate text related to a specific field, industry, or subject. Options for using a DSL model can vary from training one from scratch, to using pre-existing ones through SDKs and APIs. Another option is fine-tuning, which involves taking an existing pre-trained model and adapting it for a specific domain. Fine-tuning is often considered when a pre-trained model falls short in a specialized domain or specific task. For instance, medical queries are complex and require a lot of context. When a medical professional diagnoses a patient it's based on a variety of factors such as lifestyle or pre-existing conditions, and may even rely on recent medical journals to validate their diagnosis. In such nuanced scenarios, a general-purpose AI chat application cannot be a reliable source. Consider a chat application designed to assist medical practitioners by providing quick references to treatment guidelines, drug interactions, or recent research findings. While the original, general-purpose model might be adequate for answering basic medical questions or providing general advice, it may struggle with highly specific or complex cases. For example, a neurologist might ask the application, "What are the current best practices for managing drug-resistant epilepsy in pediatric patients?" A general-purpose model could struggle to provide a current answer that incorporates the most recent advancements in neurology and pharmacology. In instances such as these, fine-tuning the model with a specialized medical dataset can significantly improve its ability to handle these intricate medical inquiries more accurately and reliably. This requires access to a large and relevant dataset that represents the domain-specific challenges and questions that need to be addressed. From 596697d2becd16bec2692990fa50004a2d677633 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Fri, 13 Oct 2023 19:20:23 +0000 Subject: [PATCH 11/15] add chat completion example and notebook --- 6-building-chat-applications/README.md | 16 +++++++++ 6-building-chat-applications/notebook.ipynb | 39 +++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 6-building-chat-applications/notebook.ipynb diff --git a/6-building-chat-applications/README.md b/6-building-chat-applications/README.md index 951c3cf0e..ad8f944ad 100644 --- a/6-building-chat-applications/README.md +++ b/6-building-chat-applications/README.md @@ -46,6 +46,22 @@ When building a chat application, a great first step is to assess what is alread - **Easier maintenance**: Updates and improvements are easier to manage as most APIs and SDKs simply require an update to a library when a newer version is released. - **Access to cutting edge technology**: Leveraging models that have been fined tuned and trained on extensive dataset provides your application with natural language capabilities. +Accessing functionality of an SDK or API typically involves obtaining permission to use the provided services, which is often through the use of a unique key or authentication token. We'll use the OpenAI Python Library to explore what this looks like. You can also try it out on your own in the [notebook](notebook.ipynb) for this lesson. + +```python +import os +import openai + +openai.api_key = os.getenv("OPENAI_API_KEY") + +chat_completion = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Suggest two titles for a instructional lesson on chat applications for generative AI."}]) +``` + +The above example uses the GPT-3.5 Turbo model to complete the prompt, but notice that the API key is set prior to doing so. You'd receive the following error if you didn't set the key. + +``` +AuthenticationError: No API key provided. You can set your API key in code using 'openai.api_key = ', or you can set the environment variable OPENAI_API_KEY=). If your API key is stored in a file, you can point the openai module at it with 'openai.api_key_path = '. You can generate API keys in the OpenAI web interface. See https://platform.openai.com/account/api-keys for details. +``` ### User Experience (UX) diff --git a/6-building-chat-applications/notebook.ipynb b/6-building-chat-applications/notebook.ipynb new file mode 100644 index 000000000..e206a4dd5 --- /dev/null +++ b/6-building-chat-applications/notebook.ipynb @@ -0,0 +1,39 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import openai\n", + "\n", + "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n", + "\n", + "chat_completion = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", messages=[{\"role\": \"user\", \"content\": \"Suggest two titles for a instructional lesson on chat applications for generative AI.\"}])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 127bfe48272f941c399e2fd869ca2fbc131c8100 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Mon, 16 Oct 2023 20:59:07 +0000 Subject: [PATCH 12/15] rename to chapter 7 --- .../README.md | 0 .../notebook.ipynb | 5 +++++ 2 files changed, 5 insertions(+) rename {6-building-chat-applications => 7-building-chat-applications}/README.md (100%) rename {6-building-chat-applications => 7-building-chat-applications}/notebook.ipynb (92%) diff --git a/6-building-chat-applications/README.md b/7-building-chat-applications/README.md similarity index 100% rename from 6-building-chat-applications/README.md rename to 7-building-chat-applications/README.md diff --git a/6-building-chat-applications/notebook.ipynb b/7-building-chat-applications/notebook.ipynb similarity index 92% rename from 6-building-chat-applications/notebook.ipynb rename to 7-building-chat-applications/notebook.ipynb index e206a4dd5..7711255a2 100644 --- a/6-building-chat-applications/notebook.ipynb +++ b/7-building-chat-applications/notebook.ipynb @@ -13,6 +13,11 @@ "\n", "chat_completion = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", messages=[{\"role\": \"user\", \"content\": \"Suggest two titles for a instructional lesson on chat applications for generative AI.\"}])" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] } ], "metadata": { From 01848bfd0efc29f18f2ad4c1643d2a3b0f6ecbef Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Mon, 16 Oct 2023 21:58:35 +0000 Subject: [PATCH 13/15] update UX section, add more references --- .vscode/ltex.dictionary.en-US.txt | 1 + 7-building-chat-applications/README.md | 23 +++++++++++++++++---- 7-building-chat-applications/notebook.ipynb | 14 +++++++------ 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 .vscode/ltex.dictionary.en-US.txt diff --git a/.vscode/ltex.dictionary.en-US.txt b/.vscode/ltex.dictionary.en-US.txt new file mode 100644 index 000000000..338981356 --- /dev/null +++ b/.vscode/ltex.dictionary.en-US.txt @@ -0,0 +1 @@ +LLMs diff --git a/7-building-chat-applications/README.md b/7-building-chat-applications/README.md index ad8f944ad..a22cf1979 100644 --- a/7-building-chat-applications/README.md +++ b/7-building-chat-applications/README.md @@ -73,6 +73,16 @@ General UX principles apply to chat applications, but here's some additional con One such example of personalization is the "Custom instructions" settings in OpenAI's ChatGPT ![IMAGE]() +#### Microsoft's System Message Framework for Large Language Models + +[Microsoft has provided guidance](https://learn.microsoft.com/azure/ai-services/openai/concepts/system-message#define-the-models-output-format) for writing effective system messages when generating responses from LLMs broken down into 4 areas: + +1. Defining who the model is for, as well as its capabilities and limitations. +2. Defining the model's output format. +3. Providing specific examples that demonstrate intended behavior of the model. +4. Providing additional behavioral guardrails. + + ### Accessibility Whether a user has visual, auditory, motor, or cognitive impairments, a well-designed chat application should be usable by all. The following list breaks down specific features aimed at enhancing accessibility for various user impairments. @@ -91,7 +101,7 @@ Fine-tuning is often considered when a pre-trained model falls short in a specia ## Considerations for a High Quality AI-Driven Chat Experience -Below are some considerations for +This section outlines the criteria for "high-quality" chat applications, which include the capture of actionable metrics and adherence to a framework that responsibly leverages AI technology. ### Key Metrics @@ -128,8 +138,13 @@ Microsoft's approach to Responsible AI has identified six principles that should -References +## References + + +- [System message framework and template recommendations for Large Language Models (LLMs)](https://learn.microsoft.com/azure/ai-services/openai/concepts/system-message) + +- [Learn how to work with the GPT-35-Turbo and GPT-4 models](https://learn.microsoft.com/azure/ai-services/openai/how-to/chatgpt?pivots=programming-language-chat-completions) -[Fine-Tuning language models from human preferences](https://arxiv.org/pdf/1909.08593.pdf) +- [Fine-Tuning language models from human preferences](https://arxiv.org/pdf/1909.08593.pdf) -[OpenAI Fine Tuning](https://platform.openai.com/docs/guides/fine-tuning/when-to-use-fine-tuning) \ No newline at end of file +- [OpenAI Fine-Tuning](https://platform.openai.com/docs/guides/fine-tuning/when-to-use-fine-tuning) diff --git a/7-building-chat-applications/notebook.ipynb b/7-building-chat-applications/notebook.ipynb index 7711255a2..2be78efb3 100644 --- a/7-building-chat-applications/notebook.ipynb +++ b/7-building-chat-applications/notebook.ipynb @@ -1,5 +1,12 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 7: Building Chat Applications" + ] + }, { "cell_type": "code", "execution_count": null, @@ -8,16 +15,11 @@ "source": [ "import os\n", "import openai\n", - "\n", "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n", "\n", + "\n", "chat_completion = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", messages=[{\"role\": \"user\", \"content\": \"Suggest two titles for a instructional lesson on chat applications for generative AI.\"}])" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] } ], "metadata": { From c1616114cb9441d0e4042c39d5499cc657dbc674 Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 17 Oct 2023 02:49:18 +0000 Subject: [PATCH 14/15] custom setting images --- 7-building-chat-applications/README.md | 9 ++++++++- .../img/custom_instructions.png | Bin 0 -> 53659 bytes .../img/lesson_plan_prompt.png | Bin 0 -> 43024 bytes 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 7-building-chat-applications/img/custom_instructions.png create mode 100644 7-building-chat-applications/img/lesson_plan_prompt.png diff --git a/7-building-chat-applications/README.md b/7-building-chat-applications/README.md index a22cf1979..2cf6f4eff 100644 --- a/7-building-chat-applications/README.md +++ b/7-building-chat-applications/README.md @@ -71,7 +71,14 @@ General UX principles apply to chat applications, but here's some additional con - **Context retention**: Advanced generative AI models have the ability to remember context within a conversation, which can be a necessary asset to the user experience. Giving users the ability to control and manage context improves the user experience, but introduces the risk of retaining sensitive user information. Considerations for how long this information is stored, such as introducing a retention policy, can balance the need for context against privacy. - **Personalization**: With the ability to learn and adapt, AI models offer an individualized experience for a user. Tailoring the user experience through features like user profiles not only makes the user feel understood, but it also helps their pursuit in finding specific answers, creating a more efficient and satisfying interaction. -One such example of personalization is the "Custom instructions" settings in OpenAI's ChatGPT ![IMAGE]() +One such example of personalization is the "Custom instructions" settings in OpenAI's ChatGPT. It allows you to provide information about yourself that may be important context for your prompts. Here's an example of a custom instruction. + +![Custom Instructions Settings in ChatGPT](img/custom_instructions.png) + +This "profile" prompts ChatGPT to create a lesson plan on linked lists. Notice that ChatGPT takes into account that the user may want a more in depth lesson plan based on her experience. + +![A prompt in ChatGPT for a lesson plan about linked lists](img/lesson_plan_prompt.png) + #### Microsoft's System Message Framework for Large Language Models diff --git a/7-building-chat-applications/img/custom_instructions.png b/7-building-chat-applications/img/custom_instructions.png new file mode 100644 index 0000000000000000000000000000000000000000..e03e196f7c2f2a531650a2d5438c094432619841 GIT binary patch literal 53659 zcmcG#cT`i`*Y_JyEFhqVrXc2cJW2aG&(?x%>#_QAU--y0S+%50vv!g5GedFM-PaPzBj}x!2d5f ztMI=<{*t>V@>eMEJ5uD|GueAG|F`Ed5)c2Y$A9{tp4&vS2I;tiK*POSk5!CAY*$H_ zewg?lpKM~YvQgKCZdqvmAt*MU&X<@4eB@edIaO@t+yC8h1V=w=ZKI0vkwHQ0r?Q)WfwOC(_R4njEnOwMh zt+VIM>Em26zkPV=^bcj$Pk)^r|BSc4dV0K~)^PFk`0AGVxzpq4D*XuaXVlDIpv{O`Cl)^y=^pP6vD}HIt$91=1mOOXVxpF{ z^ElgzBzL5jd>am5*Q9o)5K_}-ze(Sl@hO0AIkd8YK!p%j!GVo-QT0(P`wP!&(Hhr<`69Ul9K9^}l;5o`Qo%k|BL4|@ft_@2C2BjLOea{L} zD_4QOChD>3-QNLgD(om+J^OE;%C`K||A#w05+v!w$-+gWUIRXsE&BK4eP*xIK>;O! z|6h)Z&^3|zuh7#A@~6K9N$PMiaY=B0m^qAr-}P59SEIkcxjsEt zE!=0}ehipf#GR}-0q_}D;>uABuNwz2qXO(_T*C$~b5Y?j)~DyDZ?cjEM9#Q&4FGqY z0vgg&9&ki|sls9Ot4x6FzAAZpuCVIKb&*Weim$`JH|l(Fh4Bt3NpIrJ+4%DIuz9^d zkOI!vNf8%vyyx+4ZT5QU(ABej&lUH7 z+XSD`gWK;s<#I^?fq0r!KNbIC`^)^?aC_-RE~+NG2*W&O#F2k5mbB|jKESn+E`Ylz zwzNGok-s3~m*R2AJ23kAV2v2&N$6N7p()aMSEIcNGrJD{{C0BpBbQ7t8_2bN^g^QQ z$BTuV=FJowA!P^(Z%*Or&Y_?G7}2IF-lmDB(^)bq3PQ&f4we+WKE>=sVrEZ{_cAuN zBWHW|NVy%&59lZUeDXm-Hk|?fC-g0)>{;-OtaBjOS9ktc#th#z&t&RLAc{|`>yFU`+U|cXm zC)P(EI31cAV&>ku6!?&jciTwNL)Ps<29Tujxo8lqeEidMwJMVv4}L9XGlZNxn+;{z z8xZy<305Tg9nu>LTe^QFtpH0~4$i^yU@WH$Zp5dLq@Z2Y4ZA`lqY@b>9!s~6iRrU}R9ba<`@tq;s z&$!arcfy)cX1X+%;7z8Jc-(837rsY+qc7AN5m%>Aw&rX@9Ljm+cMaP@HeI|(frQSN zXQNgV&ekL{sAtnh{TXxekLj5dlHEy=O{;jp0?Szh}xlu zdhok>;p>el;q;wJVnqS;XV@-r1dFu)#1M=@IFfKS$c|$=+rT*_<)F<$@p!)^d)BP; z8UQTtuUU3`r-McR|ei;^TWlWNtku&2Ab zyf*42EVHwzN&NLKxOB)Jm`!kJ0ezc0`%hO#@R2*O3l=(JBem`q{OetBq+*=n$&tU( zNwWOz0KscQto&P)0{Me<)Eho#J%t@TB^{o_y_44jzrl5{(YmOi)w#VUH8VW)FwZ7S zwA1BFHzhxNx7|)J-Hnrt_U+!@N{u*DaF6_s4_Kg{01K2nm5@d=G}*ryaRgzwDGnO` zZL*r(XEO3x^<^|H`xtnQec|1^Zb7anB|0QG=iY2so9jr=YU(J5NA6C}NVf8tGWfZu;ZazdklC_nP<6|((xZFLwRLp40jbr7+Y-yN z6O$amk;R}oy@Cyzi>_6x^&s2R8sd?7rczmQoEod_INQ@+H!dam_U)7Fh~>L^)(Nb6 zL|yqvrL+yJ7YPf8tIe=bnVI&IlXD=+M>WNl&w*;xs^3F5E&EJ@<5s79B~EC4+)s%= z`!Wt==hq0{tM0j|;{*3#f@f6lA-ExncXRMIv6j0a_-Ph&*%_O^#(MqHN0~^@iKgWa z*$JWb1~qXR`;UdsqMPEw50?2!;_<9ON(Y-~*4Lwm8Q);u#ANyP)q@?v7}mu&Ett+S z*%^C&mEx7XZDv)5g%N76yT!OV*KfDhc1y1Q z!##95TJy%H1p4S*KU*+$q5J2}2-i2r{h!Rl56>#_PbLKNLq;1Fbxeh?SL+;e4;C2q z$GE*5tFHH2R?0~JJ4I*FMR975#^@qj4jw&tx_) zcxJbtdJ{5Mo^)b+>4b*mMj6$O?xE4h!}(Y56z_Ha+)9*C`F?TlGkc0t#aqfuH&PE< ztjDTD<)NSL@j{(!_mi`Q8`Z7HL9Kc7T}`W<=5LWGAR)Y+58fpymchT`fr9$ zb#ITNPuGJL=b_x$go$zJ#5kzjY0yBfTqo+w1se^F9b(3`&a&fEY}5jDcdRJ;&rQc* zJcPfa85&+4uEgF@z6lIeJK%@vI_|bY0!eP}ZM%3%dy1mvulkOKYT|*hQAAIr5b%7g9|#Yf7D7#Z*+CQ@0%2ElTVIijKwJmfsru{F&uTZz`z}L+D4Y&L z9e8^RqJ~6U)UbI(+wk={yWHZ!#?;IS(MXKJ65w9_&~y^S>*Gf{Q9MO<)FznpaBm&C z(O%cKo`0!0c~FlSHf9^ESI=Zrp}3O#Xk~GoKjFqNU4^y3 zgC}iHu#;C-^xm(cPgJI>gl@woy}N0q3n3QoE@{_DsGJPAT#^r3{UwGB$UXd)a-o9N zyi9Qm-P*4@?hc=j%prLZ_#*YMndFg%0w-;-Yu#p#$WquK!uk(1`T&390Om>qw!@!#1wz9YQRB|%o$#P*Z;3!tn0@NQkG z{=u4eq&znWlP5nZbJb(AzFU6l)htTGNM-e%X0i_uf^ACKhRxI!U6Wk8BIDa5y1q)L z&v-U`ieI-ofz9Vf9n0DYS8#Xyb0+s6g5@)OSN`4#I#L45BJH}Uaajqsm{qQD^t^rK9|DX*)|g@;) z?3;BWdQ&{A0|*57KGKayaopCc($g=Dz}v*Y$u-pV*#t0j$u_Ecp{|Na$eVVUm#zFm z?&R+GR9mm&AL`zV##aK#-6`#8Vnj_8PUq!vGZyzqseOB}?3j8%X=$-yq@ZV*9Ncxd zE*}|&+Uq7AMFbO}a9*F`PrBkZp~p0rNF7_X!bLFBW2CPRfwNS+(z&iDbI>Kf(ZzgJ zaD9aOR(uFHU!jA?Js({N{9q@)*3yg>*Fh5Yg7unLy{Ly?P)hZ`s~3kca$vYY&|hj~$smEEF-1x#0>{Bc$58*N8@Y-zr8Vtd$S zNEZ{4$?ceYl9Rp{K~Q5OZ2(TeRVMOa?6{1-I4ju|?`xK_6IG*kyp?t7c;gU~8$n0I z7QY{FO2-uq6n8qXCFvL*=_=y!Z)fn}mrj`3I^ z>bUUPw7f;oKTL}U2Lr?dddZQpBZ4}lp7>EoP8`v6!{3OGTwC?L~z3_^jYh(~R9!GM?9_)beF{^9}xCG&>LAK0irL>OHE(mtQacvk&i&VaGT z+Z$|YUIm(`cu4=1Men5iKOl*5MRSpZ1zsR~cYgEWkLbHGu>VmO@jpyLs^siH4s%X# zyv&F-{rl}s(``3J(|xR-Qs@{PFsrU&`1;9d6O&~tlU*abwWp|~Pv6Es%4!B9_L~_U zWAuB#Q!W%+?act(1@&QkR+9loJ&+_B@8KS?i-Vrk+RgcV-<|s?Bc=j~HYPtT(FAt?%r_@60%5tzKCSTO$r4 zAY*t^=;W`}RD5HhQCwsxb;&WMBVQiyo9(}gS5pTX7~TfVJby~g+dEWhcj#rU`FgA+ z^c86D-mTNlDCNlSjs5d1lP!}rGKw-D zA3v&0myH+d+sLxa-@qME<}@@S+c&@D5O)=Vw+mRbMngY!7+Q3y`0PxWbpX-fV!fU> zn%>H*aFDCvyUG9(f*VMwFGv!)9^O3VjLqQWF!SsHH}L6@t|>(X(XKWAKu@q6gnB zUwEXriTry>yC)E)Hlep0UAFf7*4Hr~7i#VrjyQTM z-aQ4(?3bi#_lXsYuX@?`Wd7p#9oPTPd~LbQ%nrjUC}PQOt8Hj0`7FI6Gbk`_>!EgN z;c`Y>P_0h;@)x3CPv9$5!r|vFeF`%+cFEVBdZ%n~G_^(X5*EAEaW{zgxSzkyh>Y;Q z!1t)3)_+Q%F37{xqSZEVHcZkkL~&}9lLXbN*b(LnCP$iiMaCuf3k)v$6sWhUL!iH3 z9?~CpSQpJ_;n&Hzq0Xye9P3JvDNIyB$VpshAZ4MVaXD>k@XK^#u~?XGZotpijM$7) zr&pfHEknqwh0vnSk*>?sj|+{yv%3k0cObS}{%;}IwW!=yZ5#s^M*KW-<#Y~*d)bhr z!`(sTP!PT=4eLny@3|Xio642-kGN&4G-KLZ$7=0n%Z@gZGARZ-OF0>*X(UDcczJ=8dMh^aOw_NhbEmG2k`PEidD=FM)W|lqxP~#F z$HBo)j16u~HDGV4wQR{{oHbAS7uTX&ETU$Nr48A`nN~rYN(%;^^0l6bh(9eS$^Q z{GI|P#2TF}A^LPIu1E6mB)_)a;!qy_VVx18k3U)NmRZBZksQ2dv!Wo#Z6x}!ZTQ;G z`^ARVu_23*2Z0hRUvj**`ZYYa9%<9+0c*gY-*G1l$ew7=zw{%Rau#aX4J#b~vaiW$&<`ta`LPPDO}|ndBp~wGjmGqhqcHuC@;;^koV6x> zFjF*Gq98BZ9q*{rsvXPZyi{{78 z{7Z~G8Z@7QZYbGr^HJ8>Q2^2iWJ6=JS##tBk;Vh^095TXtuR%>NV%Qsj^~ z4ODwPhCd$ZbiwB5O~N;4J0-3AGdKrIDC}jLlm=Rh7azBr;_3$$_Y9MqTHc#nrMNgR z*graN5YI><2diUx?iq`ajPPU5!P_N~4p^ovOK8y=PL^FL{lqfM6})or$3ogD*NpKi z!$O{gDzC2sA4fU^k}ggwAIJzg&d7yV#YM`W9$7=MetWGPY99JOZ^#jV6rr$#YkNrV!2db|E) zFRe~3g_6EaveiPruZ34S4Q5uwjHW_=nLIIGQ|1|o#<2}@a4?H%5^R?jG&&_vhwDne z&zP9o8==g{9x*qKTZ<3uhT4plb(yI=2_E;faaem|-14pYAMxtOo+g6^FT`1#$zS>$ zH3;46`OC5OsjWIBAd?ps-WLz7T?sM#*k}aLJL=qMr;3r`3T|X5lOB=H0cq z)CB{c^vvgo0f$>1t?AN?J92gzDV^~GA0|R=yz;Y3>KE-kXliMTDnXFFAA8cPC)ym1 z4#$Ut^RRO8v9J?5TSWfu@>oCE#m&%da8xI&)Ra9=pgYh;BYo>Zn8cGoZot^DmuwT- zUH!2F^JQBBHT71wCoZz{Al3ur58aw~j;I zJr4S&U1tDfra1^wXE2$2~9s=RyLKy zkOV(B(X!fdCe>*DgUzn8r#u&huJNWSEET+7(Jz}C#Oc#XKq$^8Rw(qHV|@P$2i=Y={WJD zP&ylbu1^@{QdjwqpJ8}wVm-w2mT7Ry&Rl*blaP?U zaOEG2CZ^4mV0XGJcL~^fV#Ykph_hW1EhijN^}8x2M~Y^6OEu2rX;h1HIoP9nR^qj& zga@>I(ew>T)(pBlgw79agiVz?dsrrWYPK}gg0x=R+Eo6oEW|Py4sbKta4kVTFfa#> z#AL#T1=+AlCwtSkq-c^JQx1yz0wz~lc>ZvQUT4|&2v^(v?y}#NHd?kV4siFq$plx+ zfE(2~{>#>D*BW{Mh?^of_C^Sok2hAg2)r__DF@N8R~hA8sXgf>|Ui|QfFZ{-O) zD7$+XnOL?w;*9R)Wt6jBH5UuaEtgGL!xve8@R5HyA1e8$Q77|6r8-=zYzSTXJT(1p z%vM^fymoJ~j9dDNsjxSVW9FQpVinhP{$L_g1tPMFYDfv2jk5?PRBZ-H2rS=7ViiWb z#W&n79Plr>3+to>U?%2>g(?>o^X#~eguEYzI#F8ZjQU%=^l`ggT%ygxorqOcTA?I3 z@YmH)Y?mddhWyvaqqzD$Ac-k6IG@-lQ7`{%)+UgCujY3(vPvuXE3?6s;zAXr;uV|~ zybiA32)1BuVd9kDo~vH2`{5DC&Dl` zh~u9OWR+&=x*`Ml?L@lW9@KKnl~#Qk#(>tIVjKx2Ip<7M#|~Q95NxYSF+AlhmG&+e zM7jp&Z-5TPt-co)7ZhcR4}5Db=RtVN_^lOe@+VtCqe$s^qYzU>gy{3#FR^(kT8zY{ z#yZO*Ap0J>U}CzD>*6U7gz)hBo4xHG#R}um18lr--gDe^-?!w7*2uo(F~h}%`L=%u z`a;;9Dk|{{96&9o^FptORQUGr=hrUOHBZsFO@va4M@7i3R)eiM0$ME_ftRN`P2|D2 z0q%hc)y4Tl@#8`CW3923_TiSGW-*9e4elwWVOs+`vefW=urf(CR5oAR&(i^a?T>&O!GFd7B|>)idZ_Ec5{8%Y-5dYUot;PnQ9XFF}g^& ziF{W0Lfw;V6erE`h}z!;@b7u+2}KSgBuCC-6M-tvmzP`zRx$75Vh|HrXNI--ll`*n z?n`qU7x^~uN=hzz9CQY5tW{TU*9jd~!FTW29sl?R0TmXxrb{IX=~u8K%I>=IwYT&qmq-PKT5lzM6+p)ev*4J5(lubnG_L!h#RF-V6~>i?T8 z0k_(@vs=K6MSJOOLRpG*FaDq{F;DGSe~e}xi-*M&GGP5JKGyY@_F#4-)#@EK5xG9K;? z5SO9mk(Q0Luyu+GInd6#?VUgQE)GzmT(ygw!$mBswJqeG_?dV|zUMO+%zls(^-c#v z@c;P+qO5w#qhn=Cw4SCsx7yc`&T zKC|;01Z#?8o)NR`{mT3NlxkEOog01>@%vMb7p+OWIg<9T*W?c)VHVC zk#rvyVo*+6nn?ZMnUuL8;b+YM-t@a?k?TJ;0J=_txBrK4ae1pUM)#aPkn)(i$VCuB z|6o#sAGeP-DTM8rx=OE@UuexUNci159A9Z z;UqoyutOn|Z8!NUfHl<>)&i$c+pF1j0u^iDP(`Y91MyNdjcagip!ogNYY#=YUKDNJ zCaq34(|=Ryc?)=h0E$6#01XctG*3NwL>rfEo3uSks;bD#=V;``EA4-zA0y*)R#v#y4=C_K9hbQl;!TCH{f*lim-TAzw7@heJM)y z1Gp2!ld-!-=n&70m<5X9X{%R2u3a4Zg4Z6X#b4fiX?HE)x{kaT(WENo2BYRFt!UL# zaX=8vYx`xddvuy!`pwT~&LFBSHq3Su?Ip@$)i=W1ZwKErK=dN}p zIMehg5>qh?yZc>j#3$!&u96VMW~G==vaLZK9sL8tFDmg}Q?xDBhhB6~bmjf1H}&qC zBL>V@A7C3aebRvgN`FOa3H$SI=7u*p1~ybFO`CWxQE?%RUvdBE#(usGzO?T!Bz}9u zQMs7rdN?pT)_sTrG+NR@?EJPAue^W~I}J1xIUiqj0{oM|Fv0@`KD;7qqAX>tlM9ow z6`Kxt=CY2|CEx<;^tdlport$SvIke9JKy|*So8c z006wBy#`v1)N2+&E$lQ}E|f5Q*C%pC|{9 zfcx8lWNE&2ErwZqYs^w^9D@9u>DZ#1L=MeTT>s1-H9zJ8F{YASQRb+?HN2GgSH!#k z$sOL^3g#Lr*>uU~JpeWx~y{@7*WI7wXO6`9QddxF%G&(LT3}0@NduRGl9; zLw{W&!@*(JLYtITMe`YR`t+C2)wWEF`>LsM`4OD>@T!-6m7Sf;Bx;KcJuTkne z(r*_F#OJdogY(^#@?O}Dh>dXM=TW#bBnmyxI{ARA z=F*=ofB_15Ln4c)u1L6}`Z6uz+aJMHOxjUX?;JmjjL%xk4=xWs?%<~13miB!(o?u) zwlo$5ITV2-NO8e_(Olz?dj7Q>a@@uJ zCA;+R+0A}~!&Zp&1*7|#|OXOd5xCJ`wx!oj3t{H34q_H%Y9KRgGv;?u~CykZ`Hd`iiJYR z=#!aspr{lSbxgH0^cEM|XvQk;s7w{BClVJ6#5a36R;xm*8S0lMocA4IKx(%fJv}<3wmBGyMle6VK4+m#<}wiU^(Q}Fy1jJSqT_2Os*z;;ZiU+>@mgyZ( z)>`?JQt(0e@rqF#%2hGGm@*n%_mm=HW*$9JabVJbU8Nq^I|j(ES67_X1yv9O}i7kMzh{ zK+_YH!Z#_0;+VQS;#)qa6Z+Rc&3(uE04f^7HD-2ZVF++KCQZchxk@4%E^+v;4m(4Z z_v??XZatxuMKCA4M!A2OzGw8xJ40}IxxO{iGY`haW#rn?3LhO+v~6E10irmH8D3j3 z;D&WnFGi6(6GmBEP36&cx%O3{PH4Es-i5Kdr8v}QuvGpCYWi{#HWx>8C8V`<4_s)Z zm-D3gM49`Wk8GJ-Ou0E}`c?1wnSYYyMfH}`3`%tO`dwrfjd9 z9Bc(QfS1w~MRShZfDdk(YgYkIvBUORM}Np2Ty_wchf(j8;6O~y2G7Q2b@*%8rOKnE z&|fSn+>Oo8+SO|xIsdKY&tj5VA4tGFMp_h;^A7N~;<>8Uf$>q|~vK=cOhihMjx_P3$ z^*Ki9=WE~&$0 z@?j*;LrTKP^Rc;p)!)d(+MdT9N=K%`g)Nyzpw_Opxb07d@Bs8kiUqv;;DWRe@^qS8!4xvSBu?+7x0gS^K%21n6 zxNkSb_-DLoBUQuAzn)(!{H;4Z!`!9gP`|%8S*s4~^}KSqA{io&%GlMe-oEcOYO5A_ zB;cAdBT@xlQ)f{iRM=x|x1Nu~XL-b#KsygI8)VBAC%n(tZQqe_xL4_`5IiL)gQg3z z)I>JJv>08-DzINg<*l71>t+vnm$yT=;CkQc2%Y!#o1CheK@W(TpVXkRtQl1rhgXTH zQfKXRLgDPeO{c=pzmmeXW=Buf zx);TXb6#4|c-A8B4yMM*7{+wl;g0+&x@36J5X&1l-xoQGOAM|7eFClSdiyohuW`rKU$*hWWQZaD-@#%08SE9EgtOH@n zi%UN1+1z^T;Cr!wijK@hbHt8_e~5-Rh!#d})@Ra(Dj)J_7H6l)p_?yv+WUIAs z0;|!Axq+u^5j|};M5Jsg)F{heK?~;Cl^dvWmZUFxs2>U)et9_G-Jn&#RG2AN14;Jm z4-V;CK@PqA{XtywPLzZy1YQKwRYAgHgdZA*{r#w5%*#7OLAkfIJZpp-EujC1_RA4$(+yNJVvAGldv6MVcp@|0sW zo2zUu8zSMzNcwvq)_(}~k-Jn9F2@K9yZ*Sv=W1Ec>zUT;L&BZ0;86lg$+8iO%RSz0 zuwlOXW8l2WoIj&mq??^NwTS`;QY0*Zx;nQJ8)L_})>Qjnwrcj4U`2R1 z$H$NAjFVzo?HIq6I{O)DH;;N@hpV*mySu*3FkR2nAk;xtv(>fm-n*^Z@~wffy)%D8 z#=d9E!|kamb!Jp|rRi;<@9qkgb~Z!&?pxP9aj;!$-86445zK7Y!T9m0PZC>(oT;QO zWaMaM9ujhgL*9GE4|pH^-&WXEkUr|8?lAtGUsdy@>;)e>{Dkt}|M?gV4v66AgCih$ z4oqt&_+#gPTIi7aBCeJioWdhTieq?VSe#TiuIg@z@>ONoYSwG_S{9O+LQPpM-`&Fv zCRftTXO---bIA2wqnSEK*@W$1c!j9A3AMOgpoSGxqWkE!d}%!WdNiIR+GMF&>8xQD z!}f|jp-9!rhWU-MV9i|D>@`ib-!pfR9V-q|gS&loPXv~XfsGXCGs@J_NWx5Z)K02C ziyM~#e0#zGO4s^+wY?s`1+w8+8d4PB{tC{MC@BNae|K@g4D3H0iyxP%!(+kIpr9HAG6+;>$ zj~000G_kPDpp1WU%CIs9x_n2*X@FxASQaMhZIG+_i*kW0zkq!MHXAlU-&lR?Cx^PN zbENA?fTtZ|RWU05xCxYw+p&s=PEKWOdTGF{9Zy3bcIUp?5BQ7-9fXOWd&?o&`L9H3a9C)PRCve-6nRYa-FBpBC+ z*T8m3B`HLkchs-RvGKdeDdT`O`~)e8B8uXAQm`UExxFlLZ8J#=U?INbH>d&B8-3r8z0&cW_;?ni|! zr4T7_^m5RQlb+1(fRa=HIJj=^5J?{<0a5$(Ef#W`o{oR`n$&P!7=C*CR!ssERerst z`)~pdo!iS&oB(realSqIuXKejxxyuWOtg{mdS^ z_T~nPns3$Vk!{srZxD1*X!%GfcQI^dWgbm2qR$%wdJyIRO%GCM3YoMyY;Pk&2?_^O zjwri>owXeIrpkr44lLUAO>*L{zbN(hsvc&T%mbe^2M285F9 zGnNGHz;#LEy9_BQ+HPU)gUu}o%Za)*PVs{iU1JprHVxNZ+Pp|d4?IF0n#WzkJmufw z9OuU4LU|W-iq;x8|4sGZ`crKqCw7Pq6#e%*st8EaR10(d;urB zmk|o67KyXcQ}&TS?j#xR#sq*Rb~Ks%?OamjBW4br79|!b^*jleWVnv8@^i$KYTt34 zeBGSjt=>tSwz}|zY?!~v_%nnjAu!Uv@61`&-7|}Ta%XFfBi%Y|xev%Ct?2uwR0B{% zYiLEm(hf;bs6pwT5!M z4%g5WKsy=I7EXquqKNG^N79y-2+@(~O#oo{Q5P_S?qTvFzi&a2#=Ygsz1un;?u`H& z8>$#%KN*T7S!TA*4+DtENf4f4>&{x;W%NCb_dI5=Y;oojS@DV}ay9`XB56erX&0TQVx8S_ zFl&l5$uLS#C?W&K|E#UkRjyX+T@qUxruFHdKr7t<(%P3vf|I>a7T-U=o?HN=BzjV^ z%}#$yDJ7OGKzKyObMF$Nk(2HIngtd}GU>QwxesGPMV zdSPUD>Vap+7o2R+syg&Kk2k?e1Or=W8a&1#ye0-Vntf2u`%}|-;PX=t0|(BQ_`)WK z_yrMNr4g^h)ZWy!r9X!>M6^Wc4Nz49RggsBEQ)=Ho7Y>~qwOV}4#;h}fkn>^ATMC_ zTrvTfncXuRX>@ZaxvB`{J<~Nw0_e&nL{FYn{fF(|`(5{(f`bR zj;z1)u2qt2l;xPq_utstD;-Y;H+0 z#x=K$*0N(nt@0HrI;Nd-`WOrtd$kkdh4ZxGtxu&qV2aP|41Fw;?DTi7JXL-~w9X5iaEn?08gr#xI}dg9>kQfa z=|R>ujjeXZ0JXLUZI22^VV=N3eu&Fv-W4I&YGZ1Qk$wP$slJ{?GcaZsCe<}BSm-G! z^s<1VAH+dNG;Eab2KwYBWum5{z*Z6q$Z_(KMnG6ny6}9YNBK$IZoWbr71Je&y_1#f zPd=Ox>j-UOrMpu4|IBs%nyLb%&5CKTO!b_%oP=Y6Iwd04Q!{hWRZhtZH;?>f0$0)$ zqtZ2Y+}oMJ+%}Tjcd;>EtQfG~ zW#Ppmm51;*Y`IZqMq{sUo04_W_B6UB?-V1pCW9&2sg8$_(|FdAesFfC-*N#&NrG94 zV|f&9Yu;C6X43?#S@~+9|DKQ!w7^(W;_XcL@a0 zM>eb7y#PPGwL5l9-vi_ph|b~AE4F5;2-)Nw&ta6QXr9;SC7DmV-K|e)&dVaLHqy2f z#HL(9JS*SN{u_;D07AZ->zA zf2LS*!j3nL)c|`tX!<#Gn|iqs=q^(}$GxhKs`@;M0v+zRK+ZbV7>hgvo=)fH9bWzY1hHhWrY|vbVbHehX#+HMLCM96E7p7_=kvxF21CHfV|_FtT1%ppV?hkOZNxW5v{WWQEL|r z6a}Kq^s~R5O5#{$Upx^LxUizu%)-^XU}pMf6LLAPZRra;w_6~z zPiTGZ##XHJ<&9_5lepNZlS7l>=`yp$*1mjigO?JboHOY|zq8@r(l)3CXD_U8OtPOR zXdEh^F->@e{~M-h89!RAiWHR6F;A5Q)?l8jzfWxvwgreO!Q3U5MXq6iV=C0{50~zy zrOSyuliYA?&T9p~;Zu{l5FlorCRO&d|JP9)d1o=%t^M(*#HIF;j^DEh%3`57RG=l9#r*3*GC22uB?BvHYqs?w(-xv2A$QQ zmAhw;R&FnwiwCV~8LsJ7($8FAYoiA(wsm$bC*A;kLoJ8gDudo`v1ONb zVV&5uR(7bKmV5EL2&GkYYD}i#fx{{n4nW^*pO^fo?CgxA5IdUT4$YPb!)-z-OwE1W zHP7wi`^=)9s`x=zW_;d+BF{t^DTwfQ@SKheZ4;)6$c?M~qWdyMiqIl<5RqSL_wqwN z*4Q(5VFv-7wzm|gy=IC^ps1=;!19Hb#{A>7W6MlJA-WG|L%<*L58Zq4{1V+UpZ+bf zx#TfC^L%Q4+v07xcndsQ`)79FxjoWe>dDKAloqM`V|=7x|7_JLbA6LpyEq>b#LQtD zcELj8W}whGXGx6ewr8a+%|mYWIGeU4aRFC_*^n}|;P>uojByn2_Gyy; z#@S=twoDft?lHqN>PjBkE+6WBWaIMlj2txLO0Dkp5tb+8%hZGI>h9eEEJQI+<)!xM z_Y&pqDM<}N2~3k&pw_;o$LXP6<+!gyPge~l=*?OJ;4@<^`6zPylDe3w7vq&<^bW@} zjeI9^36fYyMFG2TE*E}d{#=+w|LbHUMtw_o46G$M?Ww1cCr5Sn7_GDgO2xcsg0thJ zG86E+WoB`Ozt5}RS>89cU5bx)%dTZFld7$&X2Z`IP8KY&TtnU!{wCsWO@Wr5jnC3JHBFte#VKXI?nG>{wiXx40V12 z@k)vPFWhH08)$ysdtr@<_F{YB!sq!qQO!6>bu6xjh;R&~K7_UH!F)^r=BP7;HJ z&P~KCoD|0(GfUP+cQXcIavI19di=LkhOFno>uIhx8CM`x3#BII$`w54g{ST+B$yUx zd%83_KIv~ymf3Na6V6@99qA~Uv+D2o;$C3&(oDtCFxv82QK9r}&Q6oqV*kfBc;vUT z)+*Hau3VA-C_|sb&_kJEl2+$y`<@?CYXPQIF5J=UA&ZIgn(j3#YE_h!EiFVN@VZXE zAf;ZS!gJk$eSsx@>3Fd`cOEZF8}CDHyZe36+p7-+odffjpJ*apRTnX*XibPzX&4}& zTpp!GKURRfhnp`Gr4o$mEE@4b6V4DDT)>3wbM`umasMEu{MxGdFbX0N*n7P5(s|TM z9)UWgg&2tEO~ydA1lB>uzFUl6!-m8=FQjDXNx(U^M;#D=*6s$;yZ`ZnLOB<_-e<-RpXoB}F zSjv8uWMn3kq#SwsbjCvHA>7Oj0gGk`RkwqZ9<&>;day^YWq-?iChrjj+bN>ZfSY5F ziy%ci?yP4C6H5Y%ytI7FBcX^&Y2gEFgGzm!_vP>xXZl9}U{T$+=`D_XrX`V*PaDC+ zsE+*;un5&E*ROoY%`JVH;r`&t)T9YGwz!VkIl}3MTCi0)<0m=qP%8XWZK%4VzytPm-TrY;^xoX$mzfPbi^9Eo_zd zs%&)-VmEg)&_#tGYcHaGEO4JXUpyX2*0G4nDDQEIi&TZ@NEk0?Gc*j!3vKZH^}s)o zCHFG3kk7NXOyTc#GvJc21t4np#;l$`)AC5C7cGy5AjKTc`?Kvu#9H@;iIx1S5+~#J zMccorzaSgG%g1^%Mj)cfyGNqrj1{}hn=G-~$ml@-H*?e}-x5smI-AV?>83L{c}>@9 zK6oDHOpfm8(6+s_L_`G3)L-_aLJ?{^Sv0hl+un0^@H|q3y^O!;Gb(u|Wc2++Fk4W^ z13@KqAypd}*lg=@K$S!4AA8!7zlr%V22YY%*hJ#HcKc)n{dQi+S7<`b5Elr+PrSB< z7C#JRe~n*N^iGq#MZlcKXv+dt_(UV#0c*Q43wqE>$7Q1(bgW&rS&(s^bBIZf9ml!u#8*r)UvI z-}CHj5$_C419v*Eu5Km-lV}~Wb^VytD4fzB_0a8woSESp<~Zwnrq7j!CtrN3#8=My zMJ&qj^7l(rCC2(0IsGVgXYH>r9{9QZNydZkp7HJjW65gWIl(9ESPEr6*0SV3QkozS z@oc>zzrUESG#FzPK{88*=+&+jKDsVq&wb;27(A~0a)Y;a2(MXW!?UhRQcvNyWJGom zW|*a7(3DV|hmAw~x5iw8-oYHP95C+F1Xw0#ds(9Y$O z!}QmNPk&%Sut1NJ#h~MK2VUDB#q}(GOdhH%#WQcLV>x)sXkIG)!|ol*~mQEq`?Edu{h5tgo1xlcVKr zwn4#jlqbSo?0$$oM;{_6;v}1*a+;z_MceqTvl8q}7Nxj6zRfBJt3*rL-?HN37!+Om z{=pfS?*W|gIYf7@z`~Pwv=_Zwn4R5io3i=iox#Clp41+^1W z4JZcb-~aFKM68IYg-Ta#S$VSOu4AX{gd1Sp#Zk|zUQXsMbum4FDzOGW>tFMpnCm52 zT3s{uC6Y`0;2ISCe$?WNP+K5HbuP2?>f{$wn~(Pfd@R3#uBuace00*4;tAMZRvfVF z&^Mp!FE9tPky7QPxjuY!USXj}gXhpSnZIi+Wwu-}!{r{Hqp-U&nI0lRIyXa}yg17@ zovr0R0>mx_bwICGs?5X5{9bBI_M<+-L+}$I#sT#`$pPi*$L|_d&JAt8S_9XafC#&VaQ(aZ^F#OrOrrG0jdR>mi^2mXHm3kSw|CJY z)}DA1mLdzC9cE$+{K9dQ^ zfW+Jc6s2-*cQWL}$;CF`FH6qf^c-C}`rf9n-2B4v%e#;A#$0z-y|y}K zmUgYxh$0*x5&@3o*z)pqz^L-sOFybK=ENb050(W+fC@ysaMEMAkjJT3NbEb=E=9h9 znyFT`yHLA3o44;tIf=2+JBN6~BnsWi%?RClifpi6Na%^NwSeS<`|IS|RPEg7y+<1C ziYR`hr8{aEpGsl6OM}y;K`y5NL3C9dvH66{0vz*U{ z;}*B()UGEb@|L~lK11(s80O+58&tfS zs1+ev2W4d^k;%~gfb+D7Si7C`5ZtA(UbCjyiM5QgbGoU>=Ra<>@x}4hz9-ib64p6v zioWGx?yo&4j(49$P`heLAITEnPEB~rgAj0lwv8vHfm{smNp1UBk zS(V*cc=^l;qYLsjLZ%Ol(cF?*(DG#9%aaX3MZgL~Hs4xX^k;pysHjAVUe*hkz1yQ# zUNCG6RlS$DIuXKYyHl^z6pVz{iOyY;n0^F+PMo>?bzKY|^_pjn#aBn+^hMmO>nYgD z&0%z^%tra}!D)jxkn@1@>`(lchH2^cn>Nk2#ZHX31SWCsN0~r;@ft zR%sp778U-dVOLnm*}S*6b;h3Pq|6qvvIw4)o>sJaVJ}vqtC)?w29ra)(-jN~*Ms+9 zs^F^?I_fxVhAHup5J11~6^7n^&0ML*_;xZv51vpt-h6^>8Rl)sV`?u4dS&R`HTiBk z`RKl<77(Qjr#udtonCX|{d-4eW!Be|Vsmhe?JUfml~!}5e6R$A3+6-xmnZeMx)l+1 zTMKc!+xOP)6~B5jJNQh$O2W0QnDUQ6ezdW)J{(PCur7;CgznM#F zU_QXz{Vsbzawg=~@Wnh{gLC-r0=0aULwg;<)Y-j_xw)pWaydx#`nPnLP=uBl%HmV* z455=1t$xF2Q*0zwukRaTCr4`x(J$Xd z4~Fl%U=AO{*Jt1Jp_v8&G+pSPXShg*k*S_b1&zHo4+P#V+Wi?)4 zq6(xE4IKh#WuL>4+PJXn!S!9fMUqm-+iatmUKglErGKSD`;b*uWsamb`6$eHD(kwY zRkb{8nIFv5vRbqw!@gFtW=21UHnV*Oxg%*w{g+)~5S9>!mU^8jioCMub;TlS%JHl}8L1+R6WJ1$`w$;%R}-S5=) zp!)D}M^tCd$}U1)WlebGdPS19IZC!AsXA*JM(7htq2SlT$==SV(fXDEC5g;G&8`gtWiHR=v2Z zLjCSvhZ|q7QhT*YU*Ki%t-_McZPUWoqK#a9F7_=@)Cy1&a7H9#k+SYuHg`=FF7GE~ebwRseijF@c%l)wr+TIS9WJs9$Wch9t z9N69Zv}uH0&${b)4Qu4ou;JmMDWBy%`OPHY?r_fVb-U!9y!k<_>x}OhWtb0RG<=X?Tc=*2oT4_6p7%N8E9JAq zUgjVS-ec|?4FGVvKxi>dSX+a)w^jh@4~CZhj{cz4;i}J+3nlY6MBZ>}rJ*mG#?lJ< zHsc9IzY4jdUU^aH4ro=~;U52wD(cGt5ni*}ySY3sDx2n|FHZi7(q{H=_#m(w{M&}= z(J#T-)W)eu?~f*feLB4;KHt2_@4qW-97uw_R`P6@?)vc;>9y$%g^OtvblCe4IVZzeS>l{J;KQ7{l7ZD){%mnq zX@zZ-LYjFr^T2adf{quT($F2>b+A0>ifUNZ4u~I-qFGmcJULef8qZcw;rOUau1^=k z%oY07qbK3QUIMxwb=O`K$12cqgZqGhIcsWYv}dPxf3B}~s_DRSGPvh!jw(_=?TThp zY*CAz@i`%tH4<*CR!jmV517iB@3A5~e{d?Ac5UykiPfG>m;v0(>BIf0Cg5E9=;I$L z3Xne|lCys8HFD(3PLi+XH| z^&ghw)ylNrSoHQ-`bKA}S-FjIn5BfG{c75rt3@ztO-BcWy7`_w*VaB+{Q)Len^c8d zHcH$oi*zK>g6>yllbbAZ9Y6GW*6$D~cgE=~liK^k2Y&{Ui-wrPd2EA!do7<@6mSsq z2Es^a&@Ffa%h1iqj;XzRL)aeAkQ@ByA@gmHZ%U?))$%wa&quAaxxx}E(a>6Xu1C5R z+0&;*4n0WC`+RRsckPc$uvs@y{n$ACF5bd7Cxt@p0`Nv61tQ&^aY~$-HDxJb-{_-K z#VKKS>g}1cR$RJ`CTqep3xtF}ZPNPM>PRFnIrk;=EpTSl3dS@7T5SH$XK3LSb0pSP zNO+-9Bs-h7?e9FbeC%f?dt5)n z(wUs_rpg>A3%X)rgL|)O#BLAYVGboA{Z>;*+fVTql`4#cf4*5foV&yeE7B{7=*jhu zeo*6GExcAQ`6i2mec!+J%#720D9%02#<({W<%Spxa(8q5X5S};{8qOO4;@pFy;VY)yxDqa1;!&GaO$H&KB zMt3s<>P{4h&UsIJ9-Aa|zjiPY984cGF!}ps}D8V;L8oCwKxHP2-%TJwh=0x1|ztezLP^=X#A$kHXY{q(_k%2Kw+GB7myrc z96~es-N{V%r^uc_7SUbCFYFd7_O2@jb-r&TzbAw-Yp+c~T2M?*czbqxs`jj*^?EN=j`$xJB?ziEeG5Uw~Y^dasssqT0|HivPUk~23d~IK%KD;mA$mSY#qGCmAiw!c zBti_Z50W741WehaY;ClYQ&Smo@>|jr&L`%*L{Wo*_5@;E52_fifs9Cmw%MG(^PRIi=b zs!sFnDY;4@;=?8W-3t+x&S^IH=G3L*l)!$_l~zS$*pLPZH#`=RlvcM{t^nKNZ^p|O zMl^?%P4Y3F?eOxgAAckE%KAKJF5jp)TXzvzQ+bvg%&)N8_g?C`QdS}IHzM#X4A<>d zCz}qt#PIu|k@$6_|8W0wCAzwM%O%n}!`~Hf`qnCqq*y)}!Zui6Pz;_Lq#ObNuA={U zK+5GnVeCWf;upel4yOv&#+<sn^B&GPpb)Z7cCFK6-Ao{O!)D4U!nvhBTy zZtq)@IoqmWohpDqmG<{RQiP53 z1myhq^obap-hz-}ih*v~ms=z2x@D&sW>nC}QbEON^5Bb4bPXWjX|)IP0{}t_;7t2l z;-ouNRvwRd`s86hCFLA$6No(A0kSldOz$E z#z$5|US=!G)<}u&$*o@;S zvro5`3NWnx{LW+bWspx#1=`4yQczVbHReSOBs7@=X7F-KgYUpEp>&!oAjGJ6!*iuj zW1|Bf{sFpzhD+BRX8YP)8S8@|lao=~v!~sRP95tzeOwOtJ6#)mHde>L72icja35e_ z02#^;T>+?$%Yry#I!gV?f2d`g_VA`gfB#g1R)vscL9Xqm&v^YNNHeN^_+M@3K8WG)hdF|t=#VwesWK(Qj0B#iP5L*6rdN=>#7nF;7fs}dSWRm>C%*g8d9^g|- zGxeT%+kXW=_W2t0s&rtFhb7%yXa(CJd=@(Q$%Hf&Ya&eQbDHSmAS^&~SfUus#$Mta zH7|={A5iemc175)3|mIBam1+IbN(`W+o4LSSfdyebVu2ed5eO-(jVwNF1l<_gUM z7ay03OLPw()q{hH|4J!~5gXJOCs$$yHi%Ov&)gY2m3Tc#qCHCATE@Y03xEN&zbl{I zV=7L@({*zP#g5df2w1p?gp;w(7|=TUubB`P)`k+~8OV~xrXTuma-D-&CrUY4TJ{bD zKI_U1pVT7CYJ0$^k6ovudp9QX<|C17nnrrAB%}x$*E z;v}i3g4<6N*oE=>Oh$6RGZZbS+P_{;d4JdG;+_P4Cf~8p9tUg6Hpsy&M&Bj1@Q9_; zP%;u2H*cV)05qZV6!2U+Qx^#*|!Mym2OqeS$ zxap84)<`EHQwgVZ_(!u=8PqSuJ^KEJ+_Yw`e&N!!?X;5JCyqPWKUY~J7= z5gc6T&8gxqbQ9*%sZ|+kRjTbT5(p;f!f$9A{l=VEv(Wy_1bv`M^o`-mGMcH3>;03t zYJ3$VgYmr&F4a~U2N?&KPA2LJlhP~9+N0?fPb`l<1jbp(_p=S`&$ieozTv$(TnNln zYv=+LDa(&3lWG|{mI8nP{n9(fn!Zef^|cA<8@ZcZk!tX=r2vI*S=Tc$WXUjiZ3SCv z+@QTb!CQ9EvuT6EQGjs(Uh)90pZ#jmBqzgpWmf;7B5ms2e{r0#Pyeod4?%wop&6)^ zp6Y{58Nc6$um|{aiItyoN4z-(bH4`w>WwRLzokkev}H;h%FtgaEU0($R$#!s_qUtd zcrgf&oQHj^{`JLMLAaI3>8b;6)^v4RLNEt&=lHfgYaY{|%u$g01wwdiV0PAm9x;d6 zW&@vSbN@pMVE3%|4z6R3I?gfs5_tPckQ1%kqwgxUD`uo49fs|r4Ks$nWbX^~{dufB z-?(3KF6@kapA-h%ztGAd0di4Z#~hG$zyW!b`5z7lhq_s@(Z`)iiU1A!D?!a}m^;H| z${@%NezqVXMH@+on~NAT(9s$8xLx1wDAqWC{{lXQ*;Tly>=Q`aVKm594{KL7MqZ zdzjeaTFS^xn5qH%Nt!?h){-#;US#783W5uzP~yW{I*lyj)W{lboz_1L2!-<)KrA z0W@Cj1zti0=SB!Bnrd^v+B;`Vb>(N{3q@Wnj5P&1?m%QeXywsjfDHR5({EY&B;!!H zT}6rrfB9u*my74Z-q42Bt|w1NO0S;w1oICU@4whTm}2r_Wj5x-iUqz z>MkJ(ijW!la6BfGU=p4toD|Fds%LEodqa3yB9I6mCrLRrTjCtB$OvW|o3bI%QEzVZ&nQDI8|NvkyF(CzkqX(WmrU$JPmP_n4N4_VVk>KPm5Ixz|AM>HVQKIc|Q$QxMl9y6M&4QOAg#r zHhmw_QaOILX_$Y7jp8_5qgzZC@0L3JAdO^SS4ddMQ^?TT&f>ZKuUr69fod!aE2|>A)*1>o>`@sR>dt{!t>_YjG*4pw?m1Re=+g4RIk z>^fI&+6FZ)7L@sgL5IKZPhI#)@)^n9%lttGMJAHU2GEZooXOF?JV%CA&u$(y~@9xqHwe$=1sZ0n4z?GjpkiGVDs z>%t6#D}usr^STc6tPVa$4dm>?WM6YEi`KZAJMO||9DcBnLUM}-%ceYPB-1b9g+#4WXR!o`t2Ni~?RfSyB0)yF^KMHoYQ z`vk1rszu-i+@!@%e^hnN^d4o*sisvsLs9V_odsU2%IE!ulvSK)(t)&c-R96;DY)AK zQcy>&J&@N7P;;f70%v{QhPn?fQTd0pc+ETFOiq3T0p)H9@c zmufBT6F2`FT*=>Y7eS@i`whz$yCpc+Z4INZfE~_|8*j@g;xU>Y%?2qv)$&Q>Lh>0lPo4(6x8 zium>39~VT*oyI!1uIolb_h67+^};U+%>_!xFwNgx0e!Sl@>{NAzEUl=D`DDYR>Mth z3+_G0#_74_Jme_>lj8*^6#M@wT%OGrYrT zxbB-2em1%Fc(zxqPn+(bEB64dXHjH%18sc`d2rkL`{7|(<>pdT64O3!Vq=4+q#xs;93W&8%HvSt^o&i!`}ST@U(|FppN|)SumVz8YzCAqGqb~ z0n!gox-_c)8qz?#Wd*?otI}M9S`fo|%yTJ%=F5&AIpV+1C%H<1;yp3@i zg3em5e4$bS4!9QU^d;`e-oFwAgyEKhtS2q3B($co-g3LwHl39_+7Aynn&BGovWSw1 zDul+KLiWUzAFo5#e6R|&8w@Hp4@(Wl(WX6$Rc5SHUG9sXOi;G@@i&n?#S3{~O1 zefY`@QITf-3ox>lU;`m5kCizIbruO9Go(>&7N}X4>z~tAgD6Hb?S%e~m3>fGERe@e z!%ddhd<$N&7aws!{9%F2Cv31^C`gDBj(x!Ff#S{&;2nVc!J#?3n=$t;*agNz_JXzr z`!Gj0P<(}jfQ!uR|*&`4MOgAp^cuDSEM{Dm)}V$lN~YZ z)h(W1p~eZW*VkZmk940aaVh35XK^u+5UM{aq5e%3nE`poC`8HIEKVDtk>~&r{YA-7WXu0)`)982GfbU(nZ`-p96~)e0q|@ zem5KVOZD&%nZI|y5#K!hbZKTE9M<9l2T2X~Y}Xv`;(ly_1i-2AHzh?l{8= zbs(4^Ynm=x0}Ejx0T#k@dE@p4U#*A4#^eOa-cuZEPWKHWf*L+`CGVA1shYap0lxVk z!ytp)McNx-Ma@zWopqEi#~`dgnmNyB=AncR1TUb;yaz<1IE@#TS2bUtctluHk%TzQ zhwBl!x`tlbz4iUUR|;}^nDuBCC`K&al!EFozVR{=lW;9|3J)9J#7$=Simm)xjYT)6$= zoUxt}=YK4q4&yB>%H^c3(x=X-qhkZ@N=kGY@JfFKDin)2*@X)f;%#oWFmC8}?U{f}~7uX(o(yxhzF+jLkOL1)Y)Byau z4}mlg`;T9>FXs`yrG%+aCHx{y?lWEKD8HR_)V~ibn53-$S-k+Kkg}F8`R`qGC-4qw zW0u?z2>OzatkmT-Qe3rGlJw4@#{z29*BPJ|HJb?xx-hBIf2mGMdHx^h)DK02BrMZ# zc{;ZSPmb1sp++yjfvj9ja)**ps1|Pn8$qn(@LR-0I{cDY&Ceer^*}eMv_>iK#&mhI zmaUj-mtX`xEaqm`-!hGjO(;JDJ)%QKln)Z4_Qq~z4mFkhEl)GQX4vzghX~zhkl(^{ z>#^79Zj0Zm>ak@6d>)f7?7aVf2YzhG^`>#Lc<(4_RJFF5#2vx=%v(~UUah3OMLJ$N zm2$K$^NXUKHN_j%Cg; zz-oMb0(3t0a|1%VHoZR6xOlWbdMt42GQ ziB-95^4qD?D})7JX}5TOC+{oB)q$Qmpm*FDeo~uul`d?~y)JIo`7I#t{DL-m_wA*_ zYsL*8i!?NsL6^ZjubCb(y2f~=6?WLl%u?!lr^;dIw&#>Z^noYK9fMS(=U(6cO7PWm+jFOOTmmTa)ONT&v3)7rR_cEg7+Q&xbca;S$bc!IQydq^zX|AVKgy9Vz zXNd95`1O3`@YC4@l@2s53L7GG5lxSm3c&Lc;-64|dTo^ApMa?dE&PUcmZWKV~PLj?EMXC|Bw zFQue4@d{8Qo{fYi`1y}?j;EaN!k6D)ux-GpV7N7`V{J~l%IDVgT)w$DZZJ2ffcvk` zB$>V8#GB5-4~Q~Obr`+EnoLwD;zGh_I#P3j7xZ`F1Bo(+sC^8s)P)OH_?gAI6TC|w zUCnRUU5N_(aBwkBfZ9E!tkO}HO@N4UoDq6BaJ%n=0WzO8&jLs!lcm4~{~+Jmnl-ok zPz{pXZY^~hP@J5tlnEG}HR5A>99B+mN#0J&e(bP_zQ|w-u=n~wWa^eLEZ_Y$mi_8q zWGASn)*W4SML*R*=XZiy-`FDAHOLxcEF_#8M!d#RY)njN(&G3LEod)2`{nA$>kO?g z%sRq9DQ3nQ6)z!wuYa?Ah$Op)q$?`l3+-`4-WvYQX&E2GnQB~|tqr@1NK-KHf1UAQ zr&*;1BN*eDfiZIZvV2#WoNeL1VIbdZcn)t{4iX59_;a{F4)=?^*~Fv9*JI7|p#7yB z#e{@{?zO;S((o8^bZDIHN0}N9g z;4ZBzvDdqKPPDUiY&~v6zt`Id|Hlk6A_ygi*gM}}nVXu=twMIh|7v6E^FV|2T4-4h zFe5PsW$qW_P0raoPtg5nDfX)_GzT`-*YT*3%QuTZM~mcR(yI#*r`&*jhhEnsQfCMyHMP*VR@t=DvN%1v2CJ1aYh*gV z^H77tm+)Pca^a*BO=r}83~F92$eAm+;3KKS7}uYs_58h@SiC?~1TR0<5PshvoToEy zmR$75ku9SbO2*y`F$Zy7UD2+ZEb=wvKR2 zn}Dg|_f_N%1r>l{X(_gapXQ{6(71T0yPd7Ym_0g8c+_EuJ&~`quNwd^I;o7OtsG8B z+&_jdjTidLb>Z^S$yN@izCI(8A>nQ|iX#JV{X8_7Zm632H66@>GF5@AD)>@VJN~8r z!@O7f=1nkYl9~&d8Ua2IfNkw#;xpCf%bfgy-IWtJqY2mR2ojFpz?r#M4*WfZSu>{D|8$OaT_;eeo@rFNB^m= z({6M9#D?2jPsi5vQwTJ10@?S+3ce;gZPyXzk6om9OYp!2m{A?@(VS_bYy)cX^i;+8 zZaEF#E6XOgUrcFmQaB#9N%SDsv6xYXan&aA){=t%?g z*O33*toKL2Tlx-cgQC&gyC90N7UWZ?QzgnlEQnZObI=QF(DN7jYk$oZQu?>h-m1K? z5e%rfi@n8Bwd%Hkotf5nltM)+~LyHxQlHZIk((TL9B~AeUA6gE`_!y}le!u`faa_f& zW;ZX=dmhj&Jq_#A!B}H(p?t3M&knCiN{!r!Q_|Okv!<8JYuhY>2fW?znsY4_Ee zhQ?moR7zS_k!Ha1{kQ)u^0Ie*AY%mV61f8ju#>*~ZlLT_!Oi91PQyFf-StaDH4_pI z*x1>n>!#v;^yUNrr|&1T6~*=c_ddnsxThBaCne=}zB=%Oo&D^;C>T&3=>!6ybPR;P z%rs(_zBK_d4N3=0Xu;S2FGN%YMLELvSBFXhzHr;3qxek_9{t#?#zM@!+K z-d?rU4eZypO(*3v8#OASe2UMv+C)rt>OZfM^~M!?D`KAt8twPE+fU#8yIU+ga$W!D zQ7zce{fnJ-0(N12k<3Yu$3X^aQd0lRcMtjQqnqo$jCv3NI}7M07p;`jwKw9>V7U*= zJeRP|Iw6yo%AwBy+Wmql{rWi|-l4Ct!K~zQ2=2HGPkq)+jG_;Xo=q5z=2ipW5fGCT z(sU`<;5f)BH97GpY|XsL5*A|a4@SHYh{BQI>moRNo^}0NXPx<;W{^F6ot^+w6ygmo zA%0EkbCjw_uJW*_70+h-iWJ?zg~Plpk{8gj7kJRKsP~gFR3&h_+u9pe!;PVCV0M+@ zJQ?tF8FSioqt2G(cffOWBedg2dBJb+fvh<5`Mp+PiTYafM(x3_Wp1{Jd1S3U77Fdg zTEXo)pt0ImG4rM@Xre$LeRPXt8!)r4lYp;#=?Bo|LE|37<^L%dRvC_TV^DfF%-ETa z1fXE~?>Yp8bMik%9rs31Tm}=>UMo|LHw(t;l|XLon}mYazeXMUjsL}{1M!Ief7T(K z{$vVx#rT83l^3dx)@#mP4}qVf&qz=5%63KR zJEv`2cJFgm(3&%nZnwz*Pr_2_LivKJBi>I~H9iLr5JxxW2C9B~;B9rMTM%*MwKEcHCI+D`j|8^GFX$ExHR zQI4Q7|1FCEnF>DK#k`BhrCsjsT$SAv(|zz3Nv>Z`Pgb2T{dCbWTr)@UA!6ImIdw7{ zauE?8_ZcKbjcQjNc7DyqYLD+@ti z{Uqm0&K3QN_wD*PNrz3O$W48QT+G0&)bE;Yir3cg@p=@F(eFCva%B;Uh5M+X(kz9O z4)VM_*6@OEco@jY`oQ8>GJ8Cr>$^a1zf9LF^nr#7=oQW$>lGNP;sym3yE_!5Js0O+ zgp^l^K@>q+hF+m}8dlg8ZX!hM%xhL5nihObb62|;gq0G0RE|U_OZu$e4ZyWdNh+gG znm86j%bg!3M_GOGw##d6-HK}_`f!|+PFgHNv9e5$Z@9p=R zwn>35y?A5}YWzL+9l=ANluz)`Z3{w8rIV^cQPJ9;fDD=ZKzIo;heytDBLbk7^>+r| z-kr~vG)34TD`JiP|2fzh$$wOW1ZU`%UtV2&f){u;R7z`nAcB{~pCfyP5LpaTtA_7! zOmi5s>p6`6xtVXW{WclP^}s49J;)x+F{wLKNAfb6wifE)OjluMi0@C<1dDstT*qCp zNF+~1{j!M$R9o!P>;9iZ6#G+b@_z@uNp32`^f&70py8q_lys>vf(H@BS8zAKKSv-z z*XOJr0FY!CjZ-cP8KRMUmM}LD%|Q>2jvV{tyo2|M3{!RBe;{q(i}wCqeTqfw+bV^7 zG7iNB73_B=n^Ra^i+BHN6PO@eh!;7-!WrLFvv;eU1{y@C=s>!0$Ylzw-j^*?#bIhrb(;4;QUt+g;bKCh<`JK z>N_!2aIP6+9c!NIiQZ%zYK*)2NHj)!7Xht^umXBBKcZ7jkAo3WBmUwP)%;!Nz8>5L zvvqCuIJUm}+*W8US~eTIXfrvn{|t+}Z8f6%9-&it@|F}zdn>1d#DOU1HJ zIBmw%&scPT%zte071NryPcpzw!e=XPA5D%a9zz}=V$pG-!fcOp)BI0*-*Nidep z{j6z~iP(RBQSgTf1MwkFlBfD2)YNwGb}7mA0$rAQKmUs9FI}3`DpouW)%Zs8nbY*G z6J%TPok#aIC!@p(9?ZyHqdcw#ZV(5_!0@Ne!XGPt1ZC$_LwTvS7|PQ|X6wh!CnD&J zBH$>u(SQup*E|J-HzH_3Y~bVaRb!JP+Y8+Dy0tvSh!o<^mI>s4fg8kZ0$y8 z0#m|do~gHfqvH1jg=(FZGYrDNA8}u35+R@Y!m3s6NT>fXyfYwpl-wl7WuFMDRj;l5 z(>)CToiw4XXR>bF&@0udsq0e;4{5|Kha|5blEgm^q2Jk&%&(FpsexrYz!n8oK9QhU+|5|k`1r4L9Qck#DPy13Xbvvkq_9JiQx;oPo` zW59@k0h^{Lb-W1~7*a0@as0_m|9Q~S{t!{ryztMzf~0fdjAs~THN4=Ey5Zx7H}_p8 z6E`m}FO@Jae4Ok6;vSUgjo1J820i;3b2!M_XvABJQ$XN{PP~}-llHR=LBmMI#~)ZR z|LH>ty7l;qU@a`3I}dQbq|Y28qdQ_%UW#^GpSGm3L&28(Q}5Efr_3>z5FQ{HM2pOL zBJ_V#L{bbL8k6^Yx;&`^6wJ?&D(|1afp^1iBccdoZ5VI#UmtqDkplug3km9Dgwm8< zl+`MYO)L2%1NR#c83kSp2|DixD@>TAe^`cF$B*Uz@IwBt6=TrJ0;8g(8m*+tFPn@2 zV1IC=x&vSiC#mnLzaQ?=^@3nBK1xhJ2wsXaEHJIJ3Gh~*EQ_hzoxK&XYvHkT&tqP_ zs7an=;kv*zkkNK_@m(yp{VMu+yj$2<%y0}ri~mHVUnNV5B(AoH8Ot)su{oZ5LE5BH_a-Q6_? zYSv;wks5eL50Ca;BN|ZwrV^dxL!O9QJz-Dab_Y0Dal@8$Gd$j_LWb5i?%1C{Bj42< zl{RzK`hsd?1zlsr>IUTiQ&_*1yNf{M(Q=fkzU3%4a*Dq`h2jiUw(WrLnr z7=trPVt(_2?d~^i&qeR1%~lnKzVvlLi!BA`9R3_d-2-(1%H+KWm^ySmoGDQ(kzAMA zqLhiY9~44OR%>`%SB5x#WmjQLXZpl=igok(MCnrvswvvP%^yvKSqv0XYOTX~=PE~i zDD!;`LF&l9kB=pQ|ML6b77w1vt%Kd}o~SQtV)^+i2xmLSY z&+WzmcoWM(W`^U+R5-PnQQ5CKcdTzlJlRG6_Pw7Uggk34JVuEdb5%|rC@{d37_z&_ zv3=m&bZ_x>p!`qygY}8|EN7qo2HcY$#%n;TN<=WWvq2H-T@ju&MGbu2qK>i>n z`Lufn$U(F?GEwqtfNxbt2Q&)JoT5!seWd~q(KU*C?C*qclJ`Nb(}VYgpp@>TJU@~49mzZGsB zb@Imz&SvZ9h!(ba$kep)2Y!J!`o5Q$ZU!IC9wD>)C1a}wD(&fRh9S#=+-)7B2x(&k z>v)pqA&k=*AG-|1L8~xNnfc=Iy&vJ%RB+Ann+FYG)F3v6{hphxy~c@tpRv;ai$TZH zCsJSn2xnGoO}E>Hp40bi7n-VF^0P~tABrcCQcY)%R$Wt|Ow!t;ZM0Wp6 zgZ!QHF-z*{hMh??6=XvEm|`m|droT@mLKHdn3zE*cT})TKH9uJp;JLBgR!N!vei#k! z$knymNnMYSvfL1h4>tvfKpw%gH_*x^0ygrVq~NK&zcy~%Tn*T-i+M$daSJCH`V2DI zE^_?DdxtZ9LLa%6uw5pv_hMV8!{8~i1H1;lGn(Zyx!BZMl{=f})`%@f%1+o;YqnHr zr*wh1LjBQ((_OL;d@$31boT)+aaQÄG~P^h5at;AXo$!*YWcn3Knr6bl-^Swp< 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 QS5BrRulB6uiFxpU1OCMpi~s-t literal 0 HcmV?d00001 diff --git a/7-building-chat-applications/img/lesson_plan_prompt.png b/7-building-chat-applications/img/lesson_plan_prompt.png new file mode 100644 index 0000000000000000000000000000000000000000..af865fc87039e6385ca8abf58b06e4ad3ff48b3e GIT binary patch literal 43024 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 literal 0 HcmV?d00001 From 4ef4a625d7bf2e84b108c517d68d8e6fc676220b Mon Sep 17 00:00:00 2001 From: Jasmine Greenaway Date: Tue, 17 Oct 2023 03:05:31 +0000 Subject: [PATCH 15/15] add notebooks --- .../notebook-azure-openai.ipynb | 2169 +++++++++++++++++ .../notebook-openai.ipynb | 669 +++++ 7-building-chat-applications/notebook.ipynb | 46 - 3 files changed, 2838 insertions(+), 46 deletions(-) create mode 100644 7-building-chat-applications/notebook-azure-openai.ipynb create mode 100644 7-building-chat-applications/notebook-openai.ipynb delete mode 100644 7-building-chat-applications/notebook.ipynb diff --git a/7-building-chat-applications/notebook-azure-openai.ipynb b/7-building-chat-applications/notebook-azure-openai.ipynb new file mode 100644 index 000000000..0783096eb --- /dev/null +++ b/7-building-chat-applications/notebook-azure-openai.ipynb @@ -0,0 +1,2169 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Chapter 7: Building Chat Applications\n", + "## Azure OpenAI API Quickstart" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Overview \n", + "\"Large language models are functions that map text to text. Given an input string of text, a large language model tries to predict the text that will come next\"(1). This \"quickstart\" notebook will introduce users to high-level LLM concepts, core package requirements for getting started with AML, an soft introduction to prompt design, and severa short examples of different use cases. \n", + "\n", + "For more quickstart examples please refer to the official Azure Open AI Quickstart Documentation https://learn.microsoft.com/azure/cognitive-services/openai/quickstart?pivots=programming-language-studio" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Table of Contents \n", + "\n", + "[Overview](#overview) \n", + "[How to use OpenAI Service](#how-to-use-openai-service) \n", + "[1. Creating your OpenAI Service](#1.-creating-your-openai-service) \n", + "[2. Installation](#2.-installation) \n", + "[3. Credentials](#3.-credentials) \n", + "\n", + "[Use Cases](#use-cases) \n", + "[1. Summarize Text](#1.-summarize-text) \n", + "[2. Classify Text](#2.-classify-text) \n", + "[3. Generate New Product Names](#3.-generate-new-product-names) \n", + "[4. Fine Tune a Classifier](#4.fine-tune-a-classifier) \n", + "[5. Embeddings!]((#5.-embeddings!))\n", + "\n", + "[References](#references)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Getting started with Azure OpenAI Service\n", + "\n", + "New customers will need to [apply for access](https://aka.ms/oai/access) to Azure OpenAI Service. \n", + "After approval is complete, customers can log into the Azure portal, create an Azure OpenAI Service resource, and start experimenting with models via the studio \n", + "\n", + "[Great resource for getting started quickly](https://techcommunity.microsoft.com/t5/educator-developer-blog/azure-openai-is-now-generally-available/ba-p/3719177 )\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Build your first prompt \n", + "This short exercise will provide a basic introduction for submitting prompts to an OpenAI model for a simple task \"summarization\". \n", + "\n", + "![](images/generative-AI-models-reduced.jpg) \n", + "\n", + "\n", + "**Steps**: \n", + "1. Install OpenAI library in your python environment \n", + "2. Load standard helper libraries and set your typical OpenAI security credentials for the OpenAI Service that you've created \n", + "3. Choose a model for your task \n", + "4. Create a simple prompt for the model \n", + "5. Submit your request to the model API!" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 1. Install OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674254990318 + }, + "jupyter": { + "outputs_hidden": true, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "pip install openai python-dotenv" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 2. Import helper libraries and instantiate credentials" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "gather": { + "logged": 1674829434433 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "import os\n", + "import openai\n", + "from dotenv import load_dotenv\n", + "load_dotenv()\n", + "\n", + "openai.api_type = \"azure\"\n", + "openai.api_version = os.getenv(\"OPENAI_API_VERSION\",\"\").strip()\n", + "\n", + "API_KEY = os.getenv(\"OPENAI_API_KEY\",\"\").strip()\n", + "assert API_KEY, \"ERROR: Azure OpenAI Key is missing\"\n", + "openai.api_key = API_KEY\n", + "\n", + "RESOURCE_ENDPOINT = os.getenv(\"OPENAI_API_BASE\",\"\").strip()\n", + "assert RESOURCE_ENDPOINT, \"ERROR: Azure OpenAI Endpoint is missing\"\n", + "assert \"openai.azure.com\" in RESOURCE_ENDPOINT.lower(), \"ERROR: Azure OpenAI Endpoint should be in the form: \\n\\n\\t.openai.azure.com\"\n", + "openai.api_base = RESOURCE_ENDPOINT" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 3. Finding the right model \n", + "The GPT-3.5-turbi or GPT-4 models can understand and generate natural language. The service offers four model capabilities, each with different levels of power and speed suitable for different tasks. \n", + "\n", + "[Azure OpenAI models](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/concepts/models) \n", + "![](images/a-b-c-d-models-reduced.jpg) \n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "gather": { + "logged": 1674742720788 + }, + "jupyter": { + "outputs_hidden": true, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "# Select the General Purpose curie model for text\n", + "model = \"gpt-35-turbo\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## 4. Prompt Design \n", + "\n", + "\"The magic of large language models is that by being trained to minimize this prediction error over vast quantities of text, the models end up learning concepts useful for these predictions. For example, they learn concepts like\"(1):\n", + "\n", + "* how to spell\n", + "* how grammar works\n", + "* how to paraphrase\n", + "* how to answer questions\n", + "* how to hold a conversation\n", + "* how to write in many languages\n", + "* how to code\n", + "* etc.\n", + "\n", + "#### How to control a large language model \n", + "\"Of all the inputs to a large language model, by far the most influential is the text prompt(1).\n", + "\n", + "Large language models can be prompted to produce output in a few ways:\n", + "\n", + "Instruction: Tell the model what you want\n", + "Completion: Induce the model to complete the beginning of what you want\n", + "Demonstration: Show the model what you want, with either:\n", + "A few examples in the prompt\n", + "Many hundreds or thousands of examples in a fine-tuning training dataset\"\n", + "\n", + "\n", + "\n", + "#### There are three basic guidelines to creating prompts:\n", + "\n", + "**Show and tell**. Make it clear what you want either through instructions, examples, or a combination of the two. If you want the model to rank a list of items in alphabetical order or to classify a paragraph by sentiment, show it that's what you want.\n", + "\n", + "**Provide quality data**. If you're trying to build a classifier or get the model to follow a pattern, make sure that there are enough examples. Be sure to proofread your examples — the model is usually smart enough to see through basic spelling mistakes and give you a response, but it also might assume this is intentional and it can affect the response.\n", + "\n", + "**Check your settings.** The temperature and top_p settings control how deterministic the model is in generating a response. If you're asking it for a response where there's only one right answer, then you'd want to set these lower. If you're looking for more diverse responses, then you might want to set them higher. The number one mistake people use with these settings is assuming that they're \"cleverness\" or \"creativity\" controls.\n", + "\n", + "\n", + "Source: https://github.com/Azure/OpenAI/blob/main/How%20to/Completions.md" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "![](images/prompt_design.jpg)\n", + "image is creating your first text prompt!" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 5. Submit!" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "gather": { + "logged": 1674494935186 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'The use of Oxford commas, also known as serial commas, is a matter of style and preference. Some style guides, such as the Associated Press (AP) style, do not require the use of Oxford commas in a series. However, other style guides, such as The Chicago Manual of Style (CMOS), recommend using them to clarify meaning and avoid ambiguity. Ultimately, it is important to be consistent in your use of Oxford commas within a given document or publication.'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create your first prompt\n", + "text_prompt = \"Should oxford commas always be used?\"\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " engine=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":text_prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Repeat the same call, how do the results compare?" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "gather": { + "logged": 1674494940872 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'The use of Oxford commas, also known as serial commas, is a style choice and can be subject to debate. However, using Oxford commas can help clarify the meaning of a sentence, especially when listing items that contain conjunctions. It is generally recommended to use Oxford commas for consistency and to avoid ambiguity. Ultimately, the decision to use Oxford commas should align with the style guide or preference of the writer or organization you are representing.'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "response = openai.ChatCompletion.create(\n", + " engine=\"gpt-35-turbo\",\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":text_prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Summarize Text \n", + "#### Challenge \n", + "Summarize text by adding a 'tl;dr:' to the end of a text passage. Notice how the model understands how to perform a number of tasks with no additional instructions. You can experiment with more descriptive prompts than tl;dr to modify the model’s behavior and customize the summarization you receive(3). \n", + "\n", + "Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnostic in architecture, this method still requires task-specific fine-tuning datasets of thousands or tens of thousands of examples. By contrast, humans can generally perform a new language task from only a few examples or from simple instructions - something which current NLP systems still largely struggle to do. Here we show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior state-of-the-art fine-tuning approaches. \n", + "\n", + "\n", + "\n", + "Tl;dr" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Exercises for several use cases \n", + "1. Summarize Text \n", + "2. Classify Text \n", + "3. Generate New Product Names\n", + "4. Embeddings\n", + "5. Fine tune a classifier" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "gather": { + "logged": 1674495198534 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "prompt = \"Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnostic in architecture, this method still requires task-specific fine-tuning datasets of thousands or tens of thousands of examples. By contrast, humans can generally perform a new language task from only a few examples or from simple instructions - something which current NLP systems still largely struggle to do. Here we show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior state-of-the-art fine-tuning approaches.\\n\\nTl;dr\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "gather": { + "logged": 1674495201868 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Recent work has shown that pre-training language models on a large corpus of text and then fine-tuning them on specific tasks can lead to significant improvements in natural language processing (NLP) tasks. However, this method still requires task-specific fine-tuning datasets with thousands of examples. In contrast, humans can perform new language tasks with just a few examples or simple instructions, which current NLP systems struggle to do. This study demonstrates that scaling up language models can greatly enhance their ability to perform tasks with minimal training, sometimes even outperforming previous state-of-the-art fine-tuning approaches.'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " engine=os.getenv(\"DEPLOYMENT_NAME\"),\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Classify Text \n", + "#### Challenge \n", + "Classify items into categories provided at inference time. In the following example we provide both the categories and the text to classify in the prompt(*playground_reference). \n", + "\n", + "Customer Inquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\n", + "\n", + "Classified category:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "gather": { + "logged": 1674499424645 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Classify the following inquiry into one of the following: categories: [Pricing, Hardware Support, Software Support]\n", + "\n", + "inquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\n", + "\n", + "Classified category:\n" + ] + } + ], + "source": [ + "prompt = \"Classify the following inquiry into one of the following: categories: [Pricing, Hardware Support, Software Support]\\n\\ninquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\\n\\nClassified category:\"\n", + "print(prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "gather": { + "logged": 1674499378518 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hardware Support'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " engine=os.getenv(\"DEPLOYMENT_NAME\"),\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Generate New Product Names\n", + "#### Challenge\n", + "Create product names from examples words. Here we include in the prompt information about the product we are going to generate names for. We also provide a similar example to show the pattern we wish to receive. We have also set the temperature value high to increase randomness and more innovative responses.\n", + "\n", + "Product description: A home milkshake maker\n", + "Seed words: fast, healthy, compact.\n", + "Product names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\n", + "\n", + "Product description: A pair of shoes that can fit any foot size.\n", + "Seed words: adaptable, fit, omni-fit." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "gather": { + "logged": 1674257087279 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Product description: A home milkshake maker\n", + "Seed words: fast, healthy, compact.\n", + "Product names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\n", + "\n", + "Product description: A pair of shoes that can fit any foot size.\n", + "Seed words: adaptable, fit, omni-fit.\n" + ] + } + ], + "source": [ + "prompt = \"Product description: A home milkshake maker\\nSeed words: fast, healthy, compact.\\nProduct names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\\n\\nProduct description: A pair of shoes that can fit any foot size.\\nSeed words: adaptable, fit, omni-fit.\"\n", + "\n", + "print(prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'Product names: FlexFit, OmniFit, AdaptShoes, UniversalFit'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " engine=os.getenv(\"DEPLOYMENT_NAME\"),\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},]\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Embeddings! \n", + "This section will show how to retrieve embeddings, and find similarity between words, sentences, and documents" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Model Taxonomy - Choosing a similarity model\n", + "Let's choose a similarity model, using the most powerful model (davinci)\n", + "\n", + "**Model taxonomy**: {family} - {capability} - {input-type} - {identifier} \n", + "\n", + "{family} --> text-similarity (general text GPT-3 model) \n", + "{capability} --> davincie (curie is second most powerful in ada-babbage-curie-davinci family) \n", + "{input-type} --> n/a (only specified for search models) \n", + "{identifier} --> 001 (version 001) \n", + "\n", + "model = 'text-similarity-davinci-001'" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: matplotlib in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (3.7.2)\n", + "Requirement already satisfied: plotly in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (5.16.1)\n", + "Requirement already satisfied: scikit-learn in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (1.2.2)\n", + "Requirement already satisfied: pandas in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (2.0.2)\n", + "Requirement already satisfied: contourpy>=1.0.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.1.0)\n", + "Requirement already satisfied: pyparsing<3.1,>=2.3.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (3.0.9)\n", + "Requirement already satisfied: pillow>=6.2.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (9.4.0)\n", + "Requirement already satisfied: numpy>=1.20 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.23.5)\n", + "Requirement already satisfied: python-dateutil>=2.7 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (2.8.2)\n", + "Requirement already satisfied: cycler>=0.10 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (0.11.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (4.42.1)\n", + "Requirement already satisfied: packaging>=20.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (23.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.4.5)\n", + "Requirement already satisfied: tenacity>=6.2.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from plotly) (8.2.2)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (3.1.0)\n", + "Requirement already satisfied: joblib>=1.1.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (1.2.0)\n", + "Requirement already satisfied: scipy>=1.3.2 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (1.10.1)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from pandas) (2022.7.1)\n", + "Requirement already satisfied: tzdata>=2022.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from pandas) (2023.3)\n", + "Requirement already satisfied: six>=1.5 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n", + "WARNING: Ignoring invalid distribution -aiss-cpu (c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: matplotlib in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (3.7.2)\n", + "Collecting plotly\n", + " Downloading plotly-5.16.1-py2.py3-none-any.whl (15.6 MB)\n", + " --------------------------------------- 15.6/15.6 MB 28.5 MB/s eta 0:00:00\n", + "Requirement already satisfied: scikit-learn in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (1.2.2)\n", + "Requirement already satisfied: pandas in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (2.0.2)\n", + "Requirement already satisfied: numpy>=1.20 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.23.5)\n", + "Requirement already satisfied: packaging>=20.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (23.1)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.4.5)\n", + "Requirement already satisfied: cycler>=0.10 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (0.11.0)\n", + "Requirement already satisfied: contourpy>=1.0.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (1.1.0)\n", + "Requirement already satisfied: pyparsing<3.1,>=2.3.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (3.0.9)\n", + "Requirement already satisfied: fonttools>=4.22.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (4.42.1)\n", + "Requirement already satisfied: python-dateutil>=2.7 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (2.8.2)\n", + "Requirement already satisfied: pillow>=6.2.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from matplotlib) (9.4.0)\n", + "Requirement already satisfied: tenacity>=6.2.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from plotly) (8.2.2)\n", + "Requirement already satisfied: scipy>=1.3.2 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (1.10.1)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (3.1.0)\n", + "Requirement already satisfied: joblib>=1.1.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from scikit-learn) (1.2.0)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from pandas) (2022.7.1)\n", + "Requirement already satisfied: tzdata>=2022.1 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from pandas) (2023.3)\n", + "Requirement already satisfied: six>=1.5 in c:\\users\\louisli\\miniconda3\\envs\\gpt\\lib\\site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n", + "Installing collected packages: plotly\n", + "Successfully installed plotly-5.16.1\n" + ] + } + ], + "source": [ + "# Dependencies for embeddings_utils\n", + "!pip install matplotlib plotly scikit-learn pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "gather": { + "logged": 1674829364153 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "from openai.embeddings_utils import cosine_similarity" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "gather": { + "logged": 1674829424097 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[-0.004474656656384468,\n", + " 0.00978652760386467,\n", + " -0.014904950745403767,\n", + " -0.006424985360354185,\n", + " -0.01135313231498003,\n", + " 0.015513833612203598,\n", + " -0.02372107096016407,\n", + " -0.016414472833275795,\n", + " -0.0158182755112648,\n", + " -0.029632311314344406,\n", + " 0.021298224106431007,\n", + " 0.021095262840390205,\n", + " 0.018570933490991592,\n", + " 0.004170214757323265,\n", + " -0.0007155169150792062,\n", + " -0.007579326163977385,\n", + " 0.02521790750324726,\n", + " -0.004214612767100334,\n", + " 0.011175542138516903,\n", + " -0.008587788790464401,\n", + " -0.009513798169791698,\n", + " 0.021577294915914536,\n", + " -0.005993693135678768,\n", + " -0.008257976733148098,\n", + " 0.006041261833161116,\n", + " 0.013040246441960335,\n", + " 0.007439790293574333,\n", + " -0.0035169341135770082,\n", + " -0.008955655619502068,\n", + " 0.0011939817341044545,\n", + " 0.00666600139811635,\n", + " 0.0038657733239233494,\n", + " -0.039272960275411606,\n", + " -0.002559211803600192,\n", + " -0.012761174701154232,\n", + " -0.0217422004789114,\n", + " -0.0037072100676596165,\n", + " -0.010458835400640965,\n", + " 0.02597901225090027,\n", + " -0.0456916019320488,\n", + " 0.009399632923305035,\n", + " 0.015653369948267937,\n", + " -0.02261747047305107,\n", + " -0.01161951944231987,\n", + " -0.0028573106974363327,\n", + " 0.012215716764330864,\n", + " 0.010534945875406265,\n", + " -0.01253284327685833,\n", + " -0.0228965412825346,\n", + " 0.01036369800567627,\n", + " -0.00026955761131830513,\n", + " 0.006583548616617918,\n", + " -0.009919720701873302,\n", + " -0.011625861749053001,\n", + " -0.004718843847513199,\n", + " -0.0072368294931948185,\n", + " -0.0013802936300635338,\n", + " -0.006250565405935049,\n", + " 0.009380605071783066,\n", + " -0.0057621905580163,\n", + " 0.010782305151224136,\n", + " 0.013547648675739765,\n", + " -0.005140622146427631,\n", + " -0.005632168613374233,\n", + " 0.0007163097034208477,\n", + " -0.009399632923305035,\n", + " 0.011105773970484734,\n", + " -0.010534945875406265,\n", + " -0.013052931055426598,\n", + " -0.004890092182904482,\n", + " 0.02935323864221573,\n", + " -0.001888489001430571,\n", + " 0.00033754162723198533,\n", + " 0.005996864289045334,\n", + " 0.0315350703895092,\n", + " -0.008784406818449497,\n", + " -0.027450479567050934,\n", + " 0.00896834023296833,\n", + " 0.014499028213322163,\n", + " 0.01159414928406477,\n", + " 0.029733791947364807,\n", + " -0.04188608378171921,\n", + " -0.006066631991416216,\n", + " 0.0144609734416008,\n", + " 0.01740390807390213,\n", + " 0.002544941147789359,\n", + " -0.025852160528302193,\n", + " 0.03785223141312599,\n", + " -0.017036041244864464,\n", + " 0.011093088425695896,\n", + " 0.005644853692501783,\n", + " 0.030748596414923668,\n", + " 0.008105755783617496,\n", + " -0.0055275168269872665,\n", + " -0.017239002510905266,\n", + " 0.0063901012763381,\n", + " -0.0008657556609250605,\n", + " 0.0192305576056242,\n", + " -0.010046571493148804,\n", + " -0.025852160528302193,\n", + " 0.007040210533887148,\n", + " -0.011714656837284565,\n", + " -0.027171408757567406,\n", + " -0.0031125976238399744,\n", + " 0.006856277119368315,\n", + " -0.026790855452418327,\n", + " -0.005492632742971182,\n", + " 0.022262288257479668,\n", + " 0.018063532188534737,\n", + " -0.014219957403838634,\n", + " 0.01633836328983307,\n", + " 0.023416629061102867,\n", + " 0.018203066661953926,\n", + " -0.039704252034425735,\n", + " -0.004090933129191399,\n", + " -0.011308735236525536,\n", + " 0.009659676812589169,\n", + " -0.009444030933082104,\n", + " -0.009266439825296402,\n", + " -0.008651213720440865,\n", + " 0.009380605071783066,\n", + " 0.017657609656453133,\n", + " 0.02236376889050007,\n", + " -0.0024339468218386173,\n", + " -0.01397894136607647,\n", + " -0.00952014047652483,\n", + " -0.0038974860217422247,\n", + " 0.007141691166907549,\n", + " -0.011308735236525536,\n", + " 0.0036945249885320663,\n", + " 0.03249913454055786,\n", + " 0.023708386346697807,\n", + " 0.032905057072639465,\n", + " -0.012437705881893635,\n", + " -0.03706575930118561,\n", + " 0.023695699870586395,\n", + " 0.0051342798396945,\n", + " -0.011200912296772003,\n", + " -0.030241193249821663,\n", + " -0.02241450920701027,\n", + " -0.001587218721397221,\n", + " 0.016414472833275795,\n", + " -0.006577205844223499,\n", + " 0.008727324195206165,\n", + " 0.022452564910054207,\n", + " 0.024088937789201736,\n", + " 0.02155192382633686,\n", + " 0.008708296343684196,\n", + " -0.0020581516437232494,\n", + " -0.007090950850397348,\n", + " 0.0181776974350214,\n", + " -0.0023292950354516506,\n", + " 0.029860641807317734,\n", + " 0.0003857052361126989,\n", + " 0.00962162110954523,\n", + " 0.015640685334801674,\n", + " 0.003875287249684334,\n", + " 0.0144356032833457,\n", + " -0.027932511642575264,\n", + " -0.021628035232424736,\n", + " 0.023683015257120132,\n", + " 0.022008586674928665,\n", + " -0.0004213819920551032,\n", + " -0.008137469179928303,\n", + " 0.002119991462677717,\n", + " 0.031154518947005272,\n", + " 0.03320949897170067,\n", + " 0.002744730794802308,\n", + " 0.008035988546907902,\n", + " -0.010604714043438435,\n", + " 0.005102567374706268,\n", + " 0.03298116847872734,\n", + " -0.011759054847061634,\n", + " 0.03754778951406479,\n", + " 0.002018510829657316,\n", + " 0.006868962198495865,\n", + " 0.021704144775867462,\n", + " -0.0078583974391222,\n", + " -0.03206784278154373,\n", + " 0.00159118277952075,\n", + " 0.0040497067384421825,\n", + " 0.014219957403838634,\n", + " 0.03881629556417465,\n", + " 0.0240508820861578,\n", + " 0.005204047542065382,\n", + " 0.022541359066963196,\n", + " 0.005651195999234915,\n", + " -0.027602700516581535,\n", + " -0.007344652432948351,\n", + " -0.0013327245833352208,\n", + " 0.008733666501939297,\n", + " 0.0020835218019783497,\n", + " -0.01879926584661007,\n", + " -0.01371255423873663,\n", + " -0.6864141821861267,\n", + " -0.029860641807317734,\n", + " 0.004097275901585817,\n", + " -0.010833045467734337,\n", + " 0.02160266414284706,\n", + " 0.0335393100976944,\n", + " -0.012323539704084396,\n", + " -0.010446150787174702,\n", + " -0.00034368596971035004,\n", + " 0.03544206917285919,\n", + " -0.03052026592195034,\n", + " 0.002197687514126301,\n", + " 0.004687131382524967,\n", + " -0.0027272887527942657,\n", + " -0.009824582375586033,\n", + " -0.00333934323862195,\n", + " 0.02719677798449993,\n", + " -0.022972650825977325,\n", + " -0.007959878072142601,\n", + " 0.020854245871305466,\n", + " 0.004791783168911934,\n", + " 0.006983127910643816,\n", + " -0.010978923179209232,\n", + " 0.0017330968985334039,\n", + " -0.0051342798396945,\n", + " 0.011296049691736698,\n", + " -0.0020407098345458508,\n", + " 0.005349925719201565,\n", + " -0.001236000913195312,\n", + " 0.016972616314888,\n", + " -0.0020359528716653585,\n", + " 0.018875375390052795,\n", + " -0.006488410290330648,\n", + " 0.005441892426460981,\n", + " 0.04262181743979454,\n", + " 0.004484170116484165,\n", + " -0.005946123972535133,\n", + " 0.020600544288754463,\n", + " 0.03978036344051361,\n", + " 0.05337874963879585,\n", + " -0.03559429198503494,\n", + " -0.013623759150505066,\n", + " 0.0145878242328763,\n", + " 0.008930285461246967,\n", + " -0.011511695571243763,\n", + " 0.0011789181735366583,\n", + " 0.025471609085798264,\n", + " 0.01716289296746254,\n", + " -0.0055877710692584515,\n", + " -0.0156660545617342,\n", + " 0.013573018833994865,\n", + " 0.01778445951640606,\n", + " 0.01635104790329933,\n", + " 0.00512159476056695,\n", + " -0.018101586028933525,\n", + " 0.02704455703496933,\n", + " 0.010972580872476101,\n", + " -0.0004316885897424072,\n", + " -0.0017441964009776711,\n", + " -0.002383206505328417,\n", + " -0.010560316033661366,\n", + " 0.0014667105861008167,\n", + " -0.0103446701541543,\n", + " 0.008676583878695965,\n", + " -0.022579414770007133,\n", + " 0.0035232766531407833,\n", + " -0.007046553306281567,\n", + " 0.010287587530910969,\n", + " 0.022097382694482803,\n", + " -0.014321438036859035,\n", + " 0.0228458009660244,\n", + " 0.01986481063067913,\n", + " -0.010553973726928234,\n", + " 0.01009731087833643,\n", + " 0.014638564549386501,\n", + " 0.01080133207142353,\n", + " 0.009279124438762665,\n", + " -0.006564520765095949,\n", + " -0.011581463739275932,\n", + " 0.006437669973820448,\n", + " -0.012158634141087532,\n", + " -0.0026115376967936754,\n", + " -0.039272960275411606,\n", + " -0.0015031801303848624,\n", + " 0.03567039966583252,\n", + " 0.017200946807861328,\n", + " -0.03511225804686546,\n", + " -0.0064027863554656506,\n", + " -0.005089882295578718,\n", + " -0.0241523627191782,\n", + " 0.016845766454935074,\n", + " 0.024672450497746468,\n", + " -0.031890250742435455,\n", + " -0.0011583049781620502,\n", + " -0.012431363575160503,\n", + " 0.0085116783156991,\n", + " -0.006142742466181517,\n", + " 0.03848648443818092,\n", + " 0.0411757193505764,\n", + " -0.03229617327451706,\n", + " 0.012298169545829296,\n", + " -0.0018742182292044163,\n", + " -0.003532790346071124,\n", + " -0.004239982925355434,\n", + " 0.014308752492070198,\n", + " 0.03046952560544014,\n", + " 0.016756970435380936,\n", + " 0.0018076216802001,\n", + " 0.017429279163479805,\n", + " -0.011156514286994934,\n", + " -0.008594131097197533,\n", + " -0.01754344440996647,\n", + " 0.017467333003878593,\n", + " 0.00509622460231185,\n", + " -0.0064598689787089825,\n", + " -0.02501494623720646,\n", + " 0.0156660545617342,\n", + " -0.004465142730623484,\n", + " 0.015830960124731064,\n", + " -0.01947157457470894,\n", + " 0.009425003081560135,\n", + " -0.011784425005316734,\n", + " 0.00889222975820303,\n", + " -0.0008221507305279374,\n", + " 0.007655436173081398,\n", + " 0.001875803922303021,\n", + " -0.026790855452418327,\n", + " -0.02935323864221573,\n", + " -0.015919756144285202,\n", + " -0.004804468248039484,\n", + " -0.007458817679435015,\n", + " 0.02024536207318306,\n", + " 0.03544206917285919,\n", + " -0.0024339468218386173,\n", + " -0.0031268682796508074,\n", + " -0.0043795183300971985,\n", + " 0.014422918669879436,\n", + " 0.006161769852042198,\n", + " 0.01831723377108574,\n", + " -0.015970496460795403,\n", + " -0.0316365510225296,\n", + " 0.009006395936012268,\n", + " -0.014296067878603935,\n", + " -0.013611074537038803,\n", + " 0.007224144414067268,\n", + " -0.01991555094718933,\n", + " -0.025826791301369667,\n", + " 0.004401717334985733,\n", + " 0.006646973546594381,\n", + " 0.03052026592195034,\n", + " -0.012203032150864601,\n", + " -0.02313755825161934,\n", + " -0.012367937713861465,\n", + " -0.015348928049206734,\n", + " 0.02285848557949066,\n", + " -0.0053974948823452,\n", + " -0.03270209580659866,\n", + " -0.004297065548598766,\n", + " -0.004645904991775751,\n", + " -0.02859213575720787,\n", + " 0.027704181149601936,\n", + " 0.01402968168258667,\n", + " -0.0065328083001077175,\n", + " -0.00420509884133935,\n", + " 0.01038906816393137,\n", + " -0.03534058853983879,\n", + " 0.0032600616104900837,\n", + " 0.0228965412825346,\n", + " -0.024596339091658592,\n", + " -0.026968447491526604,\n", + " -0.004877407103776932,\n", + " -0.02260478399693966,\n", + " -0.006247394252568483,\n", + " -0.001054445980116725,\n", + " -0.01755612902343273,\n", + " 0.011600491590797901,\n", + " -0.027171408757567406,\n", + " -0.024266527965664864,\n", + " -0.002250013407319784,\n", + " -0.011074061505496502,\n", + " -0.004347805865108967,\n", + " 0.018837321549654007,\n", + " 0.006434498820453882,\n", + " -0.022769691422581673,\n", + " 0.015678739175200462,\n", + " -0.004877407103776932,\n", + " 0.02468513511121273,\n", + " 0.012431363575160503,\n", + " -0.023987457156181335,\n", + " -0.01007194072008133,\n", + " 0.021057207137346268,\n", + " 0.027298258617520332,\n", + " 0.01277386024594307,\n", + " -0.013370057567954063,\n", + " -0.005537030752748251,\n", + " -0.02019462175667286,\n", + " 0.0053974948823452,\n", + " 0.030190452933311462,\n", + " 0.01494300551712513,\n", + " 0.009444030933082104,\n", + " 0.016186142340302467,\n", + " -0.007541270926594734,\n", + " 0.007300254423171282,\n", + " -0.027019187808036804,\n", + " 0.022021271288394928,\n", + " -0.03201710432767868,\n", + " -0.0016078319167718291,\n", + " -0.004157529678195715,\n", + " 0.006031747907400131,\n", + " -0.00013874289288651198,\n", + " -0.019991662353277206,\n", + " 0.0004197963571641594,\n", + " 0.019420834258198738,\n", + " -0.03871481493115425,\n", + " 0.017340483143925667,\n", + " 0.023898661136627197,\n", + " -0.012298169545829296,\n", + " 0.02260478399693966,\n", + " 0.008657556027173996,\n", + " -0.012843627482652664,\n", + " 0.002595681231468916,\n", + " -0.020473694428801537,\n", + " 0.015285502187907696,\n", + " -0.005568743217736483,\n", + " 0.02227497287094593,\n", + " 0.024672450497746468,\n", + " 0.008949313312768936,\n", + " 0.015564573928713799,\n", + " 0.0016030750703066587,\n", + " -0.004119474906474352,\n", + " -0.023505425080657005,\n", + " 0.003209321293979883,\n", + " 0.0170740969479084,\n", + " 0.017036041244864464,\n", + " 0.008479965850710869,\n", + " 0.000265197129920125,\n", + " 0.0073763648979365826,\n", + " -0.0108203599229455,\n", + " 0.014714675024151802,\n", + " -0.0013795007253065705,\n", + " 0.018063532188534737,\n", + " -0.006894332356750965,\n", + " 0.007763259578496218,\n", + " -0.014016996137797832,\n", + " 0.011638546362519264,\n", + " 0.011600491590797901,\n", + " 0.029327869415283203,\n", + " -0.005432378966361284,\n", + " -0.017226317897439003,\n", + " 0.006463040132075548,\n", + " -0.0017441964009776711,\n", + " -0.0035137629602104425,\n", + " -0.024456804618239403,\n", + " 0.02767881006002426,\n", + " 0.007433447986841202,\n", + " -0.015120596624910831,\n", + " 0.020955726504325867,\n", + " 0.005080368369817734,\n", + " 0.029251758009195328,\n", + " 0.025141797959804535,\n", + " 0.004027507733553648,\n", + " 0.003006360260769725,\n", + " 0.00889222975820303,\n", + " 0.01033832784742117,\n", + " 0.018685100600123405,\n", + " -0.0005585392354987562,\n", + " -0.006405957508832216,\n", + " 0.013116356916725636,\n", + " 0.013179781846702099,\n", + " -0.020308788865804672,\n", + " -0.02564920112490654,\n", + " -0.005530687980353832,\n", + " 0.002032781485468149,\n", + " -0.01754344440996647,\n", + " 0.020524434745311737,\n", + " 0.012989506125450134,\n", + " -0.035315219312906265,\n", + " 0.013623759150505066,\n", + " 0.01869778521358967,\n", + " 0.020334158092737198,\n", + " -0.021678775548934937,\n", + " -0.027399739250540733,\n", + " -0.006104687228798866,\n", + " 0.004135331138968468,\n", + " 0.0038372320123016834,\n", + " 0.005194534081965685,\n", + " -0.027932511642575264,\n", + " -0.0003151445707771927,\n", + " -0.003237862605601549,\n", + " 0.022287657484412193,\n", + " -0.00013160755042918026,\n", + " -0.004766413010656834,\n", + " 8.805218385532498e-05,\n", + " -0.00954551063477993,\n", + " -0.0090127382427454,\n", + " -0.013446168042719364,\n", + " 0.020042402669787407,\n", + " -0.011207254603505135,\n", + " 0.000565278169233352,\n", + " -0.028516024351119995,\n", + " 0.00834042951464653,\n", + " -0.0005803416715934873,\n", + " -0.0072621991857886314,\n", + " -0.007370022591203451,\n", + " 0.026308823376893997,\n", + " -0.0006679479265585542,\n", + " -0.012964135967195034,\n", + " -0.0011043933918699622,\n", + " -0.0009379019611515105,\n", + " 0.019205188378691673,\n", + " -0.019788701087236404,\n", + " -0.01402968168258667,\n", + " -0.017378538846969604,\n", + " 0.013573018833994865,\n", + " 0.0025211565662175417,\n", + " -0.008955655619502068,\n", + " -0.020017031580209732,\n", + " -0.011315077543258667,\n", + " 0.028186213225126266,\n", + " 0.010084626264870167,\n", + " -0.013052931055426598,\n", + " -0.01628762297332287,\n", + " -0.00637741619721055,\n", + " 0.02265552431344986,\n", + " 0.08037257194519043,\n", + " 0.020740080624818802,\n", + " -0.018494823947548866,\n", + " 0.0133827431127429,\n", + " 0.019116392359137535,\n", + " -0.026968447491526604,\n", + " -0.022769691422581673,\n", + " -0.00637741619721055,\n", + " 0.027983251959085464,\n", + " -0.0181269571185112,\n", + " -0.003780149156227708,\n", + " -0.009342550300061703,\n", + " 0.005977836437523365,\n", + " -0.007890109904110432,\n", + " 0.024025512859225273,\n", + " -0.0073763648979365826,\n", + " 0.0037420939188450575,\n", + " -0.008448252454400063,\n", + " 0.002061323029920459,\n", + " 0.0016300308052450418,\n", + " -0.005407008808106184,\n", + " -0.003770635463297367,\n", + " 0.0002251598925795406,\n", + " 0.012190346606075764,\n", + " -0.014207271859049797,\n", + " 0.0039799390360713005,\n", + " -0.002403819700703025,\n", + " 0.016858451068401337,\n", + " 0.02816084213554859,\n", + " -0.029632311314344406,\n", + " -0.0031649235170334578,\n", + " 0.0075349281542003155,\n", + " 0.015780219808220863,\n", + " 0.006272764410823584,\n", + " 0.021095262840390205,\n", + " 0.020524434745311737,\n", + " -0.005191362462937832,\n", + " 0.014511713758111,\n", + " 0.032955799251794815,\n", + " -0.03166192024946213,\n", + " 0.011797109618782997,\n", + " 0.007496872916817665,\n", + " 0.004591993521898985,\n", + " 0.004842523485422134,\n", + " 0.023936716839671135,\n", + " 0.00018294241453986615,\n", + " -0.01769566535949707,\n", + " 0.016566693782806396,\n", + " 0.005981008056551218,\n", + " -0.029708420857787132,\n", + " 0.0364568755030632,\n", + " -0.005235760472714901,\n", + " -0.010458835400640965,\n", + " 0.0021723173558712006,\n", + " 0.0058985548093914986,\n", + " 0.02554772049188614,\n", + " -0.019446203485131264,\n", + " -0.004338291939347982,\n", + " -0.012964135967195034,\n", + " 0.0016744284657761455,\n", + " -0.01036369800567627,\n", + " -0.020131196826696396,\n", + " -0.002717775059863925,\n", + " -0.009507455863058567,\n", + " -0.001725168782286346,\n", + " -0.025484293699264526,\n", + " -0.011740026995539665,\n", + " -0.008492650464177132,\n", + " -0.006837249733507633,\n", + " -0.01501911599189043,\n", + " -0.02165340445935726,\n", + " -0.018291862681508064,\n", + " -0.01890074647963047,\n", + " -0.010433465242385864,\n", + " 0.015082541853189468,\n", + " 0.030444154515862465,\n", + " 0.010325642302632332,\n", + " -0.0013271748321130872,\n", + " 0.004636391066014767,\n", + " 0.010579343885183334,\n", + " -0.016858451068401337,\n", + " -0.01605929248034954,\n", + " -0.0008498993120156229,\n", + " -0.026156602427363396,\n", + " 0.0026384934317320585,\n", + " 0.009773842059075832,\n", + " 0.013725239783525467,\n", + " -0.006478896830230951,\n", + " 0.0120254410430789,\n", + " 0.01193030271679163,\n", + " 0.010579343885183334,\n", + " 0.008657556027173996,\n", + " -0.010573001578450203,\n", + " 0.005739991553127766,\n", + " 0.02256673015654087,\n", + " -0.01072522159665823,\n", + " 0.01195567287504673,\n", + " 0.03455411642789841,\n", + " 0.019078336656093597,\n", + " -0.0053974948823452,\n", + " 0.03318412974476814,\n", + " -0.016756970435380936,\n", + " 0.0008776478935033083,\n", + " 8.19574052002281e-05,\n", + " 0.014511713758111,\n", + " -0.007553956005722284,\n", + " 0.029962122440338135,\n", + " 0.005058169364929199,\n", + " -0.020321473479270935,\n", + " -0.033285610377788544,\n", + " 0.03171266242861748,\n", + " -0.0057621905580163,\n", + " 0.014866895973682404,\n", + " 0.012526500970125198,\n", + " 0.011004293337464333,\n", + " 0.015069856308400631,\n", + " 0.015589944086968899,\n", + " 0.011238967068493366,\n", + " -0.0001285353791899979,\n", + " -0.009767499752342701,\n", + " -0.008467280305922031,\n", + " -0.021374333649873734,\n", + " -0.000982299679890275,\n", + " 0.02935323864221573,\n", + " -0.025484293699264526,\n", + " 0.021387018263339996,\n", + " -0.004198756534606218,\n", + " -0.015513833612203598,\n", + " -0.003520105266943574,\n", + " 0.0032077357172966003,\n", + " 0.011720999144017696,\n", + " 0.007370022591203451,\n", + " 0.0016379589214920998,\n", + " -0.009780184365808964,\n", + " -0.04183534160256386,\n", + " -0.011238967068493366,\n", + " -0.0036723262164741755,\n", + " 0.012456733733415604,\n", + " -0.013509593904018402,\n", + " 0.0011694043641909957,\n", + " -0.03095155768096447,\n", + " -0.008746352046728134,\n", + " 0.012431363575160503,\n", + " -0.04285014793276787,\n", + " 0.019902866333723068,\n", + " -0.025636514648795128,\n", + " -0.0015420281561091542,\n", + " -0.014118476770818233,\n", + " -0.0023039248771965504,\n", + " 0.01402968168258667,\n", + " -0.015780219808220863,\n", + " -0.010503233410418034,\n", + " -0.024609025567770004,\n", + " -0.015792904421687126,\n", + " -0.002170731546357274,\n", + " -0.03572114184498787,\n", + " 0.0079091377556324,\n", + " -0.015894385054707527,\n", + " 0.040516097098588943,\n", + " 0.0180254764854908,\n", + " 0.03008897230029106,\n", + " -0.003612072207033634,\n", + " 0.004699816461652517,\n", + " 0.024380693212151527,\n", + " -0.026816226541996002,\n", + " -0.0038435745518654585,\n", + " -0.0016680859262123704,\n", + " -0.0030158739537000656,\n", + " -0.016427159309387207,\n", + " -0.0071036359295248985,\n", + " 0.029632311314344406,\n", + " 0.005581428296864033,\n", + " 0.026587894186377525,\n", + " 0.018811950460076332,\n", + " -0.01750538870692253,\n", + " 0.011137486435472965,\n", + " -0.003894314868375659,\n", + " 0.008911257609724998,\n", + " -0.012203032150864601,\n", + " -0.016173457726836205,\n", + " 0.020080456510186195,\n", + " -0.0058287871070206165,\n", + " 0.016224198043346405,\n", + " -0.00724317179992795,\n", + " -0.008689269423484802,\n", + " -0.0042082699947059155,\n", + " 0.010465177707374096,\n", + " 0.03249913454055786,\n", + " 0.03726872056722641,\n", + " 0.006450355052947998,\n", + " 0.022186176851391792,\n", + " 0.0006576413288712502,\n", + " -0.004956688731908798,\n", + " 0.0048139821738004684,\n", + " -0.003409111173823476,\n", + " -0.02694307640194893,\n", + " -0.0016744284657761455,\n", + " 0.01082670222967863,\n", + " 0.0063139908015728,\n", + " 0.026968447491526604,\n", + " -0.0011440342059358954,\n", + " 0.016135402023792267,\n", + " -0.012919737957417965,\n", + " 0.024190418422222137,\n", + " -0.003805519314482808,\n", + " 0.005419693887233734,\n", + " -0.0115243811160326,\n", + " -0.011974700726568699,\n", + " -0.001221730257384479,\n", + " -0.025864847004413605,\n", + " -0.010515918023884296,\n", + " -0.034833185374736786,\n", + " -0.0113975303247571,\n", + " -0.017137521877884865,\n", + " 0.006215681787580252,\n", + " 0.01957305520772934,\n", + " -0.011689286679029465,\n", + " 0.010541288182139397,\n", + " -0.014714675024151802,\n", + " -0.037623900920152664,\n", + " -0.004607849754393101,\n", + " 0.001599110895767808,\n", + " 0.044955868273973465,\n", + " -0.010408095084130764,\n", + " 0.007902795448899269,\n", + " 0.012012756429612637,\n", + " -0.004401717334985733,\n", + " 0.0011884319828823209,\n", + " 0.016262251883745193,\n", + " 0.012437705881893635,\n", + " 0.004867893643677235,\n", + " -0.0006806330056861043,\n", + " 0.018114272505044937,\n", + " -0.008594131097197533,\n", + " -0.005032799206674099,\n", + " -0.01996629126369953,\n", + " -0.009291809983551502,\n", + " -0.02439337968826294,\n", + " -0.010687166824936867,\n", + " 0.02795788273215294,\n", + " 0.0008011410827748477,\n", + " 0.00036429919418878853,\n", + " -0.008682926185429096,\n", + " -0.017657609656453133,\n", + " -0.0003391272621229291,\n", + " 0.011232624761760235,\n", + " -0.015171336941421032,\n", + " -0.006111030001193285,\n", + " -0.024621710181236267,\n", + " -4.697437907452695e-05,\n", + " -0.04183534160256386,\n", + " 0.009412317536771297,\n", + " -0.018964171409606934,\n", + " 0.0034598512575030327,\n", + " -0.030621744692325592,\n", + " -0.01260895375162363,\n", + " 0.007395392749458551,\n", + " 0.015323557890951633,\n", + " -0.027704181149601936,\n", + " -0.006507438141852617,\n", + " -0.01874852553009987,\n", + " 0.012805572710931301,\n", + " -0.025129113346338272,\n", + " -0.002119991462677717,\n", + " 0.013408113270998001,\n", + " 0.002923907246440649,\n", + " -0.021945161744952202,\n", + " -0.019978975877165794,\n", + " -0.005933438893407583,\n", + " 0.025332072749733925,\n", + " -0.014042366296052933,\n", + " -0.01635104790329933,\n", + " -0.0061300573870539665,\n", + " 0.012602611444890499,\n", + " 0.016947245225310326,\n", + " -0.019776014611124992,\n", + " 0.00030107208294793963,\n", + " -0.028718985617160797,\n", + " -0.005004257895052433,\n", + " 0.015577259473502636,\n", + " 0.021539239212870598,\n", + " -0.001147205475717783,\n", + " -0.004157529678195715,\n", + " 0.00729391211643815,\n", + " -0.009583566337823868,\n", + " 0.0025306702591478825,\n", + " 0.003922855947166681,\n", + " -0.014016996137797832,\n", + " 0.009919720701873302,\n", + " -0.019370093941688538,\n", + " -0.0006207753322087228,\n", + " -0.016909191384911537,\n", + " -0.0015380640979856253,\n", + " 0.003497906494885683,\n", + " 0.020904986187815666,\n", + " 0.00032624401501379907,\n", + " -0.006970442831516266,\n", + " 0.024368008598685265,\n", + " -0.02843991480767727,\n", + " 0.017480019479990005,\n", + " -0.030723225325345993,\n", + " 0.006095173303037882,\n", + " -0.02502763271331787,\n", + " 0.007813999429345131,\n", + " 0.010509575717151165,\n", + " 0.006463040132075548,\n", + " 0.01405505184084177,\n", + " -0.020093142986297607,\n", + " 0.0032568902242928743,\n", + " -0.025230593979358673,\n", + " -0.005223075393587351,\n", + " -0.0036025582812726498,\n", + " 0.022871172055602074,\n", + " -0.024862727150321007,\n", + " 0.011245309375226498,\n", + " 0.0003555782022885978,\n", + " 0.010985265485942364,\n", + " -0.031611181795597076,\n", + " -0.0079091377556324,\n", + " 0.033234868198633194,\n", + " 0.0014722603373229504,\n", + " 0.024888096377253532,\n", + " 0.03597484156489372,\n", + " -0.02434263937175274,\n", + " 0.007186089176684618,\n", + " 0.005543373059481382,\n", + " 0.009488428011536598,\n", + " 0.012190346606075764,\n", + " -0.02260478399693966,\n", + " -0.008048673160374165,\n", + " -0.009995831176638603,\n", + " 0.028313063085079193,\n", + " 0.0039482261054217815,\n", + " -0.011270679533481598,\n", + " -0.011600491590797901,\n", + " -0.0031236971262842417,\n", + " -0.016465213149785995,\n", + " 0.015551889315247536,\n", + " -0.02318829856812954,\n", + " -0.0029540343675762415,\n", + " 0.018063532188534737,\n", + " 0.0026860623620450497,\n", + " -0.026486415416002274,\n", + " 0.011010635644197464,\n", + " -0.013293947093188763,\n", + " -0.012298169545829296,\n", + " -0.013192467391490936,\n", + " -0.005067683290690184,\n", + " -0.030215824022889137,\n", + " -0.01967453584074974,\n", + " -0.0076364087872207165,\n", + " 0.0023784495424479246,\n", + " 0.01373792439699173,\n", + " -0.01164488960057497,\n", + " -0.025573089718818665,\n", + " -0.008727324195206165,\n", + " -0.007002155762165785,\n", + " -0.010395410470664501,\n", + " 0.026410304009914398,\n", + " 0.0037008675280958414,\n", + " 0.021107947453856468,\n", + " -0.0228458009660244,\n", + " 0.011340447701513767,\n", + " 0.013890145346522331,\n", + " -0.012976820580661297,\n", + " 0.030444154515862465,\n", + " -0.0127040920779109,\n", + " -0.009558196179568768,\n", + " -0.006440841592848301,\n", + " -0.002129505155608058,\n", + " -0.0023261236492544413,\n", + " -0.0010695095406845212,\n", + " -0.004468313883990049,\n", + " -0.0108964703977108,\n", + " 0.004598335828632116,\n", + " 0.021526554599404335,\n", + " 0.010833045467734337,\n", + " 0.011238967068493366,\n", + " -0.008714639581739902,\n", + " -0.0001291299849981442,\n", + " -0.004224126227200031,\n", + " -0.019116392359137535,\n", + " 0.007579326163977385,\n", + " -0.008524362929165363,\n", + " 0.011175542138516903,\n", + " -0.0267654862254858,\n", + " -0.011359475553035736,\n", + " 0.006513780448585749,\n", + " -0.011974700726568699,\n", + " -0.026410304009914398,\n", + " -0.005882698576897383,\n", + " 0.017873255535960197,\n", + " -0.005765361711382866,\n", + " 0.00962162110954523,\n", + " -0.022300343960523605,\n", + " -0.0049249762669205666,\n", + " -0.010985265485942364,\n", + " -0.02945471927523613,\n", + " 0.01397894136607647,\n", + " -0.013002190738916397,\n", + " 0.029530830681324005,\n", + " 0.024723190814256668,\n", + " -0.011695628985762596,\n", + " -0.010186106897890568,\n", + " 0.0007638787501491606,\n", + " 0.0013168682344257832,\n", + " -0.013623759150505066,\n", + " -0.021513869985938072,\n", + " 0.007129006087779999,\n", + " -0.016997985541820526,\n", + " -0.0012264872202649713,\n", + " -0.02950545959174633,\n", + " 0.001980455592274666,\n", + " -0.0230995025485754,\n", + " 0.006710398942232132,\n", + " -0.022021271288394928,\n", + " -0.01515865232795477,\n", + " -0.01740390807390213,\n", + " 0.024723190814256668,\n", + " -0.0084609379991889,\n", + " -0.02117137238383293,\n", + " -0.0020851073786616325,\n", + " -0.022287657484412193,\n", + " 0.003605729667469859,\n", + " -0.0010718879057094455,\n", + " -0.0101924492046237,\n", + " 0.006742111872881651,\n", + " 0.003875287249684334,\n", + " -0.01779714599251747,\n", + " -0.006526465527713299,\n", + " -0.00012070631782989949,\n", + " -0.023302463814616203,\n", + " -0.012818257324397564,\n", + " 0.015348928049206734,\n", + " -0.007027525920420885,\n", + " 0.02208469808101654,\n", + " 0.20864394307136536,\n", + " -0.001875803922303021,\n", + " 0.005407008808106184,\n", + " 0.036862798035144806,\n", + " -0.010592028498649597,\n", + " 0.030139712616801262,\n", + " 0.021767569705843925,\n", + " -0.0037262376863509417,\n", + " -0.006472554057836533,\n", + " 0.02578873559832573,\n", + " -0.0026051951572299004,\n", + " 0.012907053343951702,\n", + " -0.021615350618958473,\n", + " 0.005200876388698816,\n", + " 0.014854210428893566,\n", + " 0.008467280305922031,\n", + " -0.005445064045488834,\n", + " -0.0027685153763741255,\n", + " -0.014410233125090599,\n", + " -0.03031730465590954,\n", + " -0.014473658986389637,\n", + " -0.006310819648206234,\n", + " -0.026841595768928528,\n", + " -0.004344634711742401,\n", + " 0.010883784852921963,\n", + " 0.0192812979221344,\n", + " -0.0085116783156991,\n", + " -0.0008475208887830377,\n", + " 0.03267672657966614,\n", + " 0.018342602998018265,\n", + " -0.017391223460435867,\n", + " -0.0027986422646790743,\n", + " -0.0115243811160326,\n", + " 0.02255404368042946,\n", + " -0.014714675024151802,\n", + " 0.0078583974391222,\n", + " 0.016274938359856606,\n", + " 0.018215753138065338,\n", + " 0.012399650178849697,\n", + " -0.003875287249684334,\n", + " 0.0206893403083086,\n", + " 0.0012185589876025915,\n", + " -0.0075666410848498344,\n", + " -0.015107912011444569,\n", + " 0.0019408148946240544,\n", + " 0.0253574438393116,\n", + " ...]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text = 'the quick brown fox jumped over the lazy dog'\n", + "model = 'text-embedding-ada-002'\n", + "openai.Embedding()\\\n", + " .create(input=[text], engine='text-embedding-ada-002')[\"data\"][0][\"embedding\"]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "gather": { + "logged": 1674829555255 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.9161762609368851\n", + "0.8334429695093547\n", + "0.7820358471285385\n" + ] + } + ], + "source": [ + "# compare several words\n", + "automobile_embedding = openai.Embedding.create(input='automobile', engine=model)[\"data\"][0][\"embedding\"]\n", + "vehicle_embedding = openai.Embedding.create(input='vehicle', engine=model)[\"data\"][0][\"embedding\"]\n", + "dinosaur_embedding = openai.Embedding.create(input='dinosaur', engine=model)[\"data\"][0][\"embedding\"]\n", + "stick_embedding = openai.Embedding.create(input='stick', engine=model)[\"data\"][0][\"embedding\"]\n", + "\n", + "print(cosine_similarity(automobile_embedding, vehicle_embedding))\n", + "print(cosine_similarity(automobile_embedding, dinosaur_embedding))\n", + "print(cosine_similarity(automobile_embedding, stick_embedding))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Comparing article from cnn daily news dataset\n", + "source: https://huggingface.co/datasets/cnn_dailymail\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "gather": { + "logged": 1674831122093 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
articleshighligths
0BREMEN, Germany -- Carlos Alberto, who scored ...Werder Bremen pay a club record $10.7 million ...
1(CNN) -- Football superstar, celebrity, fashio...Beckham has agreed to a five-year contract wit...
2LOS ANGELES, California (CNN) -- Youssif, the ...Boy on meeting Spider-Man: \"It was my favorite...
\n", + "
" + ], + "text/plain": [ + " articles \\\n", + "0 BREMEN, Germany -- Carlos Alberto, who scored ... \n", + "1 (CNN) -- Football superstar, celebrity, fashio... \n", + "2 LOS ANGELES, California (CNN) -- Youssif, the ... \n", + "\n", + " highligths \n", + "0 Werder Bremen pay a club record $10.7 million ... \n", + "1 Beckham has agreed to a five-year contract wit... \n", + "2 Boy on meeting Spider-Man: \"It was my favorite... " + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "cnn_daily_articles = ['BREMEN, Germany -- Carlos Alberto, who scored in FC Porto\\'s Champions League final victory against Monaco in 2004, has joined Bundesliga club Werder Bremen for a club record fee of 7.8 million euros ($10.7 million). Carlos Alberto enjoyed success at FC Porto under Jose Mourinho. \"I\\'m here to win titles with Werder,\" the 22-year-old said after his first training session with his new club. \"I like Bremen and would only have wanted to come here.\" Carlos Alberto started his career with Fluminense, and helped them to lift the Campeonato Carioca in 2002. In January 2004 he moved on to FC Porto, who were coached by José Mourinho, and the club won the Portuguese title as well as the Champions League. Early in 2005, he moved to Corinthians, where he impressed as they won the Brasileirão,but in 2006 Corinthians had a poor season and Carlos Alberto found himself at odds with manager, Emerson Leão. Their poor relationship came to a climax at a Copa Sul-Americana game against Club Atlético Lanús, and Carlos Alberto declared that he would not play for Corinthians again while Leão remained as manager. Since January this year he has been on loan with his first club Fluminense. Bundesliga champions VfB Stuttgart said on Sunday that they would sign a loan agreement with Real Zaragoza on Monday for Ewerthon, the third top Brazilian player to join the German league in three days. A VfB spokesman said Ewerthon, who played in the Bundesliga for Borussia Dortmund from 2001 to 2005, was expected to join the club for their pre-season training in Austria on Monday. On Friday, Ailton returned to Germany where he was the league\\'s top scorer in 2004, signing a one-year deal with Duisburg on a transfer from Red Star Belgrade. E-mail to a friend .',\n", + " '(CNN) -- Football superstar, celebrity, fashion icon, multimillion-dollar heartthrob. Now, David Beckham is headed for the Hollywood Hills as he takes his game to U.S. Major League Soccer. CNN looks at how Bekham fulfilled his dream of playing for Manchester United, and his time playing for England. The world\\'s famous footballer has begun a five-year contract with the Los Angeles Galaxy team, and on Friday Beckham will meet the press and reveal his new shirt number. This week, we take an in depth look at the life and times of Beckham, as CNN\\'s very own \"Becks,\" Becky Anderson, sets out to examine what makes the man tick -- as footballer, fashion icon and global phenomenon. It\\'s a long way from the streets of east London to the Hollywood Hills and Becky charts Beckham\\'s incredible rise to football stardom, a journey that has seen his skills grace the greatest stages in world soccer. She goes in pursuit of the current hottest property on the sports/celebrity circuit in the U.S. and along the way explores exactly what\\'s behind the man with the golden boot. CNN will look back at the life of Beckham, the wonderfully talented youngster who fulfilled his dream of playing for Manchester United, his marriage to pop star Victoria, and the trials and tribulations of playing for England. We\\'ll look at the highs (scoring against Greece), the lows (being sent off during the World Cup), the Man. U departure for the Galacticos of Madrid -- and now the Home Depot stadium in L.A. We\\'ll ask how Beckham and his family will adapt to life in Los Angeles -- the people, the places to see and be seen and the celebrity endorsement. Beckham is no stranger to exposure. He has teamed with Reggie Bush in an Adidas commercial, is the face of Motorola, is the face on a PlayStation game and doesn\\'t need fashion tips as he has his own international clothing line. But what does the star couple need to do to become an accepted part of Tinseltown\\'s glitterati? The road to major league football in the U.S.A. is a well-worn route for some of the world\\'s greatest players. We talk to some of the former greats who came before him and examine what impact these overseas stars had on U.S. soccer and look at what is different now. We also get a rare glimpse inside the David Beckham academy in L.A, find out what drives the kids and who are their heroes. The perception that in the U.S.A. soccer is a \"game for girls\" after the teenage years is changing. More and more young kids are choosing the European game over the traditional U.S. sports. E-mail to a friend .',\n", + " 'LOS ANGELES, California (CNN) -- Youssif, the 5-year-old burned Iraqi boy, rounded the corner at Universal Studios when suddenly the little boy hero met his favorite superhero. Youssif has always been a huge Spider-Man fan. Meeting him was \"my favorite thing,\" he said. Spider-Man was right smack dab in front of him, riding a four-wheeler amid a convoy of other superheroes. The legendary climber of buildings and fighter of evil dismounted, walked over to Youssif and introduced himself. Spidey then gave the boy from a far-away land a gentle hug, embracing him in his iconic blue and red tights. He showed Youssif a few tricks, like how to shoot a web from his wrist. Only this time, no web was spun. \"All right Youssif!\" Spider-Man said after the boy mimicked his wrist movement. Other superheroes crowded around to get a closer look. Even the Green Goblin stopped his villainous ways to tell the boy hi. Youssif remained unfazed. He didn\\'t take a liking to Spider-Man\\'s nemesis. Spidey was just too cool. \"It was my favorite thing,\" the boy said later. \"I want to see him again.\" He then felt compelled to add: \"I know it\\'s not the real Spider-Man.\" This was the day of dreams when the boy\\'s nightmares were, at least temporarily, forgotten. He met SpongeBob, Lassie and a 3-year-old orangutan named Archie. The hairy, brownish-red primate took to the boy, grabbing his hand and holding it. Even when Youssif pulled away, Archie would inch his hand back toward the boy\\'s and then snatch it. See Youssif enjoy being a boy again » . The boy giggled inside a play area where sponge-like balls shot out of toy guns. It was a far different artillery than what he was used to seeing in central Baghdad, as recently as a week ago. He squealed with delight and raced around the room collecting as many balls as he could. He rode a tram through the back stages at Universal Studios. At one point, the car shook. Fire and smoke filled the air, debris cascaded down and a big rig skidded toward the vehicle. The boy and his family survived the pretend earthquake unscathed. \"Even I was scared,\" the dad said. \"Well, I wasn\\'t,\" Youssif replied. The father and mother grinned from ear to ear throughout the day. Youssif pushed his 14-month-old sister, Ayaa, in a stroller. \"Did you even need to ask us if we were interested in coming here?\" Youssif\\'s father said in amazement. \"Other than my wedding day, this is the happiest day of my life,\" he said. Just a day earlier, the mother and father talked about their journey out of Iraq and to the United States. They also discussed that day nine months ago when masked men grabbed their son outside the family home, doused him in gas and set him on fire. His mother heard her boy screaming from inside. The father sought help for his boy across Baghdad, but no one listened. He remembers his son\\'s two months of hospitalization. The doctors didn\\'t use anesthetics. He could hear his boy\\'s piercing screams from the other side of the hospital. Watch Youssif meet his doctor and play with his little sister » . The father knew that speaking to CNN would put his family\\'s lives in jeopardy. The possibility of being killed was better than seeing his son suffer, he said. \"Anything for Youssif,\" he said. \"We had to do it.\" They described a life of utter chaos in Baghdad. Neighbors had recently given birth to a baby girl. Shortly afterward, the father was kidnapped and killed. Then, there was the time when some girls wore tanktops and jeans. They were snatched off the street by gunmen. The stories can be even more gruesome. The couple said they had heard reports that a young girl was kidnapped and beheaded --and her killers sewed a dog\\'s head on the corpse and delivered it to her family\\'s doorstep. \"These are just some of the stories,\" said Youssif\\'s mother, Zainab. Under Saddam Hussein, there was more security and stability, they said. There was running water and electricity most of the time. But still life was tough under the dictator, like the time when Zainab\\'s uncle disappeared and was never heard from again after he read a \"religious book,\" she said. Sitting in the parking lot of a Target in suburban Los Angeles, Youssif\\'s father watched as husbands and wives, boyfriends and girlfriends, parents and their children, came and went. Some held hands. Others smiled and laughed. \"Iraq finished,\" he said in what few English words he knows. He elaborated in Arabic: His homeland won\\'t be enjoying such freedoms anytime soon. It\\'s just not possible. Too much violence. Too many killings. His two children have only seen war. But this week, the family has seen a much different side of America -- an outpouring of generosity and a peaceful nation at home. \"It\\'s been a dream,\" the father said. He used to do a lot of volunteer work back in Baghdad. \"Maybe that\\'s why I\\'m being helped now,\" the father said. At Universal Studios, he looked out across the valley below. The sun glistened off treetops and buildings. It was a picturesque sight fit for a Hollywood movie. \"Good America, good America,\" he said in English. E-mail to a friend . CNN\\'s Arwa Damon contributed to this report.'\n", + "]\n", + "\n", + "cnn_daily_article_highlights = ['Werder Bremen pay a club record $10.7 million for Carlos Alberto .\\nThe Brazilian midfielder won the Champions League with FC Porto in 2004 .\\nSince January he has been on loan with his first club, Fluminense .',\n", + " 'Beckham has agreed to a five-year contract with Los Angeles Galaxy .\\nNew contract took effect July 1, 2007 .\\nFormer English captain to meet press, unveil new shirt number Friday .\\nCNN to look at Beckham as footballer, fashion icon and global phenomenon .',\n", + " 'Boy on meeting Spider-Man: \"It was my favorite thing\"\\nYoussif also met SpongeBob, Lassie and an orangutan at Universal Studios .\\nDad: \"Other than my wedding day, this is the happiest day of my life\"' \n", + "]\n", + "\n", + "cnn_df = pd.DataFrame({\"articles\":cnn_daily_articles, \"highligths\":cnn_daily_article_highlights})\n", + "\n", + "cnn_df.head() " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "gather": { + "logged": 1674831294043 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.7621254342360414\n", + "0.7103234824922888\n" + ] + } + ], + "source": [ + "article1_embedding = openai.Embedding.create(input=cnn_df.articles.iloc[0], engine=model)[\"data\"][0][\"embedding\"]\n", + "article2_embedding = openai.Embedding.create(input=cnn_df.articles.iloc[1], engine=model)[\"data\"][0][\"embedding\"]\n", + "article3_embedding = openai.Embedding.create(input=cnn_df.articles.iloc[2], engine=model)[\"data\"][0][\"embedding\"]\n", + "\n", + "print(cosine_similarity(article1_embedding, article2_embedding))\n", + "print(cosine_similarity(article1_embedding, article3_embedding))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# References \n", + "-Azure Reference Documentation \n", + "-Azure OpenAI GitHub Repo\n", + "-cookbooks \n", + "-OpenAI website \n", + "\n", + "1 - [Openai Cookbook](https://github.com/openai/openai-cookbook) \n", + "2 - [Azure Documentation - Azure Open AI Models](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/concepts/models) \n", + "3 - [OpenAI Studio Examples](https://oai.azure.com/portal) \n", + "4 - [[PUBLIC] Best practices for fine-tuning GPT-3 to classify text](https://docs.google.com/document/d/1rqj7dkuvl7Byd5KQPUJRxc19BJt8wo0yHNwK84KfU3Q/edit#)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# For More Help \n", + "[OpenAI Commercialization Team](AzureOpenAITeam@microsoft.com) \n", + "AI Specialized CSAs [aka.ms/airangers](aka.ms/airangers)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Contributors\n", + "* Louis Li \n" + ] + } + ], + "metadata": { + "kernel_info": { + "name": "python310-sdkv2" + }, + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + }, + "microsoft": { + "host": { + "AzureML": { + "notebookHasBeenCompleted": true + } + } + }, + "nteract": { + "version": "nteract-front-end@1.0.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/7-building-chat-applications/notebook-openai.ipynb b/7-building-chat-applications/notebook-openai.ipynb new file mode 100644 index 000000000..036732d63 --- /dev/null +++ b/7-building-chat-applications/notebook-openai.ipynb @@ -0,0 +1,669 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Chapter 7: Building Chat Applications\n", + "## OpenAI API Quickstart\n", + "\n", + "This notebook is adapted from the [Azure OpenAI Samples Repository](https://github.com/Azure/azure-openai-samples) that include notebooks that access [OpenAI](notebooks-oai) and [Azure OpenAI](notebooks-azure-oai) services.\n", + "\n", + "The Python OpenAI API works with Azure OpenAI Models as well, with a few modifications. Learn more about the differences here: [How to switch between OpenAI and Azure OpenAI endpoints with Python](https://learn.microsoft.com/azure/ai-services/openai/how-to/switching-endpoints?WT_mc_id=academic-109527-jasmineg)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Overview \n", + "\"Large language models are functions that map text to text. Given an input string of text, a large language model tries to predict the text that will come next\"(1). This \"quickstart\" notebook will introduce users to high-level LLM concepts, core package requirements for getting started with AML, an soft introduction to prompt design, and several short examples of different use cases. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Table of Contents \n", + "\n", + "[Overview](#overview) \n", + "[How to use OpenAI Service](#how-to-use-openai-service) \n", + "[1. Creating your OpenAI Service](#1.-creating-your-openai-service) \n", + "[2. Installation](#2.-installation) \n", + "[3. Credentials](#3.-credentials) \n", + "\n", + "[Use Cases](#use-cases) \n", + "[1. Summarize Text](#1.-summarize-text) \n", + "[2. Classify Text](#2.-classify-text) \n", + "[3. Generate New Product Names](#3.-generate-new-product-names) \n", + "[4. Fine Tune a Classifier](#4.fine-tune-a-classifier) \n", + "\n", + "[References](#references)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Build your first prompt \n", + "This short exercise will provide a basic introduction for submitting prompts to an OpenAI model for a simple task \"summarization\". \n", + "\n", + "![](images/generative-AI-models-reduced.jpg) \n", + "\n", + "\n", + "**Steps**: \n", + "1. Install OpenAI library in your python environment \n", + "2. Load standard helper libraries and set your typical OpenAI security credentials for the OpenAI Service that you've created \n", + "3. Choose a model for your task \n", + "4. Create a simple prompt for the model \n", + "5. Submit your request to the model API!" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 1. Install OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674254990318 + }, + "jupyter": { + "outputs_hidden": true, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "pip install openai python-dotenv" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 2. Import helper libraries and instantiate credentials" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674829434433 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "import os\n", + "import openai\n", + "from dotenv import load_dotenv\n", + "load_dotenv()\n", + "\n", + "openai.api_type = \"openai\"\n", + "API_KEY = os.getenv(\"OPENAI_API_KEY\",\"\")\n", + "assert API_KEY, \"ERROR: OpenAI Key is missing\"\n", + "openai.api_key = API_KEY\n", + "\n", + "RESOURCE_ENDPOINT = \"https://api.openai.com\" " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 3. Finding the right model \n", + "The GPT-3.5-turbo or GPT-4 models can understand and generate natural language." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674742720788 + }, + "jupyter": { + "outputs_hidden": true, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "# Select the General Purpose curie model for text\n", + "model = \"gpt-3.5-turbo\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## 4. Prompt Design \n", + "\n", + "\"The magic of large language models is that by being trained to minimize this prediction error over vast quantities of text, the models end up learning concepts useful for these predictions. For example, they learn concepts like\"(1):\n", + "\n", + "* how to spell\n", + "* how grammar works\n", + "* how to paraphrase\n", + "* how to answer questions\n", + "* how to hold a conversation\n", + "* how to write in many languages\n", + "* how to code\n", + "* etc.\n", + "\n", + "#### How to control a large language model \n", + "\"Of all the inputs to a large language model, by far the most influential is the text prompt(1).\n", + "\n", + "Large language models can be prompted to produce output in a few ways:\n", + "\n", + "Instruction: Tell the model what you want\n", + "Completion: Induce the model to complete the beginning of what you want\n", + "Demonstration: Show the model what you want, with either:\n", + "A few examples in the prompt\n", + "Many hundreds or thousands of examples in a fine-tuning training dataset\"\n", + "\n", + "\n", + "\n", + "#### There are three basic guidelines to creating prompts:\n", + "\n", + "**Show and tell**. Make it clear what you want either through instructions, examples, or a combination of the two. If you want the model to rank a list of items in alphabetical order or to classify a paragraph by sentiment, show it that's what you want.\n", + "\n", + "**Provide quality data**. If you're trying to build a classifier or get the model to follow a pattern, make sure that there are enough examples. Be sure to proofread your examples — the model is usually smart enough to see through basic spelling mistakes and give you a response, but it also might assume this is intentional and it can affect the response.\n", + "\n", + "**Check your settings.** The temperature and top_p settings control how deterministic the model is in generating a response. If you're asking it for a response where there's only one right answer, then you'd want to set these lower. If you're looking for more diverse responses, then you might want to set them higher. The number one mistake people use with these settings is assuming that they're \"cleverness\" or \"creativity\" controls.\n", + "\n", + "\n", + "Source: https://github.com/Azure/OpenAI/blob/main/How%20to/Completions.md" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### 5. Submit!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674494935186 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "# Create your first prompt\n", + "text_prompt = \"Should oxford commas always be used?\"\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":text_prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "### Repeat the same call, how do the results compare?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674494940872 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "\n", + "response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":text_prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Summarize Text \n", + "#### Challenge \n", + "Summarize text by adding a 'tl;dr:' to the end of a text passage. Notice how the model understands how to perform a number of tasks with no additional instructions. You can experiment with more descriptive prompts than tl;dr to modify the model’s behavior and customize the summarization you receive(3). \n", + "\n", + "Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnostic in architecture, this method still requires task-specific fine-tuning datasets of thousands or tens of thousands of examples. By contrast, humans can generally perform a new language task from only a few examples or from simple instructions - something which current NLP systems still largely struggle to do. Here we show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior state-of-the-art fine-tuning approaches. \n", + "\n", + "\n", + "\n", + "Tl;dr" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Exercises for several use cases \n", + "1. Summarize Text \n", + "2. Classify Text \n", + "3. Generate New Product Names" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674495198534 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "prompt = \"Recent work has demonstrated substantial gains on many NLP tasks and benchmarks by pre-training on a large corpus of text followed by fine-tuning on a specific task. While typically task-agnostic in architecture, this method still requires task-specific fine-tuning datasets of thousands or tens of thousands of examples. By contrast, humans can generally perform a new language task from only a few examples or from simple instructions - something which current NLP systems still largely struggle to do. Here we show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior state-of-the-art fine-tuning approaches.\\n\\nTl;dr\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674495201868 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Classify Text \n", + "#### Challenge \n", + "Classify items into categories provided at inference time. In the following example we provide both the categories and the text to classify in the prompt(*playground_reference). \n", + "\n", + "Customer Inquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\n", + "\n", + "Classified category:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674499424645 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "prompt = \"Classify the following inquiry into one of the following: categories: [Pricing, Hardware Support, Software Support]\\n\\ninquiry: Hello, one of the keys on my laptop keyboard broke recently and I'll need a replacement:\\n\\nClassified category:\"\n", + "print(prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674499378518 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## Generate New Product Names\n", + "#### Challenge\n", + "Create product names from examples words. Here we include in the prompt information about the product we are going to generate names for. We also provide a similar example to show the pattern we wish to receive. We have also set the temperature value high to increase randomness and more innovative responses.\n", + "\n", + "Product description: A home milkshake maker\n", + "Seed words: fast, healthy, compact.\n", + "Product names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\n", + "\n", + "Product description: A pair of shoes that can fit any foot size.\n", + "Seed words: adaptable, fit, omni-fit." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "gather": { + "logged": 1674257087279 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "prompt = \"Product description: A home milkshake maker\\nSeed words: fast, healthy, compact.\\nProduct names: HomeShaker, Fit Shaker, QuickShake, Shake Maker\\n\\nProduct description: A pair of shoes that can fit any foot size.\\nSeed words: adaptable, fit, omni-fit.\"\n", + "\n", + "print(prompt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [], + "source": [ + "#Setting a few additional, typical parameters during API Call\n", + "\n", + "response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages = [{\"role\":\"system\", \"content\":\"You are a helpful assistant.\"},\n", + " {\"role\":\"user\",\"content\":prompt},])\n", + "\n", + "response['choices'][0]['message']['content']" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# References \n", + "-Azure Reference Documentation \n", + "-Azure OpenAI GitHub Repo\n", + "-cookbooks \n", + "-OpenAI website \n", + "\n", + "1 - [Openai Cookbook](https://github.com/openai/openai-cookbook) \n", + "2 - [Azure Documentation - Azure Open AI Models](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/concepts/models) \n", + "3 - [OpenAI Studio Examples](https://oai.azure.com/portal) \n", + "4 - [[PUBLIC] Best practices for fine-tuning GPT-3 to classify text](https://docs.google.com/document/d/1rqj7dkuvl7Byd5KQPUJRxc19BJt8wo0yHNwK84KfU3Q/edit#)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# For More Help \n", + "[OpenAI Commercialization Team](AzureOpenAITeam@microsoft.com) \n", + "AI Specialized CSAs [aka.ms/airangers](aka.ms/airangers)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "# Contributors\n", + "* Louis Li \n" + ] + } + ], + "metadata": { + "kernel_info": { + "name": "python310-sdkv2" + }, + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + }, + "microsoft": { + "host": { + "AzureML": { + "notebookHasBeenCompleted": true + } + } + }, + "nteract": { + "version": "nteract-front-end@1.0.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/7-building-chat-applications/notebook.ipynb b/7-building-chat-applications/notebook.ipynb deleted file mode 100644 index 2be78efb3..000000000 --- a/7-building-chat-applications/notebook.ipynb +++ /dev/null @@ -1,46 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 7: Building Chat Applications" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import openai\n", - "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n", - "\n", - "\n", - "chat_completion = openai.ChatCompletion.create(model=\"gpt-3.5-turbo\", messages=[{\"role\": \"user\", \"content\": \"Suggest two titles for a instructional lesson on chat applications for generative AI.\"}])" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}