<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.1">Jekyll</generator><link href="https://ibragimov.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://ibragimov.org/" rel="alternate" type="text/html" /><updated>2024-03-27T17:15:12+11:00</updated><id>https://ibragimov.org/feed.xml</id><title type="html">Maksud Ibrahimov</title><subtitle>Maksud Ibrahimov&apos;s personal website with blog posts, thought and pages</subtitle><entry><title type="html">Key pillars to capture value out of artificial intelligence in organisations</title><link href="https://ibragimov.org/2024/03/26/pillars-to-capture-ai-value.html" rel="alternate" type="text/html" title="Key pillars to capture value out of artificial intelligence in organisations" /><published>2024-03-26T00:00:00+11:00</published><updated>2024-03-26T00:00:00+11:00</updated><id>https://ibragimov.org/2024/03/26/pillars-to-capture-ai-value</id><content type="html" xml:base="https://ibragimov.org/2024/03/26/pillars-to-capture-ai-value.html"><![CDATA[<p>I am often asked by companies, people and universities “How organisations can use artificial intelligence (AI) for their competitive advantage?”. In this article I’d like to share the framework that simplifies this complex question into 5 dimensions.</p>

<p>It’s no surprise in this day and age that organisations need to leverage AI to keep up with competition and ever increasing. Companies see real improvements from applying AI in their businesses. McKinsey estimates, that AI leaders show over 2 time better financial performance, 5-10% increase of revenue and 10-20% reduced cost [1].</p>

<p>This framework has 5 pillars that every organisation needs to adopt to realise value of artificial intelligence: strategy, data, technology, people and process. Let me go through each one of them, and provide an intuition with making a race car example.</p>

<p>Effective AI started to build a product based on this framework that allows companies to fast track their AI journey and become ultra competitive within months, instead of spending years building capabilities. Please reach out to me if you’re interested in participating in the trial of this product.</p>

<p><img src="/assets/img/header/key-pillars-aa-enablement.png" alt="5 pillars of AI enablement" /></p>

<h1 id="1-digital-strategy">1. Digital strategy</h1>

<p>The first and most important dimension is having a clear strategic vision, plan and roadmap for leveraging AI. Organisational leadership needs to determine how analytics can support key business objectives and priorities. This could include enhancing customer experience, optimising operations, gaining insights into new markets and more. Aligning analytics initiatives to strategic goals ensures efforts are focused and value is maximised.</p>

<p>In the race car example, strategy is the map and the route or routes that you planning to take.</p>

<h1 id="2-utilising-high-quality-data">2. Utilising high-quality data</h1>

<p>High-quality, relevant data is the lifeblood for any AI initiative. Organisations must establish processes to capture both internal and external data from diverse sources. Ensuring data is cleansed, integrated and governed properly sets the foundation for powerful insights. Investments may also be required to fill data gaps through alternative sources. With a robust data strategy and architecture, organisations can fuel analytics programs for years. The recent advances in AI show that no matter how good your algorithm and hardware is, it’s the data that is the main driver of progress</p>

<p>In our race car example, data is fuel for the car.</p>

<h1 id="3-technology">3. Technology</h1>

<p>Technology is a critical component in these 5 dimensions. In our road trip analogy, it’s a car itself. It includes decisions on infrastructure, architecture, hardware and software and platforms.</p>

<p>Building a robust analytics architecture is critical to enable AI competitive advantage. Depending on the organisation and its goals they can choose on-premise and/or cloud-based infrastructure. Organisations need also to design modern architectures and platforms to help them to reach their goals.</p>

<p>Finally, having the right software tools and libraries enable people to develop the use cases. Languages, with strong analytics support, like Python or R, allow data exploration while tools like PowerBI and Tableau enable visualization. Machine learning libraries like Scikit-learn, TensorFlow power predictive modelling. Natural language processing libraries help with text and language data. Proper model management systems govern deployed algorithms.</p>

<h1 id="4-people-and-multidisciplinary-teams">4. People and multidisciplinary teams</h1>

<p>While technology is critical, people remain the most important asset for making AI a competitive advantage. Organisations need multidisciplinary teams including data scientists, data engineers, machine learning engineers, business analysts and experts to help build models, collaborate with business and ensure value delivery. Training existing staff and strategic hiring allows building these specialised analytical skills over time. Nurturing a culture of experimentation and innovation further unleashes the potential of people.</p>

<p>People - is a car driver. The car will not move or will not get to the end point if the driver doesn’t have relevant skills.</p>

<h1 id="5-process">5. Process</h1>

<p>Well defined processes in the company make the results of AI efforts optimal, effective, repeatable, scalable and allows for continuous improvement.</p>

<p>A version of Agile methodology allows analytical teams to work iteratively and deliver value every sprint via minimum viable products. Classic agile methodology can also be scaled across multiple levels of the company via frameworks like SAFe.</p>

<p>Additionally, there should be sufficient software engineering best practices, product development best practices, UI/UX and security processes in place to build a robust, scalable and extensible products.</p>

<p>Finally, organisations need a way to measure the results on regular basis to help pivot and understand if the products are going in the right directions.</p>

<p>While well-defined processes provide numerous benefits, organisations need to be cognizant of not going overboard and remain lean.</p>

<h1 id="conculsion">Conculsion</h1>

<p>A holistic set of capabilities across these 5 dimensions allows organisations to maximise competitive advantage with artificial intelligence. With the right strategy, data, technology, skills and processes in place, AI becomes a strategic weapon to outperform competition.</p>

<p><strong>Effective AI started to build a product based on this framework that allows companies to fast track their AI journey and become ultra competitive within months, instead of spending years building capabilities. Please reach out to me if you’re interested in participating in the trial of this product.</strong></p>

<p>References:</p>

<p>[1] McKinsey Tech Trends Outlook 2022 <a href="https://www.mckinsey.com/~/media/mckinsey/business%20functions/mckinsey%20digital/our%20insights/the%20top%20trends%20in%20tech%202022/mckinsey-tech-trends-outlook-2022-full-report.pdf">link</a></p>]]></content><author><name></name></author><category term="ai" /><category term="product" /><category term="data" /><category term="strategy" /><category term="technology" /><category term="people" /><category term="process" /><category term="value" /><summary type="html"><![CDATA[I am often asked by companies, people and universities “How organisations can use artificial intelligence (AI) for their competitive advantage?”. In this article I’d like to share the framework that simplifies this complex question into 5 dimensions.]]></summary></entry><entry><title type="html">Understanding the differences between product and project management</title><link href="https://ibragimov.org/2023/08/16/product-vs-project-management.html" rel="alternate" type="text/html" title="Understanding the differences between product and project management" /><published>2023-08-16T00:00:00+10:00</published><updated>2023-08-16T00:00:00+10:00</updated><id>https://ibragimov.org/2023/08/16/product-vs-project-management</id><content type="html" xml:base="https://ibragimov.org/2023/08/16/product-vs-project-management.html"><![CDATA[<p>In my work, companies often confuse product and project management, thinking that is the same thing. In reality, product management and project management are two distinct disciplines within the realm of business management, each with its own unique focus, goals, and responsibilities. In this article I will outline the key differences between the two</p>

<p>While product management and project management roles may seem similar on the surface, they require very different skills and focus on distinct aspects of bringing new offerings to market.</p>

<p><strong>Product management</strong> is responsible for the overall success of a product from concept to end of life. <strong>Project managemen</strong>t focuses on successful planning and execution of projects according to constraints like scope, budget, timeline and resources.</p>

<p>To make it easy to compare, I put together a table that compares product and project management from 4 dimensions: purpose, scope, responsibilities and metrics.</p>

<table>
  <tbody>
    <tr>
      <td><strong>Dimension</strong></td>
      <td><strong>Product management</strong></td>
      <td><strong>Project management</strong></td>
    </tr>
    <tr>
      <td>Purpose</td>
      <td>- The purpose of product management is to deliver a product that provides value to customers and meets business objectives. <br />  - Product managers focus on the product’s life cycle, from idea to market launch and beyond.</td>
      <td>- The purpose of project management is to ensure that specific projects are completed on time, within budget, and meet the defined objectives. <br />  - Project managers focus on delivering the project according to the plan.</td>
    </tr>
    <tr>
      <td>Scope</td>
      <td>The scope of product management is the entire lifespan of a product, which could potentially be indefinite. It involves ideation, strategy, design, development, testing, launch, and maintenance.</td>
      <td>The scope of project management is limited to the duration of a specific project. It starts when the project is initiated and ends when the project is completed, which is a finite period.</td>
    </tr>
    <tr>
      <td>Responsibility</td>
      <td>Product managers are responsible for defining the product vision, setting the product strategy, understanding customer needs, and prioritizing features. They work closely with various teams (such as engineering, marketing, sales, etc.) to ensure the product meets customer needs and business goals.</td>
      <td>Project managers are responsible for planning the project, coordinating resources, managing risks, resolving issues, and ensuring the project is delivered on time and within budget. They work with various stakeholders to ensure the project’s deliverables are achieved.</td>
    </tr>
    <tr>
      <td>Success Metrics</td>
      <td>The success of product management is usually measured by long-term metrics related to the product, such as market share, revenue, customer satisfaction, and product usage.</td>
      <td>The success of project management is usually measured by project-specific metrics, such as on-time delivery, budget adherence, quality of deliverables, and stakeholder satisfaction.</td>
    </tr>
  </tbody>
</table>

<p>In summary, while product management is about the ‘what’ and ‘why’ (what product to build and why), project management is about the ‘how’ and ‘when’ (how to deliver the project and when). Both disciplines are critical to the success of any organization, but they focus on different aspects of the business.</p>]]></content><author><name></name></author><category term="project management" /><category term="product management" /><category term="product" /><category term="agile" /><category term="development" /><category term="management" /><summary type="html"><![CDATA[In my work, companies often confuse product and project management, thinking that is the same thing. In reality, product management and project management are two distinct disciplines within the realm of business management, each with its own unique focus, goals, and responsibilities. In this article I will outline the key differences between the two]]></summary></entry><entry><title type="html">Exploring business use cases to harness the power of Generative AI</title><link href="https://ibragimov.org/2023/08/01/genai-use-cases.html" rel="alternate" type="text/html" title="Exploring business use cases to harness the power of Generative AI" /><published>2023-08-01T00:00:00+10:00</published><updated>2023-08-01T00:00:00+10:00</updated><id>https://ibragimov.org/2023/08/01/genai-use-cases</id><content type="html" xml:base="https://ibragimov.org/2023/08/01/genai-use-cases.html"><![CDATA[<p>In today’s rapidly evolving technological landscape, businesses are constantly seeking innovative solutions to enhance their operations and drive growth. By leveraging the power of generative AI, companies have the potential to unlock significant value and revolutionize various aspects of their business. <a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/the-economic-potential-of-generative-ai-the-next-productivity-frontier" target="_blank">McKinsey research</a> estimates that generative AI could add $2.6 trillion to $4.4 trillion of value annually.  In this article, we will explore some compelling use cases where generative AI can be applied to drive transformative outcomes.</p>

<p>Across industries, McKinsey estimates highest impact from generative AI in sales, marketing, software engineering and customer operations. (see figure below)</p>

<p><img src="/assets/img/feature-img/gen_ai_usecases_mckinsey.png" alt="Across industries, McKinsey estimates highest impact from generative AI in sales, marketing, software engineering and customer operations." /></p>

<p>Based on my experience, majority of use cases fall into one of 4 categories:</p>
<ol>
  <li>Synthesis of large text data</li>
  <li>Content generation</li>
  <li>Chatbots with domain knowledge</li>
  <li>Code generation</li>
</ol>

<p>Let’s explore them in detail.</p>

<h3 id="1-synthesis-of-large-text-data">1. Synthesis of large text data</h3>

<p>Dealing with vast amounts of text data has always been a challenge for businesses. Generative AI presents a game-changing opportunity to quickly synthesize large documents, saving valuable time and effort for knowledge workers. By employing generative AI algorithms, businesses can efficiently extract specific attributes from text data, enabling them to gain meaningful insights from dialogues, correspondence, and vast textual resources.</p>

<p>Specific use cases in this category include:</p>
<ul>
  <li>Quick synthesis of large documents: research papers, legal documents.</li>
  <li>Extraction of particular attributes from the text data: sentiment, pricing.</li>
  <li>Insights from dialogues and correspondence: actions for each team member from conversation</li>
</ul>

<h3 id="2-content-generation">2. Content generation</h3>

<p>Personalization has become a critical aspect of modern marketing and customer engagement strategies. Generative AI enables businesses to create personalized content tailored to each customer’s unique circumstances and preferences. Whether it’s generating personalized product recommendations, crafting individualized marketing campaigns, or tailoring content for specific customer segments, generative AI proves to be a powerful tool in enhancing the customer experience and driving brand loyalty.</p>

<p>Specific use cases in this category include:</p>
<ul>
  <li>Personalised marketing content for each customer based on their own circumstances.</li>
  <li>Writing articles</li>
  <li>Creating legal or other documents</li>
</ul>

<h3 id="3-chatbots-with-domain-knowledge">3. Chatbots with domain knowledge</h3>

<p>Chatbots have become increasingly prevalent in various industries, offering real-time support and seamless interactions with customers. Generative AI takes chatbot capabilities to a whole new level by providing domain knowledge expertise. These intelligent chatbots can serve as advisors in specialized fields such as legal, medical, engineering, and more, offering personalized and expert guidance to users. Moreover, businesses can deploy chatbots as sales agents, enhancing customer engagement and driving sales conversion rates. Additionally, chatbots can provide valuable support to customers, resolving queries efficiently and enhancing customer satisfaction.</p>

<p>Specific use cases in this category include:</p>
<ul>
  <li>Chatbot as an internal or external advisor for legal, medical, engineering, etc</li>
  <li>Chatbot as sales agent</li>
  <li>Chatbot as support agent</li>
</ul>

<h3 id="4-code-generation">4. Code generation</h3>

<p>Software development is a complex and time-consuming process. However, generative AI can act as an invaluable co-pilot for developers, dramatically speeding up the code generation process. This technology can facilitate no-code app generation, empowering individuals with limited coding knowledge to create applications effortlessly. Additionally, generative AI can aid in template generation, automating the creation of standardized code structures, further streamlining development workflows.</p>

<p>Specific use cases in this category include:</p>
<ul>
  <li>Co-pilot for developers</li>
  <li>No-code app generation</li>
  <li>Template generation</li>
</ul>

<h3 id="final-thoughts">Final thoughts</h3>

<p>As businesses continue to explore and adopt this technology, it is crucial to address ethical considerations and ensure responsible AI usage. Transparent and ethical deployment of generative AI will foster trust among customers and stakeholders, promoting the long-term sustainability and success of organizations.</p>

<p>In conclusion, embracing generative AI in the right manner will undoubtedly unlock new possibilities and propel businesses into a future of innovation and prosperity. As this technology continues to evolve, enterprises must remain at the forefront of its adoption to remain competitive and reap the full benefits of generative AI.</p>]]></content><author><name></name></author><category term="llm" /><category term="business" /><category term="use case" /><category term="innovation" /><category term="chatbots" /><category term="code generation" /><category term="synthesis" /><category term="content generation" /><summary type="html"><![CDATA[In today’s rapidly evolving technological landscape, businesses are constantly seeking innovative solutions to enhance their operations and drive growth. By leveraging the power of generative AI, companies have the potential to unlock significant value and revolutionize various aspects of their business. McKinsey research estimates that generative AI could add $2.6 trillion to $4.4 trillion of value annually. In this article, we will explore some compelling use cases where generative AI can be applied to drive transformative outcomes.]]></summary></entry><entry><title type="html">How to tune LLM models within the context of your business?</title><link href="https://ibragimov.org/2023/07/25/llm-tuning.html" rel="alternate" type="text/html" title="How to tune LLM models within the context of your business?" /><published>2023-07-25T00:00:00+10:00</published><updated>2023-07-25T00:00:00+10:00</updated><id>https://ibragimov.org/2023/07/25/llm-tuning</id><content type="html" xml:base="https://ibragimov.org/2023/07/25/llm-tuning.html"><![CDATA[<p>One of the most frequent questions that I am asked by my clients is how to tune LLM models on their data, whether it’s proprietary or data from certain public domain, like legal. In this article I will cover three archetypes how to achieve it.</p>

<p>The tradeoff between these archetypes is the cost and the effort required vs how domain specific the model is. If mostly general knowledge is required first archetype can be sufficient, but for more specific domains archetype number 3 is more relevant.</p>

<p>Here are the three archetypes:</p>

<ol>
  <li>
    <p><strong>Use out of the box LLM API with the power of prompt engineering to pass context of your problem</strong>. In this case, you take a question and ask your model to give an answer. You may provide some context and a few examples as a context, and this is proven to improve the model quite a bit. This is a cost effective, easy to implement and requires careful prompt engineering. The model is limited mostly to general knowledge and the knowledge included in the limited context.</p>
  </li>
  <li>
    <p><strong>Fine tune pre-trained LLM with your proprietary data</strong>. In this archetype, you take existing pre-trained model and train it further on proprietary data. Transfer learning can be another option in this case. This will still require GPU compute, probably on a cluster but not as expensive as training the model from scratch. The model will have a lot more domain specific knowledge than in the first archetype.</p>
  </li>
  <li>
    <p><strong>Train your own LLM from scratch</strong>. This is the most expensive and hardest to implement archetype. The cost of training such a model is in hundreds of millions of dollars and training can last for months. Sam Altman estimated that the cost to train GPT-4 was about $100 million. An example of such model was trained by Bloomberg - <a href="https://www.bloomberg.com/company/press/bloomberggpt-50-billion-parameter-llm-tuned-finance/" target="_blank">BloombergGPT</a>, which was trained on Bloomberg financial data.</p>
  </li>
</ol>]]></content><author><name></name></author><category term="llm" /><category term="production" /><category term="best practice" /><category term="challenges" /><category term="tuning" /><category term="training" /><summary type="html"><![CDATA[One of the most frequent questions that I am asked by my clients is how to tune LLM models on their data, whether it’s proprietary or data from certain public domain, like legal. In this article I will cover three archetypes how to achieve it.]]></summary></entry><entry><title type="html">How to evaluate performance of systems based on LLM models?</title><link href="https://ibragimov.org/2023/06/10/evaluating-llm-performance.html" rel="alternate" type="text/html" title="How to evaluate performance of systems based on LLM models?" /><published>2023-06-10T00:00:00+10:00</published><updated>2023-06-10T00:00:00+10:00</updated><id>https://ibragimov.org/2023/06/10/evaluating-llm-performance</id><content type="html" xml:base="https://ibragimov.org/2023/06/10/evaluating-llm-performance.html"><![CDATA[<p>One of the most important considerations when building complex AI systems, including LLM based systems, is evaluating their performance. It is important because we need to 1) understand how well the model works overall, as well as 2) what impact did the recent change made.</p>

<p>In this article, I will cover model evaluation of LLM models that are already producing good results by themselves (like GPT-3.5 or GPT-4) on a generic standard metrics (like superglue) and we want to evaluate performance for a <strong>specific task we are building the model for</strong>. I.e, we are not evaluating general performance of LLM but performance of GPT-4 for a task like chatbot for a bank.</p>

<p>Three main points to decide on for model evaluation is to choose the main metric, create a test set and decide how to compare the outputs of the model to the ground truth.</p>

<ol>
  <li>
    <p><strong>Choose the main metric</strong>. There might be multiple metrics to get an intuition of what is happening in the system but it’s always easier to compare a single metric rather than multiple. Often simple metric like accuracy works, where we count example as true if the meaning matches one or multiple expected results. Point 3 covers how to compare output to the expected result by meaning.</p>
  </li>
  <li>
    <p><strong>Create a test set</strong>, either manually, by generating it with LLM or to use both. My preference is to use the last option because manual examples allow to build an intuition about the queries and answers that we want. The rest can be quicky generated by the LLM.</p>

    <p>LangChain has a very nice chain <code class="language-plaintext highlighter-rouge">QAGenerateChain</code> to help to automatically generate the questions and answers from examples.</p>
  </li>
  <li>
    <p>Decide how to <strong>compare results of the model with the ground truth</strong>. It’s easy to compare numbers but with the fuzzy nature of text inputs and outputs it can become a trickier question. The answer, again, is to use LLM itself to do the comparison.</p>
  </li>
</ol>

<p>Additional metrics to keep track of:</p>
<ul>
  <li>Bias and fairness</li>
  <li>Drifts. Data and model drifts</li>
  <li>Data quality</li>
</ul>

<p>If there is enough interest, I can explore these additional concepts and relevant metrics in future articles.</p>]]></content><author><name></name></author><category term="llm" /><category term="memory" /><category term="langchain" /><category term="metrics" /><category term="performance" /><summary type="html"><![CDATA[One of the most important considerations when building complex AI systems, including LLM based systems, is evaluating their performance. It is important because we need to 1) understand how well the model works overall, as well as 2) what impact did the recent change made.]]></summary></entry><entry><title type="html">LLM memory abstractions</title><link href="https://ibragimov.org/2023/05/30/llm-memory.html" rel="alternate" type="text/html" title="LLM memory abstractions" /><published>2023-05-30T00:00:00+10:00</published><updated>2023-05-30T00:00:00+10:00</updated><id>https://ibragimov.org/2023/05/30/llm-memory</id><content type="html" xml:base="https://ibragimov.org/2023/05/30/llm-memory.html"><![CDATA[<p>In this article I am planning to discuss how to incorporate memory into LLM models and do it seamlessly via LangChain framework. One inherent limitation of the modern LLM models is their stateless nature, where each transaction with an LLM is treated as an independent interaction. This lack of memory poses a challenge when it comes to maintaining context across multiple conversations.</p>

<h3 id="overall-approach">Overall approach</h3>

<p>Since LLM models are stateless, the most common method of keeping track of memory of previous conversations, is to include it at every new call to LLM as a context. In the future, there may be new models that can keep track of memory naturally but with ChatGPT and GPT-4 it this is the most common way.</p>

<p>Frameworks like LangChain, however, allow developers to abstract out of this limitation and make it seamless. The framework manages the memory and include it every time “automatically”.</p>

<p>In this article I’ll explore examples of the basic LLM memory abstractions:</p>
<ul>
  <li>ChatMessageHistory</li>
  <li>ConversationBufferMemory</li>
  <li>ConversationBufferWindowMemory</li>
  <li>ConversationSummaryBufferMemory</li>
  <li>ConversationEntityMemory</li>
</ul>

<h3 id="langchain-abstractions">LangChain abstractions</h3>

<p>Let’s review several classes that I used in the last few weeks.</p>

<p>The core class that is behind all the abstractions is a <code class="language-plaintext highlighter-rouge">ChatMessageHistory</code> that is just a collection of past user and AI messages.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="kn">from</span> <span class="nn">langchain.memory</span> <span class="kn">import</span> <span class="n">ChatMessageHistory</span>

<span class="n">history</span> <span class="o">=</span> <span class="n">ChatMessageHistory</span><span class="p">()</span>
<span class="n">history</span><span class="p">.</span><span class="n">add_user_message</span><span class="p">(</span><span class="s">"hello, chatgpt"</span><span class="p">)</span>
<span class="n">history</span><span class="p">.</span><span class="n">add_ai_message</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">history</span><span class="p">.</span><span class="n">messages</span><span class="p">)</span>
</code></pre></div></div>

<p>Output is:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">HumanMessage</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s">'hello, chatgpt'</span><span class="p">,</span> <span class="n">additional_kwargs</span><span class="o">=</span><span class="p">{},</span> <span class="n">example</span><span class="o">=</span><span class="bp">False</span><span class="p">),</span>
 <span class="n">AIMessage</span><span class="p">(</span><span class="n">content</span><span class="o">=</span><span class="s">'hello'</span><span class="p">,</span> <span class="n">additional_kwargs</span><span class="o">=</span><span class="p">{},</span> <span class="n">example</span><span class="o">=</span><span class="bp">False</span><span class="p">)]</span>

</code></pre></div></div>

<h4 id="conversationbuffermemory">ConversationBufferMemory</h4>

<p><code class="language-plaintext highlighter-rouge">ConversationBufferMemory</code> is one abstraction above <code class="language-plaintext highlighter-rouge">ChatMessageHistory</code> and can be used in OpenAI models directly. It automatically records all the conversations with the model.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">langchain.llms</span> <span class="kn">import</span> <span class="n">OpenAI</span>
<span class="kn">from</span> <span class="nn">langchain.chains</span> <span class="kn">import</span> <span class="n">ConversationChain</span>
<span class="kn">from</span> <span class="nn">langchain.memory</span> <span class="kn">import</span> <span class="n">ConversationBufferMemory</span>


<span class="n">memory</span> <span class="o">=</span> <span class="n">ConversationBufferMemory</span><span class="p">()</span>
<span class="n">memory</span><span class="p">.</span><span class="n">chat_memory</span><span class="p">.</span><span class="n">add_user_message</span><span class="p">(</span><span class="s">"My name is Maksud"</span><span class="p">)</span> 

<span class="n">conversation_with_memory</span> <span class="o">=</span> <span class="n">ConversationChain</span><span class="p">(</span>
    <span class="n">llm</span><span class="o">=</span><span class="n">OpenAI</span><span class="p">(</span><span class="n">temperature</span><span class="o">=</span><span class="mi">0</span><span class="p">),</span> 
    <span class="n">verbose</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> 
    <span class="n">memory</span><span class="o">=</span><span class="n">ConversationBufferMemory</span><span class="p">()</span>
<span class="p">)</span>

<span class="n">conversation_without_memory</span> <span class="o">=</span>  <span class="o">=</span> <span class="n">ConversationChain</span><span class="p">(</span>
    <span class="n">llm</span><span class="o">=</span><span class="n">OpenAI</span><span class="p">(</span><span class="n">temperature</span><span class="o">=</span><span class="mi">0</span><span class="p">),</span> 
    <span class="n">verbose</span><span class="o">=</span><span class="bp">True</span>
<span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">conversation_without_memory</span><span class="p">.</span><span class="n">predict</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="s">"What is my name?"</span><span class="p">))</span>

<span class="k">print</span><span class="p">(</span><span class="n">conversation_with_memory</span><span class="p">.</span><span class="n">predict</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="s">"What is my name?"</span><span class="p">))</span>

</code></pre></div></div>

<p>The output, first with memoryless model and second is with memory. Nice touch GPT-4 reminding us that you don’t store personal information :)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; I apologize, but as an AI language model,
I don't have access to personal information...


&gt; Your name is Maksud.
</code></pre></div></div>

<h4 id="conversationbufferwindowmemory">ConversationBufferWindowMemory</h4>

<p>This class is the same as <code class="language-plaintext highlighter-rouge">ConversationBufferMemory</code> but it has a window of last N messages to pass to the LLM.</p>

<p>Let’s take a look at example:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">memory</span> <span class="o">=</span> <span class="n">ConversationBufferWindowMemory</span><span class="p">(</span> <span class="n">k</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">memory</span><span class="p">.</span><span class="n">save_context</span><span class="p">({</span><span class="s">"input"</span><span class="p">:</span> <span class="s">"a=1"</span><span class="p">},</span> <span class="p">{</span><span class="s">"output"</span><span class="p">:</span> <span class="s">"The value of the variable a is 1."</span><span class="p">})</span>
<span class="n">memory</span><span class="p">.</span><span class="n">save_context</span><span class="p">({</span><span class="s">"input"</span><span class="p">:</span> <span class="s">"b=5"</span><span class="p">},</span> <span class="p">{</span><span class="s">"output"</span><span class="p">:</span> <span class="s">"The value of the variable b is 5. "</span><span class="p">})</span>
<span class="n">memory</span><span class="p">.</span><span class="n">save_context</span><span class="p">({</span><span class="s">"input"</span><span class="p">:</span> <span class="s">"c=11"</span><span class="p">},</span> <span class="p">{</span><span class="s">"output"</span><span class="p">:</span> <span class="s">"The value of the variable c is 11. "</span><span class="p">})</span>

<span class="k">print</span><span class="p">(</span><span class="n">conversation_without_memory</span><span class="p">.</span><span class="n">predict</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="s">"what is value of c?"</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">conversation_without_memory</span><span class="p">.</span><span class="n">predict</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="s">"what is value of a?"</span><span class="p">))</span>

</code></pre></div></div>

<p>In the first case LLM knows the value of <code class="language-plaintext highlighter-rouge">c</code> because it was recent but in the second case it “forgot” the value of <code class="language-plaintext highlighter-rouge">a</code> since it’s outside of buffer window of 2.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; The value of the variable "c" is 11.
Is there anything specific you would like to know or do with this information?


&gt; Based on the information provided so far,
there is no mention of the variable "a" or its value.
</code></pre></div></div>

<h4 id="conversationsummarybuffermemory">ConversationSummaryBufferMemory</h4>

<p>Storing all the message history with LLM can accumulate over time and can be expensive tokenwise. To overcome this, a nice trick of summarising the previous chats retains most of information and compresses the content passed to LLM every time.</p>

<p>LangChain’s <code class="language-plaintext highlighter-rouge">ConversationSummaryBufferMemory</code> helps to summarise the previous chats and uses LLM itself to create these summaries.</p>

<h4 id="conversationentitymemory">ConversationEntityMemory</h4>

<p>More advanced version of summarisation and LLM memory is <code class="language-plaintext highlighter-rouge">ConversationEntityMemory</code>. This class helps the model to keep track of multiple entities in the conversation.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">memory</span> <span class="o">=</span> <span class="n">ConversationEntityMemory</span><span class="p">(</span><span class="n">llm</span><span class="o">=</span><span class="n">llm</span><span class="p">,</span> <span class="n">return_messages</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">_input</span> <span class="o">=</span> <span class="p">{</span><span class="s">"input"</span><span class="p">:</span> <span class="s">"Alice and Bob talk over the phone about their gym class"</span><span class="p">}</span>
<span class="n">memory</span><span class="p">.</span><span class="n">load_memory_variables</span><span class="p">(</span><span class="n">_input</span><span class="p">)</span>
<span class="n">memory</span><span class="p">.</span><span class="n">save_context</span><span class="p">(</span>
    <span class="n">_input</span><span class="p">,</span>
    <span class="p">{</span><span class="s">"output"</span><span class="p">:</span> <span class="s">" Great to know about Alice and Bob. Sounds like exicting class"</span><span class="p">}</span>
<span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="n">memory</span><span class="p">.</span><span class="n">load_memory_variables</span><span class="p">({</span><span class="s">"input"</span><span class="p">:</span> <span class="s">'what is Bob doing?'</span><span class="p">}))</span>
</code></pre></div></div>

<p>LangChain uses LLM to extract entities from this conversation, in this case Alice and Bob and stores it.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{'history':
[HumanMessage(content='Alice and Bob talk over the phone about their gym class', additional_kwargs={}),
  AIMessage(content=' Great to know about Alice and Bob. Sounds like exicting class', additional_kwargs={})],
 'entities': {
   'Alice': 'Alice is talking to Bob about their gym class.',
   'Bob': 'Bob is talking to Alice about their gym class.',
   }}

</code></pre></div></div>

<h3 id="other-langchain-memory-classes">Other LangChain memory classes</h3>

<p>In this article I covered some of the basic LangChain clasess to emulate memory in LLMs. Some other classes worth considering are:</p>
<ul>
  <li>VectorStore-Backed Memory</li>
  <li>DynamoDB, Cassandra, Zep, etc and other databases backed memory</li>
  <li>Motörhead Memory</li>
</ul>

<p>If you are interested, I am happy to connect with you to talk about the right memory class for your LLM project.</p>]]></content><author><name></name></author><category term="llm" /><category term="memory" /><category term="langchain" /><summary type="html"><![CDATA[In this article I am planning to discuss how to incorporate memory into LLM models and do it seamlessly via LangChain framework. One inherent limitation of the modern LLM models is their stateless nature, where each transaction with an LLM is treated as an independent interaction. This lack of memory poses a challenge when it comes to maintaining context across multiple conversations.]]></summary></entry><entry><title type="html">Graph summit in Melbourne. Graph workshop notebook included.</title><link href="https://ibragimov.org/2023/05/22/graph-summit-melbourne.html" rel="alternate" type="text/html" title="Graph summit in Melbourne. Graph workshop notebook included." /><published>2023-05-22T00:00:00+10:00</published><updated>2023-05-22T00:00:00+10:00</updated><id>https://ibragimov.org/2023/05/22/graph-summit-melbourne</id><content type="html" xml:base="https://ibragimov.org/2023/05/22/graph-summit-melbourne.html"><![CDATA[<p>I have recently had a pleasure to attend Graph Summit Melbourne 2023 and it was a resounding success, bringing together experts and enthusiasts from the graph technology community. Attendees were treated to a range of enlightening presentations and workshops showcasing the transformative power of graphs.</p>

<p>Special thanks to my friend Emil Pastor who invited me to the summit and shed the light on the modern graph technology.</p>

<p>Here’s a recap of some of the notable sessions:</p>

<ul>
  <li>
    <p>Dr. Jim Webber, Chief Scientist at Neo4j, captivated the audience with his opening keynote on “The Art of the Possible with Graph Technology.” Dr. Webber shed light on the boundless potential of graphs and their applications across various domains.</p>
  </li>
  <li>
    <p>Karthick Thanigaimani, Engineering Chapter Lead at Payments Reliability Engineering and Support Services, shared insights into ANZ Payment Ops using Neo4j. His presentation demonstrated how Neo4j’s capabilities could revolutionize the payment operations landscape.</p>
  </li>
  <li>
    <p>Matthew Campbell, Manager of Bioinformatics at InterVenn Biosciences, presented “Building knowledge graphs for clinical glycomics and molecular pathway analysis.” He showcased the power of knowledge graphs in advancing clinical research and analysis in glycomics and molecular pathways.</p>
  </li>
  <li>
    <p>Michela Ledwidge, Founder and CEO of Mod, addressed the challenge of overcoming adoption barriers in spatial visualization. Her talk highlighted innovative solutions to seamlessly integrate spatial data within graph databases.</p>
  </li>
  <li>
    <p>Emil Pastor, Solution Architect Manager at Neo4j ANZ, discussed “Connected Data in the Age of AI/ML: The Path to Success using Graph Database and Data Science.” Attendees gained valuable insights into leveraging the synergies between graph databases and AI/ML techniques to unlock new opportunities.</p>
  </li>
  <li>
    <p>Joshua Yu, Director of Pre-Sales and Field Engineer APAC at Neo4j, explored “LLMs using Neo4j.” His session provided valuable insights into how organizations can harness the power of Neo4j to manage large-scale learning and knowledge management systems.</p>
  </li>
  <li>
    <p>Ryan Jeffery and Peter Dart delivered an enlightening presentation on “Using Neo4j for Modeling Complex Telco Network.” Their talk delved into the intricacies of modelling telco networks using Neo4j, showcasing the advantages of graph databases in this domain.</p>
  </li>
</ul>

<p>In addition to the presentations, attendees had the opportunity to participate in the GraphWorkshop titled “Building a Knowledge Centric Fraud Detection Graph”, conducted by Andrew Conacher and Muddassir Zaidi from Neo4j. The workshop offered hands-on experience in constructing a fraud detection graph and provided practical insights into leveraging knowledge-centric approaches.</p>

<p>Overall, Graph Summit Melbourne 2023 proved invaluable, fostering knowledge sharing and paving the way for future advancements in the field. The <a href="https://github.com/neo4j-field/graph-summit-apac-2023" target="_blank">GitHub</a> link for the GraphWorkshop materials is available for those who want to dive deeper into the concepts covered during the event.</p>]]></content><author><name></name></author><category term="analytics" /><category term="melbourne" /><category term="graphs" /><category term="neo4j" /><summary type="html"><![CDATA[I have recently had a pleasure to attend Graph Summit Melbourne 2023 and it was a resounding success, bringing together experts and enthusiasts from the graph technology community. Attendees were treated to a range of enlightening presentations and workshops showcasing the transformative power of graphs.]]></summary></entry><entry><title type="html">Tuning LLMs beyond prompt engineering</title><link href="https://ibragimov.org/2023/05/10/llm-parameters.html" rel="alternate" type="text/html" title="Tuning LLMs beyond prompt engineering" /><published>2023-05-10T00:00:00+10:00</published><updated>2023-05-10T00:00:00+10:00</updated><id>https://ibragimov.org/2023/05/10/llm-parameters</id><content type="html" xml:base="https://ibragimov.org/2023/05/10/llm-parameters.html"><![CDATA[<p>I see most of the content is focusing on tweaking ChatGPT models using prompt engineering. I agree, the bulk of the impact is in creative prompts. However, there are a few, more traditional parameters, that we often forget about. In this arcitle, I will cover the ones I found most useful for my work.</p>

<p>The goal of this article is not to provide comprehensive documentation of parameters but to point to the ones I found most important. Then readers can refer to the <a href="https://platform.openai.com/docs/api-reference/completions/create" target="_blank">official documentation</a> to get the details.</p>

<h3 id="1-temperature">1. Temperature</h3>
<p>Temperature is the parameter that I tune the most. It corresponds to randomness of output or how diverse the output can be. It ranges from 0 to 2. When it’s 0, the output will be deterministic, as the model always chooses the most likely token. At temperatures closer to 2, the output will be diverse and more “creative”.</p>

<h3 id="2-top_p---nucleus-sampling">2. Top_p - nucleus sampling</h3>

<p>This is an alternative to temperature parameter. Instead of considering temperature, this parameter considers only outputs that are more likely with cumulative probability adding up to top_p. For example, if top_p = 0.2, it considers tokens that fall into 20% of the probability mass.</p>

<h3 id="3-n---number-of-completions">3. N - number of completions</h3>

<p>This is number of completions, if you want to generate more than one response. Be careful, as it eats into your token budget.</p>

<h3 id="4-frequency-and-presence-penalties">4. Frequency and presence penalties</h3>

<p>Frequency penalty penalises multiple use of the same word. Presence penalty does not consider number of times the word used but wheather it is being used or not, so it’s boolean in nature.</p>

<p>They are used directly in calculating logits. Here’s the formula:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mu</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="n">mu</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">-</span> <span class="n">c</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">alpha_frequency</span> <span class="o">-</span> <span class="nb">float</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">*</span> <span class="n">alpha_presence</span>
</code></pre></div></div>

<p>There are more parameters in the <a href="https://platform.openai.com/docs/api-reference/completions/create" target="_blank">official documentation</a> but these ones made the biggest difference in my experiments. If you think there is a missing one, please <a href="/contact/" target="_blank">drop me a note</a>, I’ll be happy to include it here :).</p>]]></content><author><name></name></author><category term="llm" /><category term="chatgpt" /><category term="tuning" /><summary type="html"><![CDATA[I see most of the content is focusing on tweaking ChatGPT models using prompt engineering. I agree, the bulk of the impact is in creative prompts. However, there are a few, more traditional parameters, that we often forget about. In this arcitle, I will cover the ones I found most useful for my work.]]></summary></entry><entry><title type="html">This newsletter reached 100 subscribers! First milestone</title><link href="https://ibragimov.org/2023/04/29/newsletter-reached-100-subscribers.html" rel="alternate" type="text/html" title="This newsletter reached 100 subscribers! First milestone" /><published>2023-04-29T00:00:00+10:00</published><updated>2023-04-29T00:00:00+10:00</updated><id>https://ibragimov.org/2023/04/29/newsletter-reached-100-subscribers</id><content type="html" xml:base="https://ibragimov.org/2023/04/29/newsletter-reached-100-subscribers.html"><![CDATA[<p>This is the first milestone for my newsletter - I reached 100 subscribers last week, after launching it 2 months ago.</p>

<p>Here’s what I learned during the last 2 months:</p>

<ol>
  <li>
    <p><strong>Events drive the engagement</strong>. When I look at my subscribers graph, the two events that I ran, generated big bumps of new subscribers. Another source of subscribers, although smaller but more consistent, is publishing to my LinkedIn network, where I have 1,500 followers.</p>
  </li>
  <li>
    <p><strong>Organic discovery is slow</strong>. The goal for me was not to grow it as quick as possible, but rather to learn the skills required to run the newsletter and a promote it and just to have fun sharing my knowledge. I also realised how important the discovery is and how slow is organic growth, without social media.</p>
  </li>
  <li>
    <p><strong>Even at small scale, publishing online can drive a lot of networking opportunities, sourcing great ideas and finding leads</strong>. I’ve never had so many people, who I know and strangers, reaching out with ideas, leads and interesting connections.</p>
  </li>
  <li>
    <p><strong>Social media consumes a lot of time</strong>, so prioritising it is vital when you don’t have a team to rely on.</p>
  </li>
  <li>
    <p><strong>Ask for feedback proactively</strong>. As with any product or service it is almost impossible to get it right the first time. On the other hand, over-planning is also counterproductive. So, from the beginning I decided to prioritise action over planning, just give it a crack and just fix based on user feedback.</p>
  </li>
  <li>
    <p><strong>I learned heaps</strong> by just writing a newsletter every week</p>

    <ul>
      <li>
        <p><strong>Writing</strong> with the help of GPT-4 is much easier but a bit of an art. You do need to provide your original ideas first.</p>
      </li>
      <li>
        <p><strong>Optimising my time</strong> to write weekly edition of newsletter based on my learning routine is important</p>
      </li>
      <li>
        <p>Refreshed my skills on running and optimising a website in the <strong>cloud</strong>, as well as automating my workflow through scripts and storing content in git</p>
      </li>
      <li>
        <p><strong>SEO</strong> optimisation is an art</p>
      </li>
      <li>
        <p><strong>Audio editing</strong> skills and working with professional microphones is an entire new world for me</p>
      </li>
      <li>
        <p><strong>Voice training</strong>. By hearing your own voice gives a lot of room for improvement. I also discovered that voice training is a thing not only for actors but also for business professionals.</p>
      </li>
      <li>
        <p>Understanding the <strong>social media</strong> ecosystem that I have never tapped into in the past</p>
      </li>
      <li>
        <p>Overall <strong>structuring</strong> of my thoughts and knowledge</p>
      </li>
    </ul>
  </li>
</ol>

<p>Next milestone is 500 subscribers!</p>]]></content><author><name></name></author><category term="personal" /><category term="newsletter" /><category term="networking" /><category term="lessons" /><summary type="html"><![CDATA[This is the first milestone for my newsletter - I reached 100 subscribers last week, after launching it 2 months ago.]]></summary></entry><entry><title type="html">My prompt engineering best practices</title><link href="https://ibragimov.org/tip/2023/04/24/prompt-engineering.html" rel="alternate" type="text/html" title="My prompt engineering best practices" /><published>2023-04-24T00:00:00+10:00</published><updated>2023-04-24T00:00:00+10:00</updated><id>https://ibragimov.org/tip/2023/04/24/prompt-engineering</id><content type="html" xml:base="https://ibragimov.org/tip/2023/04/24/prompt-engineering.html"><![CDATA[<p>I’ve been <a href="/tip/2023/02/25/chatgpt-to-speed-up-coding.html" target="_blank">playing</a> with GPT-4 over the last few weeks and there are a few prompt engineering best practices that I developed through my exploration that I want to share here.</p>

<p>Here are my 5 best practices for prompt engineering:</p>
<ol>
  <li>Write instructions clearly, as you would do for an intern</li>
  <li>Add structure to your prompt</li>
  <li>Develop prompts iteratively</li>
  <li>Reduce the risk of prompt injection by using prompt delimiters</li>
  <li>Never trust the model</li>
</ol>

<p>In the rest of the article, I will expand on each of these practices.</p>

<h3 id="write-instructions-clearly-as-you-would-do-for-an-intern">Write instructions clearly, as you would do for an intern</h3>

<p>The number one skill for prompt engineering, is to give clear, unambiguous instructions to what you want to produce. I find it a bit like coaching interns, where you want to lead them to get the right answer, without letting them going into wrong direction. Clear instructions also mean they may not be short.</p>

<p>If I know what is required to solve the problem, I often also provide the steps that the model should follow, and it really helps to nail the answer faster.</p>

<p>This also includes checking for failure conditions. For example, if I want to extract all the dates from the text and the text doesn’t have any dates, I ask the model to output “no dates found”, to avoid hallucinations.</p>

<h3 id="add-structure-to-your-prompt">Add structure to your prompt</h3>

<p>The anatomy of an LLM prompt that I usually follow is this:</p>
<ol>
  <li>context</li>
  <li>request</li>
  <li>text to analyse</li>
  <li>output specification.</li>
</ol>

<p>Each one of them, except for probably 3, can be improved with the structure.</p>

<p>For the <strong>context</strong>, if the problem is nontrivial, I tend to favour few-shots learning, where I provide a couple of examples, how to solve it. The context can also include some assumptions, that model need to know before tackling the problem. When writing a chatbot, context can also include roles, such as system, user, assistant.</p>

<p>In <strong>request</strong>, if the problem is nontrivial, I tend to specify steps to solve it, failure modes, and even steps to check itself. This can also include specifications such as tone, translation language and references.</p>

<p>I often need to use <strong>outputs</strong> of the model in other parts of the problem and parsing arbitrary output can be painful. When I write my prompts, I specify exact format that I want the output to be. For example, JSON with the specific structure.</p>

<h3 id="develop-prompts-iteratively">Develop prompts iteratively</h3>

<p>Prompts never work from the first time, just like developing any machine learning models. The key here is to build them iteratively starting from simple prompt and growing details. All the best practices that I described in the previous section can and need to be added iteratively, otherwise you are risking of overengineering your prompts.</p>

<p>The process that I use is:</p>

<div class="mermaid">
graph TD
    id1([prompt idea]) --&gt; id2([implementation])
    id2 --&gt; id3([analyse result])
    id3 --&gt; id4([make adjustments to the prompt])
    id4 --&gt; id2
</div>

<h3 id="reduce-the-risk-of-prompt-injection-by-using-prompt-delimiters">Reduce the risk of prompt injection by using prompt delimiters</h3>

<p>When sending LLM model a prompt one part will be some sort of context and instructions and another one will be the actual text to analyse. After reading a couple of articles on prompt injection, I started wrapping text to analyse into prompt delimiters, such as triple backquote. This also flags the model that text between these delimiters is the main text for it to analyse and it’s not context or instructions.</p>

<h3 id="never-trust-the-model">Never trust the model</h3>

<p>As good as the LLM model is, it still hallucinates quite a lot. When you give clear instructions and structure, it usually reduces the hallucinations but it still happens. Another issue that I found with these models is forgetting - context that I’ve given a few prompts ago is lost. So, for any final output, I carefully check every sentence that the model produce.</p>

<p>Obviously, this is not a complete list of best practices, just the ones I developed for myself. If you have any best practices that you find useful, I’d love to hear about them, and I can share it in the future articles.</p>]]></content><author><name></name></author><category term="tip" /><category term="analytics" /><category term="data" /><category term="llm" /><category term="promt engineering" /><category term="best practices" /><summary type="html"><![CDATA[I’ve been playing with GPT-4 over the last few weeks and there are a few prompt engineering best practices that I developed through my exploration that I want to share here.]]></summary></entry></feed>