<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aarushi Kansal</title>
    <description>The latest articles on DEV Community by Aarushi Kansal (@aarushikansal).</description>
    <link>https://dev.to/aarushikansal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F212124%2F312e21cd-ca77-43da-99cc-cdd84221539e.jpg</url>
      <title>DEV Community: Aarushi Kansal</title>
      <link>https://dev.to/aarushikansal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aarushikansal"/>
    <language>en</language>
    <item>
      <title>Personal movie recommendation agent with GPT4 + Neo4J</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Tue, 20 Jun 2023 09:25:43 +0000</pubDate>
      <link>https://dev.to/aarushikansal/personal-movie-recommendation-agent-with-gpt4-neo4j-3aib</link>
      <guid>https://dev.to/aarushikansal/personal-movie-recommendation-agent-with-gpt4-neo4j-3aib</guid>
      <description>&lt;p&gt;Large Language Model (LLM) powered applications become more powerful and intriguing when you start leveraging the model's reasoning abilities, rather than pure generation abilities. &lt;/p&gt;

&lt;p&gt;And combine that reasoning with external tools like databases and APIs and you have yourself an application that can reason and take actions. &lt;/p&gt;

&lt;p&gt;Over the past few months I've been deep in the world of using LLMs for both personalized recommendations and reasoning and combing the two concepts, in more of assistant style format. &lt;/p&gt;

&lt;p&gt;When you think of recommendation engines, maybe you see it as a huuuge topic to tackle, teams of data scientists, ML engineers, GPUs? &lt;/p&gt;

&lt;p&gt;While that holds true, you can still get started with some basic DS algorithms, an LLM and some UI libraries. &lt;/p&gt;

&lt;p&gt;I wanted to see what I could do with a knowledge graph since they can be a good basis for recommendation engines. And luckily, LangChain already has a chain that can be used with Neo4j, so that's what we'll use. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;First we need a dataset and we'll use the default movies one provided by Neo4j. You can also find others on Kaggle, or create your own (probably more for when you're ready for a production system, cause trust me, cleaning data is a tiresome task!) &lt;/p&gt;

&lt;p&gt;You can find the various existing sets + set up your sandbox database &lt;a href="https://sandbox.neo4j.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  LangChain
&lt;/h3&gt;

&lt;p&gt;If there's something you want to use with an LLM, your best bet is to first check what's going on in the LangChain world. &lt;/p&gt;

&lt;p&gt;LLMs are very good at creating Cypher queries, and I wanted to use an LLM to give a user a conversational way to get their personalized recommendations. This essentially means, we need something that takes a users natural language, and creates a Cypher query out of it that can be used to query the DB. &lt;/p&gt;

&lt;p&gt;And LangChain's &lt;a href="https://python.langchain.com/docs/modules/chains/additional/graph_cypher_qa" rel="noopener noreferrer"&gt;Graph DB QA chain&lt;/a&gt; does just that. &lt;/p&gt;

&lt;p&gt;Set up is farily simple, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph = Neo4jGraph(
    url="bolt://18.212.1.173:7687",
    username="neo4j", 
    password="finishes-executions-arcs"
)


os.environ['OPENAI_API_KEY'] = "sk-key"

chain = GraphCypherQAChain.from_llm(
    ChatOpenAI(model_name="gpt-4", temperature=0.0), graph=graph, verbose=True,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Main thing here is setting the temperature to 0 so the LLM doesn't try and get 'creative' with queries. We want a deterministic output here. &lt;/p&gt;

&lt;p&gt;With just this set up alone, you can start doing some basic Q+A as well as getting it to run basic queries. &lt;/p&gt;

&lt;h3&gt;
  
  
  Q&amp;amp;A + Basic queries
&lt;/h3&gt;

&lt;p&gt;Let's try out this chain, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chain.run(
    """
        Set Cynthia Freeman's rating for Inception to 4.0.
    """
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key here is that while this LLM has no awareness of your actual data or schema by default, the chain runs a few queries to get the entire schema and pass the schema in as context into the prompt. So all of a sudden, it's like your LLM has a solid understanding of your exact DB! Simple but elegant solution really. &lt;/p&gt;

&lt;p&gt;And that's why it's great at figuring out queries like the above. &lt;/p&gt;

&lt;p&gt;Let's try out some other questions, we're working on recommendations right, so let's see if our LLM can find us movies in similar genres. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;find me movies most similar to 'Inception'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At this point, most likely it'll try and base it on genre or imdb ratings. So far pretty good. The LLM is doing enough reasoning to understand what 'similar' could mean (ie. genre or ratings). &lt;/p&gt;

&lt;p&gt;You can tell it to base it on genre, making sure it always basis similarity on genre. Go further and tell it actors and it'll correctly identify that - by figuring out the movie to actor/s relationship and counting how many shared actors a movie has to Inception. &lt;/p&gt;

&lt;p&gt;Now, at this point, the aspect I'm more interested in is the different similarity functions and algorithms we can apply to start getting recommendations for movies. &lt;/p&gt;

&lt;p&gt;In particular, I want to use Neo4j's &lt;a href="https://python.langchain.com/docs/modules/chains/additional/graph_cypher_qa" rel="noopener noreferrer"&gt;data science library&lt;/a&gt;. You can go ahead and read about the different ways of calculating similarities, if you aren't familiar.&lt;/p&gt;

&lt;p&gt;And I want to some collaborative filtering, based on kNN. Essentially, I want recommendations based on users with similar tastes to mine, their top rated movies, that I haven't rated (no rating infers hasn't been watched). &lt;/p&gt;

&lt;p&gt;So you can try any form of that question now&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Who are the 5 users with tastes in movies most similar to Aarushi Kansal? What movies have they rated highly that Aarushi Kansal hasn't rated yet?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This seems pretty specific right, but unfortunately, it doesn't give me quite what I want. The query it comes out with is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MATCH (u1:User {name: "Aarushi Kansal"})-[:RATED]-&amp;gt;(m1:Movie)&amp;lt;-[:IN_GENRE]-(g:Genre)-[:IN_GENRE]-&amp;gt;(m2:Movie)&amp;lt;-[:RATED]-(u2:User)
WHERE NOT (u1)-[:RATED]-&amp;gt;(m2)
WITH u2, count(*) AS similarity, m2.title AS recommended_movie, m2.imdbRating as rating
ORDER BY similarity DESC, rating DESC
RETURN u2.name AS user, recommended_movie
LIMIT 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay so what if we go more specific?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Who are the 5 users with tastes in movies most similar to Aarushi Kansal? What movies have they rated highly that Aarushi Kansal hasn't rated yet? Use kNN and Pearson similarity&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At this point, it tried hard, but the query just doesn't work at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MATCH (u1:User {name: "Aarushi Kansal"})-[:RATED]-&amp;gt;(m1:Movie)&amp;lt;-[:RATED]-(u2:User)
WITH u1, u2, tofloat(count(m1)) as numCommonMovies
MATCH (u1)-[r1:RATED]-&amp;gt;(m1:Movie)&amp;lt;-[r2:RATED]-(u2)
WITH u1, u2, numCommonMovies, m1,
     (r1.rating - u1.avgRating) * (r2.rating - u2.avgRating) as simNumer,
     (r1.rating - u1.avgRating) * (r1.rating - u1.avgRating) as simDenom1,
     (r2.rating - u2.avgRating) * (r2.rating - u2.avgRating) as simDenom2
WITH u1, u2, numCommonMovies, sum(simNumer) as simNumer, sum(simDenom1) as simDenom1, sum(simDenom2) as simDenom2
WITH u1, u2, simNumer, sqrt(simDenom1 * simDenom2) as simDenom
WHERE simDenom &amp;gt; 0
WITH u1, u2, numCommonMovies, simNumer / simDenom as pearson
ORDER BY pearson DESC, numCommonMovies DESC, u2.name ASC
LIMIT 10
MATCH (u2)-[r:RATED]-&amp;gt;(m:Movie)
WHERE NOT (u1)-[:RATED]-&amp;gt;(m) AND r.rating &amp;gt;= 4
RETURN u2.name as UserName, m.title as MovieTitle, r.rating as UserRating
ORDER BY r.rating DESC, m.title ASC, u2.name ASC;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the best solution is to actually give it an example of the query you actually want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MATCH (u1:User {name:"Aarushi Kansal"})-[r:RATED]-&amp;gt;(m:Movie)
WITH u1, avg(r.rating) AS u1_mean

MATCH (u1)-[r1:RATED]-&amp;gt;(m:Movie)&amp;lt;-[r2:RATED]-(u2)
WITH u1, u1_mean, u2, COLLECT({r1: r1, r2: r2}) AS ratings WHERE size(ratings) &amp;gt; 10

MATCH (u2)-[r:RATED]-&amp;gt;(m:Movie)
WITH u1, u1_mean, u2, avg(r.rating) AS u2_mean, ratings

UNWIND ratings AS r

WITH sum( (r.r1.rating-u1_mean) * (r.r2.rating-u2_mean) ) AS nom,
     sqrt( sum( (r.r1.rating - u1_mean)^2) * sum( (r.r2.rating - u2_mean) ^2)) AS denom,
     u1, u2 WHERE denom &amp;lt;&amp;gt; 0

WITH u1, u2, nom/denom AS pearson
ORDER BY pearson DESC LIMIT 10

MATCH (u2)-[r:RATED]-&amp;gt;(m:Movie) WHERE NOT EXISTS( (u1)-[:RATED]-&amp;gt;(m) )

RETURN m.title, SUM( pearson * r.rating) AS score
ORDER BY score DESC LIMIT 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Annd, it works, I get movies like The Silence of the Lambs, Forest Gump, Pulp Fiction etc. &lt;/p&gt;

&lt;p&gt;Up til now you can see we've gotten to a pretty good place, we can do querying on a knowledge graph, and even without too much context/ prompt engineering it's able to determine what relationships to search through (e.g. movies -&amp;gt; genres). As you add more guidance it gets better and better. &lt;/p&gt;

&lt;p&gt;But having to give it an example of every similarity function or algorithm makes it a pretty poor assistant and bad user experience. Users would be better off just querying the DB or having some kind of button that runs the query etc. &lt;/p&gt;

&lt;p&gt;And that's where we now combine what we have so far, with an Agent and Chainlit for that assistant style user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;p&gt;First let's briefly summarize what we're aiming for. &lt;/p&gt;

&lt;p&gt;A human-eqsue experience for a user, for movie recommendations. They should be able to ask for movies, based on their interests, update ratings and the agent should have some understanding about a user. &lt;/p&gt;

&lt;p&gt;1) Chat interface&lt;br&gt;
2) Natural language understanding&lt;br&gt;
3) Access to data source (I'm also going to give it access to the internet, because I think an agent should be able get fun facts or summarizes, or even recent news about actors or directors)&lt;br&gt;
4) Reasoning abilities to choose what tools and action to take&lt;/p&gt;
&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;

&lt;p&gt;For the interface, I'm using &lt;a href="https://docs.chainlit.io" rel="noopener noreferrer"&gt;chainlit&lt;/a&gt;, a new UI library for building LLM apps, with an integration with Langchain. &lt;/p&gt;

&lt;p&gt;I'm using the out of the box chat UI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j2wdwitsjmvb8jyoylt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9j2wdwitsjmvb8jyoylt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For natural lanaguage understanding I'm using GPT-4, but you can sub out your favorite LLM here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;llm1 = OpenAI(temperature=0, streaming=True)
    # search = SerpAPIWrapper()
    memory = ConversationBufferMemory(
        memory_key="chat_history", return_messages=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With memory, so it can remember the context of our conversation (an agent that forgets messages, feels like bad UX!)&lt;/p&gt;

&lt;p&gt;I'm using chat-zero-shot-react-description, which is a MRKL implementation for chat models. If you're interested in MRKL agents and an intro into tools, &lt;a href="https://dev.to/aarushikansal/giving-your-large-language-model-skills-stoicism-meets-ai-5gd1"&gt;you can check out another blog of mine&lt;/a&gt;. But in a nutshell, this is what allows the model to choose what tool (DB or Google search) to use when answering a user's requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    tools = [
        Tool(
            name="Cypher search",
            func=cypher_tool.run,
            description="""
            Utilize this tool to search within a movie database, 
            specifically designed to find movie recommendations for users.
            This specialized tool offers streamlined search capabilities
            to help you find the movie information you need with ease.
            """,
        ),
        Tool(
            name="Google search",
            func=search.run,
            description="""
    Utilize this tool to search the internet when you're missing information. In particular if you want recent events or news.
    """,
        )
    ]
    return initialize_agent(
        tools, llm1, agent="chat-zero-shot-react-description", verbose=True, memory=memory
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Annnd, finally the Cypher/Neo4j/knowledge graph parts! So, remember earlier on, we found that the more context you give the LLM (details on which parts of the schema to use, example queries etc), the better it performs at finding the right movies for you? But the whole point here is to give the user an easy way to get recommendations, but not have to know or understand the inner workings of our DB or even Cypher. &lt;/p&gt;

&lt;p&gt;Essentially, we want to bake the logic in the backend and the user never has to know.&lt;/p&gt;

&lt;p&gt;So, what we're going to do is determine which exact usecases we want this agent to handle (or feel like an expert in). I.e. we're going to tell it exactly how to handle certain requests. &lt;/p&gt;

&lt;p&gt;For the purpose of this post, I'm giving it the specifics of finding movie recommendations based on similar users and movies similar to another movie, based on content (i.e genres) using the Jacard index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CYPHER_GENERATION_TEMPLATE = """Task:Generate Cypher statement to query a graph database. 
Instructions:
Make recommendations for a given user only. 
Update ratings for a given user only.
Schema:
{schema}
Username: 
{username}

Examples:
# When a user asks for movie recommendations: 


    # When asked for movies similar to a movie, use the weighted content algorithm, like this: 

CYPHER_GENERATION_PROMPT = PromptTemplate(
    input_variables=["schema", "question", "username"], template=CYPHER_GENERATION_TEMPLATE
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: this is the template built in LangChain, that I've repurposed for my needs. If you remove this piece of code, it will still work, just with the defaults we used earlier.&lt;/p&gt;

&lt;p&gt;At this point you might be thinking, we've made this agent kind of 'dumb' by only allowing it to do things..? An if statement could have sufficed? Well, don't worry giving it examples like this only expands it's so called knowledge. It's still able to do all the other things like find movies based on actors and update your ratings. &lt;/p&gt;

&lt;p&gt;You can play around with different/more algorithms based on your needs. &lt;/p&gt;

&lt;p&gt;Let's see it action so far by asking it "what movie should I watch?":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63dm9jo39elibv6spd6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63dm9jo39elibv6spd6w.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you can see it starts using the query for collaborative filtering based on neighbourhood - exactly what I wanted. &lt;/p&gt;

&lt;p&gt;Let's try another one, "Suggest movies similar to Inception"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fraysk11fsw5fv56bhanu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fraysk11fsw5fv56bhanu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, now you can see it using the desired query. &lt;/p&gt;

&lt;p&gt;If you want, now you can also start asking it about actors, news about them and so on, which it'll handle via our Google search tool. &lt;/p&gt;

&lt;p&gt;Annd there you have it, an end to end personalised movie agent for you!&lt;br&gt;
&lt;a href="https://gist.github.com/aarushik93/8b979de55d913439e21ac6f3302ec55d" rel="noopener noreferrer"&gt;You can check out the full code here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.chainlit.io/examples/mrkl" rel="noopener noreferrer"&gt;https://docs.chainlit.io/examples/mrkl&lt;/a&gt;&lt;br&gt;
&lt;a href="https://neo4j.com/docs/graph-data-science/current/" rel="noopener noreferrer"&gt;https://neo4j.com/docs/graph-data-science/current/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://neo4j.com/docs/graph-data-science/current/algorithms/kmeans/" rel="noopener noreferrer"&gt;https://neo4j.com/docs/graph-data-science/current/algorithms/kmeans/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://python.langchain.com/docs/modules/chains/additional/graph_cypher_qa" rel="noopener noreferrer"&gt;https://python.langchain.com/docs/modules/chains/additional/graph_cypher_qa&lt;/a&gt;&lt;br&gt;
&lt;a href="https://neo4j.com/developer-blog/exploring-practical-recommendation-systems-in-neo4j/" rel="noopener noreferrer"&gt;https://neo4j.com/developer-blog/exploring-practical-recommendation-systems-in-neo4j/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>llms</category>
    </item>
    <item>
      <title>AWS + Falcon Quickstart</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sat, 03 Jun 2023 20:09:13 +0000</pubDate>
      <link>https://dev.to/aarushikansal/aws-falcon-quickstart-1ob</link>
      <guid>https://dev.to/aarushikansal/aws-falcon-quickstart-1ob</guid>
      <description>&lt;p&gt;Okay, so I haven't used SageMaker in a looooong time (maybe like 4 years or so ago) and I have to say, it feels like a whole new ecosystem. It's definitely a lot more intuitive, and waay more features. And now with easy access to foundational models as well as models from HuggingFace, it's starting to climb up my list of preferred ML/AI platforms. &lt;/p&gt;

&lt;p&gt;And in this post I wanna show you how to deploy and use the shiny new Falcon models. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is SageMaker
&lt;/h2&gt;

&lt;p&gt;It's basically AWS' fully managed, end to end ML platform. This includes an IDE (Jupyter Notebooks), storage, foundational models and one click deployments. All of the infrastructure management is handled by AWS. &lt;/p&gt;

&lt;h2&gt;
  
  
  Roles and Permissions
&lt;/h2&gt;

&lt;p&gt;The first thing you're going to need is to create a role (or maybe you have a default role you want to use), that has the AmazonSageMakerFullAccess policy attached to it. Give it a name you'll remember so you can use it later on. &lt;/p&gt;

&lt;p&gt;In my case, I'm gonna go with:&lt;/p&gt;

&lt;p&gt;AmazonSageMakerRole-experimentation&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Domain
&lt;/h2&gt;

&lt;p&gt;So from AWS: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A domain includes an associated Amazon Elastic File System (EFS) volume; a list of authorized users; and a variety of security, application, policy, and Amazon Virtual Private Cloud (VPC) configurations. Each user in a domain receives a personal and private home directory within the EFS for notebooks, Git repositories, and data files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essentially, it's your home for everything you'll need to train, finetune, build and deploy models. Both as an individual or collaboratively in a team. &lt;/p&gt;

&lt;p&gt;Go ahead and navigate to SageMaker &amp;gt; Domains and create a domain. It'll take you to a screen like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B7GQMSoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wk3o093oevyyoj8eg1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B7GQMSoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wk3o093oevyyoj8eg1w.png" alt="Image description" width="800" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll go with the quick set up for the purpose of this post. &lt;/p&gt;

&lt;p&gt;Here you can use any name you want for your domain and a user you'll create with the role you previously created. &lt;/p&gt;

&lt;p&gt;Once you've chosen your names and selected your role, it'll take some time to spin up your domain. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying a model
&lt;/h2&gt;

&lt;p&gt;Now that you're domain is running, head into users and select launch. You'll have a few options, go for studio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NXOBf29j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zq3u3aosbwa2ahehwrl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NXOBf29j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zq3u3aosbwa2ahehwrl3.png" alt="Image description" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new notebook and we'll use the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sagemaker
import boto3
from sagemaker.huggingface import HuggingFaceModel

try:
    role = sagemaker.get_execution_role()
except ValueError:
    iam = boto3.client('iam')
    role = role = iam.get_role(RoleName='sagemaker_execution_role')['Role']['Arn']
# Hub Model configuration. https://huggingface.co/models
hub = {
    'HF_MODEL_ID':'tiiuae/falcon-7b',
    'HF_TASK':'text-generation'
}

# create Hugging Face Model Class
huggingface_model = HuggingFaceModel(
    transformers_version='4.26.0',
    pytorch_version='1.13.1',
    py_version='py39',
    env=hub,
    role=role, 
)

# deploy model to SageMaker Inference
predictor = huggingface_model.deploy(
    initial_instance_count=1, # number of instances
    instance_type='ml.m5.xlarge' # ec2 instance type
)

predictor.predict({
    "inputs": "Once upon a time in Narnia ",
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the general code you'll use for all HuggingFace models. You'll just needed to change the details such as which model, what AWS instance, what Python libraries and versions etc.&lt;/p&gt;

&lt;p&gt;Take note, in the predictor code, your choosing 1 instance of type ml.m5.xlarge. You can use different options here, but depending on your account you might need to adjust your quotas for resources like an ml.m5.xlarge instance!&lt;/p&gt;

&lt;p&gt;Now you're ready to run and you should get some text generated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The endpoint
&lt;/h2&gt;

&lt;p&gt;So far you've just run it via a Jupyter notebook. But don't worry it's actually deployed an API you can use. So go to Deployments &amp;gt; Endpoints and you'll see the one you just deployed. &lt;/p&gt;

&lt;p&gt;Once you click into it you'll be able to test the inference endpoint, as well as see various bits of information about your endpoint such as traffic patterns. You'll also see the actual endpoint that you can now use within your LLM powered applications. &lt;/p&gt;

&lt;h2&gt;
  
  
  Bits and pieces
&lt;/h2&gt;

&lt;p&gt;This was a quickstart and SageMaker has a lot more to it. So I would recommend playing around with it as much as possible and deploy different models. Just remember to shut everything down when you're done!&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>aws</category>
    </item>
    <item>
      <title>Opensource with HuggingFace</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sun, 21 May 2023 16:17:32 +0000</pubDate>
      <link>https://dev.to/aarushikansal/opensource-with-huggingface-2e7</link>
      <guid>https://dev.to/aarushikansal/opensource-with-huggingface-2e7</guid>
      <description>&lt;p&gt;"We Have No Moat, And Neither Does OpenAI"&lt;/p&gt;

&lt;p&gt;"Open-source models are faster, more customizable, more private, and pound-for-pound more capable."&lt;/p&gt;

&lt;p&gt;You've probably all heard these quotes by now and if you haven't checkout em out &lt;a href="https://www.semianalysis.com/p/google-we-have-no-moat-and-neither"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And both Google and OpenAI should rightfully be worried. We're well and truly in the age of democratized machine learning. &lt;/p&gt;

&lt;p&gt;As big tech and the tech community quickly churn out open source models, it just makes our lives easier, to pick and choose which models serve us and in what way. &lt;/p&gt;

&lt;p&gt;Given that, just open sourcing a model isn't enough, we have to be able to deploy, run and maintain it. Thankfully, even this is becoming easier and easier. &lt;/p&gt;

&lt;p&gt;In this post I want to walk you through one of the simplest ways of deploying and (if you have money) scaling these models. &lt;/p&gt;

&lt;h2&gt;
  
  
  HuggingFace
&lt;/h2&gt;

&lt;p&gt;Deploying on HuggingFace is definitely my favourite, it's super easy to get started and there's burgeoning community developing in the opensource machine learning space. &lt;/p&gt;

&lt;p&gt;If you're not already familiar with HuggingFace, it's an end to end machine learning platform, with a GitHub like interface. &lt;/p&gt;

&lt;p&gt;One of my favourite features is the model hub + the ease of deploying a model. And this is what I'm going to show you now. &lt;/p&gt;

&lt;p&gt;First let's take a look at the model hub: &lt;a href="https://huggingface.co/models"&gt;https://huggingface.co/models&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you'll find all the open source models, from both individual people as well as companies like Google, Meta, OpenAI etc. &lt;/p&gt;

&lt;p&gt;For the purpose of this blog, let's go ahead and find StabilityAI's stable-diffusion-2. A text to image model, because playing with images is fun: &lt;a href="https://huggingface.co/stabilityai/stable-diffusion-2"&gt;https://huggingface.co/stabilityai/stable-diffusion-2&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Here, you can see all the information about the model, relevant research papers, licenses, model card, examples, useages, the code etc. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2oMNN_9o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puojgju55r62rh2n4h6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2oMNN_9o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puojgju55r62rh2n4h6r.png" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To the right, you'll notice a deploy button. Go ahead and click that. There's three different options: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;InferenceAPI (which allows you to use the model in API form for testing purposes: this is not for production use!)&lt;/li&gt;
&lt;li&gt;Inference Endpoints (which is what we'll use) &lt;/li&gt;
&lt;li&gt;Spaces (this allows you to deploy the model behind a GUI using Gradio, Streamlit etc. We won't cover this in this post). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OJKRpNCq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etwffdrd9tcnx125ty7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OJKRpNCq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etwffdrd9tcnx125ty7h.png" alt="Image description" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can choose a cloud provider: so far AWS has the most GPU options (and I haven't actually seen GCP usable, so I don't know if that's available yet or not!). &lt;/p&gt;

&lt;p&gt;For this model, I chose a large GPU on AWS, feel free to try others, however, small ran out of memory for me!&lt;/p&gt;

&lt;p&gt;Once you've clicked deploy, maybe go get a coffee or something cause deploying will take some time. &lt;/p&gt;

&lt;p&gt;As soon as it's up and running, you can start using the built in UI for testing. More importantly, you can also use it as an API to power your applications. &lt;/p&gt;

&lt;p&gt;For example, testing: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uva_Uoto--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7j958obd1b4b2v130f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uva_Uoto--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7j958obd1b4b2v130f3.png" alt="Image description" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the equivalent cuRL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://endpoint-name.us-east-1.aws.endpoints.huggingface.cloud \
-X POST \
-d '{"inputs":"A beautiful sunset over the horizon on a clear day in Rome"}' \
-H "Authorization: Bearer &amp;lt;hf_token&amp;gt;" \
-H "Content-Type: application/json"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can use this API and your token to build any apps or tools you want.&lt;/p&gt;

&lt;p&gt;At this point, you're probably wondering about scalability, monitoring and observability. &lt;/p&gt;

&lt;h2&gt;
  
  
  Scalability
&lt;/h2&gt;

&lt;p&gt;If you flick through the tabs at the top, you can configure replica autoscaling to suit your needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;p&gt;The analytics tab is a good starting point, to monitor latency, requests, and utilization. &lt;/p&gt;

&lt;p&gt;I would suggest building out more detailed monitoring dashboard once you actually build an application on top of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability
&lt;/h2&gt;

&lt;p&gt;The logs tab again is a good starting point to see what's going on with your model. &lt;/p&gt;

&lt;p&gt;I would suggest more verbose, detailed logging at various levels of your actual application (LB, API gateway, server etc)&lt;/p&gt;

&lt;p&gt;Annd, there you have it, a fairly production ready Generative AI API for you to utilize. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Always remember to delete or pause your deployed models, if you don't want a nasty surprise at the end of the month!&lt;/p&gt;

&lt;p&gt;Last thought I want to leave you with: really consider the cost of hosting a model vs using one as a service through something like OpenAI. A lot of these services are very cheap, compared to running a model yourself (on prem or cloud), so always do some maths and projections before making a choice!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Superpower your push notifications with AI</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Mon, 15 May 2023 00:30:47 +0000</pubDate>
      <link>https://dev.to/aarushikansal/superpower-your-push-notifications-with-ai-348l</link>
      <guid>https://dev.to/aarushikansal/superpower-your-push-notifications-with-ai-348l</guid>
      <description>&lt;p&gt;Lately, I've been spending a lot of time thinking about how best to target users in a meaningful way that doesn't feel so spammy - I've come to the conclusion that AI can help me with super, super personalized, almost real time personalization. &lt;/p&gt;

&lt;p&gt;In particular, I want to focus on push notifications - in my experience, our phones are over saturated with notifications. Looking at my screen right now, I have about 56 notifications from different apps and none of them really stand out to me.&lt;/p&gt;

&lt;p&gt;Is using AI over engineering? Well, I would say for most companies or apps with a couple of thousand users it's not scalable to handcraft push notifications that are personalised, timely and also have the ability to change certain aspects based on user behavior. &lt;/p&gt;

&lt;p&gt;So let's see how we can do better with AI. For the purpose of this demo, let's pretend we're working for a food delivery app - you know the kind; restaurants, delivery drivers and food orderers in one eco-system. &lt;/p&gt;

&lt;p&gt;Okay, so  let's consider why and when we'd want to send push notifications. I see a few potentials: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Big events (sports, holidays, those international something days)&lt;/li&gt;
&lt;li&gt;New restaurants&lt;/li&gt;
&lt;li&gt;Targeting a user based on who they are (dietary requirements, are they traveling? Where do they normally order from? etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's more but let's keep it to these ones for now. &lt;/p&gt;

&lt;p&gt;First up, we're going to start with generic push notifications for restaurants. &lt;/p&gt;

&lt;p&gt;For this, I'm using a subset of Zomato restaurants, pulled from &lt;a href="https://www.kaggle.com/datasets/shrutimehta/zomato-restaurants-data?select=zomato.csv"&gt;here&lt;/a&gt; and cleaned for my needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Data set up
&lt;/h2&gt;

&lt;p&gt;We're going to ingest all the restaurant data, and their details into a vector database - this is what's going to allow us to plug in an LLM eventually, which will create descriptions, push notifications and eventually make decisions on changing pushes and when to send pushes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/aarushik93/65318d6bbb6b2642001cad77f80e59b0"&gt;You can find the full code here &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But let's focus on some specifics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Restaurant = {
        "classes": [
            {
                "class": "Restaurant",
                "description": "An MunchMate Restaurant.",
                "moduleConfig": {
                    "text2vec-openai": {
                        "skip": False,
                        "vectorizeClassName": False,
                        "vectorizePropertyName": False
                    }
                },
                "vectorIndexType": "hnsw",
                "vectorizer": "text2vec-openai",
                "properties": [
                    {
                        "name": "description",
                        "dataType": ["text"],
                        "description": "The general description written by an LLM.",
                        "moduleConfig": {
                            "text2vec-openai": {
                                "skip": False,
                                "vectorizePropertyName": False,
                                "vectorizeClassName": False
                            }
                        }
                    },
              // code omitted     
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at the Restaurant class, which contains all of the details of the restaurant (or any other entity you want to focus on for your usecase). In particular notice, we use text2vec-openai module to vectorize the description - here you can use any other model and module (plenty of new things coming out). &lt;/p&gt;

&lt;p&gt;The reason I'm only vectorizing description in this example is because that's the only thing I envision doing a semantic search on later down the line. &lt;/p&gt;

&lt;h2&gt;
  
  
  Descriptions
&lt;/h2&gt;

&lt;p&gt;Okay, so next up, we need to write a description for the restaurant. I don't want to do it manually TBH! &lt;/p&gt;

&lt;p&gt;So, let's use our LLM to actually generate a restaurant's description. Here, it depends on your usecase, in particular your CRM and/or marketing strategy on what you want to focus on about the restaurant. &lt;/p&gt;

&lt;p&gt;My prompt is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Create a description, for a restaurant with the following details:
    Restaurant Name: {restaurantName}
    Cuisines: {cuisines}
    Delivering now: {isDeliveringNow}
    Table Booking Offered: {hasTableBooking}
    City: {city}

    Stick to the information provided. Do not make up any information about the restaurant in your description.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, I end up with various descriptions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BJ's Country Buffet is an American and BBQ restaurant located in Albany, offering a range of delicious dishes. With both dine-in and delivery options, you can enjoy the restaurant's offerings from the comfort of your own home. You can also book a table in advance to make sure you have the perfect spot to enjoy their delicious cuisine.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason I'm setting up descriptions rather than just creating push notifications directly from the restaurants details is because I want this to become a base for all different types of marketing campaigns, CRM and anything that involves content to get users back into the app.&lt;/p&gt;

&lt;p&gt;Now on to the fun stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Push Notifications For Events
&lt;/h2&gt;

&lt;p&gt;Like we talked about initially, one of the usecases for custom pushes could be specific events. A push crafted for each individual restaurant. &lt;/p&gt;

&lt;p&gt;Again, &lt;a href="https://gist.github.com/aarushik93/65318d6bbb6b2642001cad77f80e59b0"&gt;you can check out the full code here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I'll walk you through some parts of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events = ["valentines day", "super bowl", "international women's day"]
    for e in events:
        generatePrompt = """
          Write a tempting, short push notification, with a short heading for the following new Restaurant:
          Description: {description}.
         Do not make up any information in the push notification
         Target the push towards: {event}

        Style:
        Heading:
        Content: 
        """


// code omitted

new_push_properties = {
                "content": push_content,
                "event": e
            }
            new_push_id = get_valid_uuid(uuid4())
            client.data_object.create(
                data_object=new_push_properties,
                class_name="Push",
                uuid=new_push_id
            )
            client.data_object.reference.add(
                from_uuid=restaurant["_additional"]["id"],
                from_property_name="hasPush",
                to_uuid=new_push_id
            )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this time we've changed our prompt to creating a push notification, based on the description. This is where you can also get a bit more creative: maybe you have a certain style or tone of voice that you want all pushes to sound like. This is where you can also pass examples of those in. &lt;/p&gt;

&lt;p&gt;In this example, I end up with pushes like this: &lt;/p&gt;

&lt;p&gt;Heading: Sweet Valentine's Day!&lt;br&gt;
Content: Satisfy your sweet tooth at Cookie Shoppe!&lt;/p&gt;

&lt;p&gt;This is pretty good so far, minimal manual effort - code it once and every time there's a new event, you can have a bunch of pushes for each restaurant. Or maybe every time you have a new restaurant added on a particular event day, an automatic push is generated and sent out - hopefully getting you users to that restaurant. &lt;/p&gt;

&lt;p&gt;Let's take it further and personalise to each individual user. Not just by name, but by information we already have about them. &lt;/p&gt;
&lt;h2&gt;
  
  
  Personalised Push Notifications
&lt;/h2&gt;

&lt;p&gt;Okay so for this step you're going to need information about your users to create a sort of biography about them. For simplicities sake, I've created bios for users in this example. But in reality you can get more creative and collect information about users based on their eating history, you can ask them to input preferences. For other applications, maybe you can think about social logins and asking to collect some information about them from there. &lt;/p&gt;

&lt;p&gt;Let me walk you through some of the specifics: &lt;/p&gt;

&lt;p&gt;First, I've gone ahead and created a User class. Which just contains a name and bio (remember in a real life case this data structure is likely to be more complex).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    user_schema = {
        "classes": [
            {
                "class": "User",
                "description": "A user.",
                "properties": [
                    {
                        "dataType": ["text"],
                        "name": "biography",
                    },
                    {
                        "dataType": ["text"],
                        "name": "name"
                    }
                ]
            }
        ]
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I've given two users bios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"biography": "Alex enjoys Mexican food, hates valentines day, loves the superbowl",
        "name": "Alex"


"biography": "Alice is a vegetarian, woman, loves Valentines day and the superbowl.",
        "name": "Alice"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note here, one of the good things about LLMs is that you don't need to be super strict on the structure of bio or what information to include - essentially whatever information you have - pop it in and let the LLM work it's creativity to give some personalized. Some personalization is better than none I say.&lt;/p&gt;

&lt;p&gt;The prompt I'm using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            generatePrompt = """
                 Write a short, targeted, clever, punchy push notification, with a short heading for the following new Restaurant:
                Description: {description}.
                The push notification should appeal to this user, based on their biography, likes and dislikes: {person}.
                Base the push notification on today's event: {event}.
                Use their name.
                Do not make up any information in the push notification. 
                Style:
                Heading:
                Content: 
            """
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, you can be as creative as you want with the prompt!&lt;/p&gt;

&lt;p&gt;And I end up with pushes like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Heading: Bye Bye V-Day!
Content: Alex, treat yourself to BBQ at BJ's! Enjoy dine-in or delivery.
Heading: Valentine's Day at Austin's!
Content: Alex, forget roses, get BBQ! Order now: Austin's BBQ &amp;amp; Oyster Bar
Heading: Skip the Date Night
Content: Alex, forget V-Day with taco night at El Vaquero!
Heading: Bye Bye Valentines!
Content: Alex, end the day with something sweet at Cookie Shoppe!


Heading: Veg Out Today!
Content: Alice, make Valentine's Day extra special with a delicious feast from Austin's BBQ and Oyster Bar!
Heading: Celebrate V-Day with Alice!
Content: Enjoy Mexican-style vegetarian dishes at El Vaquero Mexican Restaurant in Albany!
Heading: Valentine's Day at Cookie Shoppe!
Content: Alice, satisfy your sweet tooth with our delicious veg options!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I really like about these is it's taking into account differences in each person based on their bios. For example,  Alex doesn't like Valentines day, but Alice does. Or the fact that Alice is vegetarian, but we don't know Alex's dietary requirements so it doesn't focus on that aspect.&lt;/p&gt;

&lt;p&gt;Annnd there you have it - few hundred lines of code and now you can have you're own fully personalised push notification builder. &lt;/p&gt;

&lt;p&gt;Take it a step further and you can build out full blow marketing campaigns. &lt;/p&gt;

&lt;p&gt;In my personal work, I'm going to be taking it further and figuring out the tone of voice my users react best to. If it's of interest, let me know and I'll write about that too!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>gpt3</category>
      <category>programming</category>
    </item>
    <item>
      <title>Giving your Large Language Model skills: Stoicism Meets AI</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Fri, 28 Apr 2023 19:47:21 +0000</pubDate>
      <link>https://dev.to/aarushikansal/giving-your-large-language-model-skills-stoicism-meets-ai-5gd1</link>
      <guid>https://dev.to/aarushikansal/giving-your-large-language-model-skills-stoicism-meets-ai-5gd1</guid>
      <description>&lt;p&gt;By now, you've probably already seen the onslaught of large language models (LLMs), whether closed source (e.g Open AI), open source (e.g. LLamA, HuggingChat) or maybe you're hosting one yourself (💰💰) and the language skills they possess. &lt;/p&gt;

&lt;p&gt;In this post I want to talk about giving your LLMs "skills". When I talk about skills, I mean more abilities that a "human" might be able to do. In particular, I'm going to focus on the ability to focus on a very specific domain, reasoning and the ability to take an action and memory. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;br&gt;
Well, these "skills" are going to start becoming the basis of any LLM application you want to build. Purely prompting an LLM via an API or UI can only take you so far. A general LLM isn't trained or finetuned on your specific data, it doesn't have access to the most recent data/events/news and it doesn't have a memory by default. &lt;/p&gt;

&lt;p&gt;Okay so, the application I'm going to focus on is a chatbot for Stoicism for the modern age. While Stoicism is great, it's ancient and I want actionable, modern day advice BASED on Stocism. Like so: &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7056228587254755328/" rel="noopener noreferrer"&gt;https://www.linkedin.com/feed/update/urn:li:activity:7056228587254755328/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While models like GPT-4 already have knowledge on Stoicism, I want my model to narrow down on particular practitioners. I don't want it be basing it's Stoic advice on all of the internet/freely available data. So, enter: Weaviate DB, and two of my favourite books: Meditations by Marcus Aurelius and Letters from a Stoic written by Seneca. &lt;/p&gt;

&lt;p&gt;And the next thing I mentioned was "actionable, modern day"...so where would I as human being get any information really? Google. And that's exactly what I'm going to give my LLM the ability to do.&lt;/p&gt;

&lt;p&gt;Now, as a chatbot, it also needs to have memory, I need it to be able to remember what we were talking about? There are a few ways to that and in this case, we're going to use the simplest form, just via the prompt. &lt;/p&gt;

&lt;p&gt;And finally, and my favourite: the ability to reason. As a chatbot that gives modern day advice based on Stoicism, it needs to be able to not just answer a question but logically think about how to get to the answer. For example: the user wants Stoic advice in a modern context...so I should search the DB and then how do I make it modern? I should Google it, what do I need to Google?&lt;/p&gt;

&lt;p&gt;So, with all of that in mind, this is roughly what're going to build: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr0j8t80rm5d7bxsq5cn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr0j8t80rm5d7bxsq5cn.png" alt="diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're using two tools: Google search (via Serper API) and a Vector DB (Weaviate), which contains the two books mentioned earlier. &lt;/p&gt;

&lt;p&gt;On top of that we're using the concept of "Agent" which is a wrapper around a model you'll input the query in here, and get outputted an action to take. &lt;/p&gt;

&lt;p&gt;The AgentExecutor, written in Python is responsible for actually executing the action (i.e Google search or search DB). &lt;/p&gt;

&lt;p&gt;And with this kind of set up, here's an example of it's thoughts and actions: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskq81s7ns5tcwsxss1uj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskq81s7ns5tcwsxss1uj.png" alt="reasoning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I ask it how to get motivation for the gym, first it searches for motivation via Stoicism then understands and reasonss and then decides to Google for building habits aligning with your values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show me the code!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can find the full code here: &lt;a href="https://gist.github.com/aarushik93/2a9c9c050e78b34ff2a701bf5c6faf31" rel="noopener noreferrer"&gt;https://gist.github.com/aarushik93/2a9c9c050e78b34ff2a701bf5c6faf31&lt;/a&gt;. Below I'll walk you through the most relevant bits!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: We're not going through ingesting data into a VectorDB in this post. I will  show you in another post or you can check out the weaviate documentation: &lt;a href="https://weaviate.io/developers/weaviate" rel="noopener noreferrer"&gt;https://weaviate.io/developers/weaviate&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client = weaviate.Client(
    url=WEAVIATE_URL,
    additional_headers={
        'X-OpenAI-Api-Key': OPENAI_API_KEY
    }
)

vectorstore = Weaviate(client, "Paragraph", "content")
ret = vectorstore.as_retriever()

AI = OpenAI(temperature=0.2, openai_api_key=OPENAI_API_KEY)

# Set up the question-answering system
qa = RetrievalQA.from_chain_type(
    llm=AI,
    chain_type="stuff",
    retriever=ret,
)

search = GoogleSerperAPIWrapper(serper_api_key=SERPER_API_KEY)

# Set up the conversational agent
tools = [
    Tool(
        name="Stoic System",
        func=qa.run,
        description="Useful for getting information rooted in Stoicism. Ask questions based on themes, life issues and feelings ",
    ),
    Tool(
        name="Search",
        func=search.run,
        description="Useful for when you need to get current, up to date answers."
    )
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this block we're doing a few things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up the Weaviate and SerperAPI clients&lt;/li&gt;
&lt;li&gt;Setting up the RetrievalQA chain, which is going to allow us to query the DB using the question we/AgentExecutor provides it AND stop the LLM from hallucianting or making up answers. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The prompt template for that is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"""Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
{context}
Question: {question}
Helpful Answer:"""
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And finally, we're setting up the Tools for the AgentExecutor to actually use: Take note of the descriptions, these are what help the LLM determine which tool it tells the Agent it wants to use. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, next up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prefix = """You are a Stoic giving people advice using Stoicism, based on the context and memory available.
            Your answers should be directed at the human, say "you".
            Add specific examples, relevant in 2023, to illustrate the meaning of the answer.
            You can use these two tools:"""
suffix = """Begin!"
Chat History:
{chat_history}
Latest Question: {input}
{agent_scratchpad}"""

## agent 
prompt = ZeroShotAgent.create_prompt(
    tools,
    prefix=prefix,
    suffix=suffix,
    input_variables=["input", "chat_history", "agent_scratchpad"],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the actual prompt we're using to get the LLM to act like a Stoic. &lt;/p&gt;

&lt;p&gt;First, take note, we tell it has access to two tools...we didn't specify the tools yet but that's okay, this is a template and the Agent wrapper will actually craft the prompt, with the tools and all. &lt;/p&gt;

&lt;p&gt;Next, take notice we're also creating this prompt as a template for the chat history, with a latest question, that way the LLM has a so called memory. &lt;/p&gt;

&lt;p&gt;Keep in mind with this approach the memory is limited by the number of tokens we can actually send with the context. And that depends on the model you're using. &lt;/p&gt;

&lt;p&gt;Also take not of this so called "agent scratchpad": which is where the model can do it's "thinking".&lt;/p&gt;

&lt;p&gt;The next part to take note of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent_chain = AgentExecutor.from_agent_and_tools(
    agent=agent, tools=tools, verbose=True, memory=st.session_state.memory
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the actual executor, when the LLM outputs a decision, this is the thing that executes that decision. &lt;/p&gt;

&lt;p&gt;And there you have it. Your Stoic Bot.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>chatgpt</category>
      <category>programming</category>
    </item>
    <item>
      <title>Prompt Engineering</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sat, 22 Apr 2023 21:42:16 +0000</pubDate>
      <link>https://dev.to/aarushikansal/prompt-engineering-2d4j</link>
      <guid>https://dev.to/aarushikansal/prompt-engineering-2d4j</guid>
      <description>&lt;p&gt;I want to start off this series, with some general theory and then we'll go into building an actual application!&lt;/p&gt;

&lt;p&gt;By now you've probably already tried some form of zero shot or few shot prompting. If you haven't here's quick explanation: &lt;/p&gt;

&lt;p&gt;Both are ways of getting a large language model (LLM) to perform a task that it wasn't specifically trained for without finetuning. Some usecases could be: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentiment analysis on text the model's never seen before&lt;/li&gt;
&lt;li&gt;Writing in your, or your company's style or tone of voice&lt;/li&gt;
&lt;li&gt;Creating product names
The list goes on, but I think you get it. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero Shot:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simplest one is to just tell or ask the model to do what you want, with no examples whatsoever. This can work quite well, given the vast training data most of the really popular LLMs are trained on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Few Shot:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one just means giving the model a few examples of the task or final output you want. It's a way of guiding the model to your final outcome. &lt;/p&gt;

&lt;p&gt;Both of these are a great ways of getting simple, shorter tasks done. But once you have anything more complex, you need more of a "human" brain. And human brains allow us to think and reason. That's where chain of thought comes into the picture. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chain of Thought&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/abs/2201.11903"&gt;The full paper is here&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The TLDR; chain of thought is a way to prompt the LLM to reason its way through a problem by chaining rationales, one step at a time, until it reaches a solution. Again, there are two types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero shot:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;This involves getting the model to work through a problem using natural language, like "show your rationale, step by step" or ""Let's break this down into smaller steps and consider each one in turn. What is the first step we need to take, and what information do we need to gather in order to take that step? Once we have that information, what is the next logical step to take? Let's continue this process until we have a clear understanding of the issue at hand and a plan for how to proceed."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Few shot:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With shot you give some examples of rationale chains, so it knows how to work through a problem. For example, by providing a few examples on how to do BODMAS, before asking it to solve a maths problem.&lt;/p&gt;

&lt;p&gt;So, there you have it, a very quick theory session on prompt engineering. In the next post, we'll start putting this (in particular chain of thought) into action by building a content engine. All powered by AI. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>gpt3</category>
    </item>
    <item>
      <title>Dwight AI</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sat, 22 Apr 2023 00:22:36 +0000</pubDate>
      <link>https://dev.to/aarushikansal/dwight-ai-12kl</link>
      <guid>https://dev.to/aarushikansal/dwight-ai-12kl</guid>
      <description>&lt;p&gt;Introducing my new lil project: Dwight Schrute the Reporter...an AI driven Dwight Schrute that post about the news 🤖&lt;/p&gt;

&lt;p&gt;I've been working on lots of different AI things atm and in this project I'm bringing some of the most most interesting things together all with various ML models for different tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hyper relevant to a user&lt;/li&gt;
&lt;li&gt;Logic and reasoning&lt;/li&gt;
&lt;li&gt;Memory&lt;/li&gt;
&lt;li&gt;NLP for technical things like working with an API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the aim being a full blown human like news writer. Follow along here as Dwight posts and gets smarter: &lt;a href="https://dwightdoesthenews.com/"&gt;https://dwightdoesthenews.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>Secrets With SOPS</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sat, 13 Nov 2021 11:58:54 +0000</pubDate>
      <link>https://dev.to/aarushikansal/secrets-with-sops-2h5e</link>
      <guid>https://dev.to/aarushikansal/secrets-with-sops-2h5e</guid>
      <description>&lt;p&gt;SOPS (Secrets OperationS) is an open source tool from Mozilla, intended to edit, encrypt, decrypt a range of different file types, such as YAML, JSON, ENV etc. &lt;/p&gt;

&lt;p&gt;Encryption can be done in variety of ways, using major cloud providers encryption tools, PGP, and even age.&lt;/p&gt;

&lt;p&gt;In this article, we'll focus on using AWS + KMS. A similar setup and workflow can be used for GCP and Azure as well. &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing
&lt;/h3&gt;

&lt;p&gt;Download + install one of: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/mozilla/sops/releases"&gt;stable releases&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="//go.mozilla.org/sops/v3/cmd/sops"&gt;unstable features&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details can be found on the SOPS github repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring
&lt;/h3&gt;

&lt;p&gt;Pre-requistes for this are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A ready to use KMS key.&lt;/li&gt;
&lt;li&gt;Correctly configured AWS credentials, for example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
aws_access_key_id = &amp;lt;access-key-id&amp;gt;
aws_secret_access_key = &amp;lt;access-key&amp;gt;

[kmsuser]
aws_access_key_id = &amp;lt;kmsuser-access-key-id&amp;gt;
aws_secret_access_key = &amp;lt;kmsuer-access-key&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A separate kmsuser is not a requirement, but SOPS supports switching profiles, which will be discussed later on. &lt;/p&gt;

&lt;p&gt;Next, you'll need to set up your sops configuration, which means telling sops which key to use, possibly what profile and what role to use. &lt;/p&gt;

&lt;p&gt;Set up a .sops.yaml, locally. &lt;/p&gt;

&lt;p&gt;Some configurations are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sops:
    kms:
    - arn: arn:aws:kms:ap-southeast-2:036762315531:key/46b7ee9d-d11a-4a7e-83a5-c83fe5c93e8f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the most basic configuration. It specifies KMS and the specific resource to use for encryption and decryption. &lt;br&gt;
There is no profile or role listed, so it uses your default credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sops:
    kms:
    - arn: arn:aws:kms:ap-southeast-2:036762315531:key/00aa1727-d895-4dc9-a10c-96ad40470a91
      aws_profile: kmsuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some situations you'll want to define alternative credentials, so you can specify which profile to use, from your credentials file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sops:
    kms:
    -   arn: arn:aws:kms:ap-southeast-2:036762315531:key/00aa1727-d895-4dc9-a10c-96ad40470a91
        role: arn:aws:iam::913492025681:role/sopsuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SOPS also allows you to make use of AWS' roles feature, meaning you can use KMS from multiple accounts. &lt;/p&gt;

&lt;h3&gt;
  
  
  Using
&lt;/h3&gt;

&lt;p&gt;Encryption:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sops -e secrets.yaml &amp;gt; secrets.enc.yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Decryption:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sops -d secrets.enc.yaml &amp;gt; secrets.yaml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Plaintext secrets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Secret
metadata:
    name: t0p-S3cret
type: Opaque
data:
    password: 12345-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Encrypted secrets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: ENC[AES256_GCM,data:690=,iv:GM5Rle5baQNBC4MBECfVEY9YZzAeywnHcrcclGnwAVw=,tag:xN311xVOyvqC+TXy16KNcQ==,type:str]
kind: ENC[AES256_GCM,data:PGiPB4h3,iv:t9kAkvT9u38dwqOtBAPXEcLGqBa07/Ggk4gEhO/SzSQ=,tag:4NN94br3Ut9EmB/zMjkWMw==,type:str]
metadata:
  name: ENC[AES256_GCM,data:AZP+jxs5kVJQyh5ZcxROzIuuZgTsEQ==,iv:wA2OVYCQ8icb10XIRxTZu+QMILUoORrIOJmh30rmX84=,tag:VGBR8shJQ8x7RQY0R5fMqQ==,type:str]
type: ENC[AES256_GCM,data:fqP1lGtK,iv:bzhdcaZ1WyJpgy4v3Q2MS0J6q3XNLRtC2qbdWHkoqtk=,tag:dGbR3gWt54lnRRIYtq7i9w==,type:str]
data:
  password: ENC[AES256_GCM,data:ihVGHIa/SqDxC64wzFRvtFcKtk3WPmpjIWUh3HxCo60=,iv:gcxL6u2JNh+T7lXb5VbfZS9aKun8ZOAK+X93uJ4Vd6M=,tag:/y5UTFa3mIiAaV6RPif9mQ==,type:str]
sops:
  kms:
    - arn: arn:aws:kms:ap-southeast-2:036762315531:key/46b7ee9d-d11a-4a7e-83a5-c83fe5c93e8f
      created_at: "2021-11-12T06:28:22Z"
      enc: AQICAHguJRDZ0cg53Sh5Mus9w8WLD236AYz81m6wFTHAa6ObgQFSNXL+AHX+kn+akWNtP7aQAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMKaUlIgOrUMmOA/LzAgEQgDs62h0/zahsnr+4z1trkI+Euk5WkWqkQBnBh3KijqPEJJnKnPE9v41vSGJLbfeI8QOruvR6YwU2V3G7LQ==
      aws_profile: kmsuser
  gcp_kms: []
  azure_kv: []
  hc_vault: []
  age: []
  lastmodified: "2021-11-12T06:28:23Z"
  mac: ENC[AES256_GCM,data:Lwo28isqP6hA2nxjXDTnkglZjj8Ip1+W+erYlV/dq7r7YoJWAE+vFbWdiKIm4wE7bhSsoNQiIFGbQVqRx7VoGjwAE8A//0BCfrd7i5dTS5+/c0BOiLLrpNSqdTxRiNTUMGcvvWWnmkf+uBmMN/pOhyXwhdB+z9h0ST6Y3rR+zHE=,iv:l01KhN0a6BeoIIn45lbUamNKBNWX2eTMo7ToA2OsF/I=,tag:jfuPs6lS913B7Yb0jMjefA==,type:str]
  pgp: []
  unencrypted_suffix: _unencrypted
  version: 3.7.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see here, we have a regular secrets manifest, which is encrypted and can then be checked in or shared freely.&lt;/p&gt;

&lt;p&gt;SOPS encrypts all the values, not just secrets, specifies metadata such as profile and kms key used. &lt;/p&gt;

&lt;h3&gt;
  
  
  CI
&lt;/h3&gt;

&lt;p&gt;There are a number of ways to use sops encrypted secrets in your CI workflow. &lt;/p&gt;

&lt;p&gt;The most basic way is to install sops, decrypt and apply the decrypted file to your cluster.&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sops -d secrets.enc.yaml | kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it's most like you're using some kind of manifest management tool and will want secrets to work within that ecosystem. To achieve this there are some wrappers for sops: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jkroepke/helm-secrets"&gt;helm-secrets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/viaduct-ai/kustomize-sops"&gt;ksops&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;SOPS is a great tool to get started with a GitOps style of secret management. However, there are some consideration you should take into account before committing to this solution: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key rotation&lt;/li&gt;
&lt;li&gt;Lack of control over who can see secrets once in the cluster&lt;/li&gt;
&lt;li&gt;Scalability for large teams, or a large number of secrets &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why is IBM cloud not widely used?</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Fri, 03 Jul 2020 18:55:23 +0000</pubDate>
      <link>https://dev.to/aarushikansal/why-is-ibm-cloud-not-widely-used-4c9j</link>
      <guid>https://dev.to/aarushikansal/why-is-ibm-cloud-not-widely-used-4c9j</guid>
      <description>&lt;p&gt;I started using IBM mainly because I needed more computing power for my machine learning projects, and I actually found IBM less complicated, cheaper (for my projects not sure about other usecases) and the overall user experience was much nicer than other cloud providers....and yet I don't know anyone in my network that uses IBM for their work or side projects?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>watercooler</category>
      <category>cloud</category>
      <category>ibm</category>
    </item>
    <item>
      <title>How to create your own invisibility cloak</title>
      <dc:creator>Aarushi Kansal</dc:creator>
      <pubDate>Sun, 27 Oct 2019 12:00:46 +0000</pubDate>
      <link>https://dev.to/aarushikansal/how-to-create-your-own-invisibility-cloak-4ndg</link>
      <guid>https://dev.to/aarushikansal/how-to-create-your-own-invisibility-cloak-4ndg</guid>
      <description>&lt;p&gt;I wanted to start learning about computer vision and I grew up on Harry Potter, so as my first experiment, I tried to make Harry's coveted invisibility cloak. &lt;/p&gt;

&lt;p&gt;This is an introduction into colour detection, colour spaces, and opencv. &lt;/p&gt;

&lt;p&gt;For this demo, I am using GoCV, as I also want to further experiment with Go + computer vision. &lt;/p&gt;

&lt;p&gt;For anyone not familiar, this is what an invisibility cloak is&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F73dkn0qfhql18x53goi3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F73dkn0qfhql18x53goi3.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It makes the wearer invisible! &lt;/p&gt;

&lt;h1&gt;
  
  
  Theory
&lt;/h1&gt;

&lt;h3&gt;
  
  
   Color spaces
&lt;/h3&gt;

&lt;p&gt;The first aspect we need to understand is colour spaces. Most people will be familiar with the RGB colour space. If you're not &lt;a href="https://www.baslerweb.com/en/sales-support/knowledge-base/frequently-asked-questions/what-is-the-rgb-color-space/15179/" rel="noopener noreferrer"&gt;here's an article&lt;/a&gt; explaining RGB. &lt;/p&gt;

&lt;p&gt;The problem with this colour space is that, it attempts to describe the level of red, green and blue, all in one value. This works for display purposes, but not for detecting colour in video.&lt;/p&gt;

&lt;p&gt;Colour in the natural world is very much dependant on lighting, and any object has a range of shades, even for the same colour. &lt;/p&gt;

&lt;p&gt;This is where the HSV color space comes into play. HSV describes color with one channel, hue (H), which means that color is very much only dependant on the hue, and different shades, and lighting are taken into account by saturation (S) and value (V). &lt;br&gt;
So in our example, a cloth might all green, but because of the folds, the lighting in the room etc, different parts of the cloth will have slightly different colors. Using HSV, all we would need to do is adjust the V, to take into account light changes, and our algorithm is still able to recognise different greens still being green.&lt;/p&gt;

&lt;h3&gt;
  
  
  Masks and morphing in CV
&lt;/h3&gt;

&lt;p&gt;A mask is essentially just another image, that you can apply on top of another image of the same size. &lt;/p&gt;

&lt;p&gt;Morhping is the term we use to describe applying certain transformations to an image. OpenCV offers a few different transformations, all of which are based on a 'Kernal'.&lt;/p&gt;

&lt;p&gt;In the world of image processing, a kernal is a matrix, which is used to actually apply the different effects we want, such as blurring or dilation. &lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html" rel="noopener noreferrer"&gt;transformations here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Show me the code
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/aarushik93/invisibility-cloak" rel="noopener noreferrer"&gt;Code here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look more closely at the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fodebh5l9tlenxmuuge5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fodebh5l9tlenxmuuge5v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this block, we are doing all the set up, creating the video capture object (0 refers to webcam), creating the window, setting up the various mask objects we will use, and setting up the HSV values for a green cloak. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnxfng3clzl0y24tqelqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnxfng3clzl0y24tqelqw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we grab the static background, with a sleep, which gives the webcam time to start up and video to load (if we capture the background as soon as the webcam starts, we end up with some odd lighting in the background). &lt;/p&gt;

&lt;p&gt;We then start continuously reading frames from the webcam, and doing some transformations.&lt;/p&gt;

&lt;p&gt;First, we convert our frame to the HSV colour space. &lt;br&gt;
Then we filter that HSV image for the pixels that are within our HSV green space, and create a mask. This allows us to create a mask specifically for our green cloak. &lt;/p&gt;

&lt;p&gt;Once we've identified our cloak, the magic can begin. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsws8gqvfqp25zrhzjs6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsws8gqvfqp25zrhzjs6x.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see we create our kernal, we then do a dilation. Up to this step we have a black dilated mask on our cloak. &lt;/p&gt;

&lt;p&gt;A dilation is a type of morphological transformation that increases the object's area. I'm using this to ensure all the coloured areas is covered by our mask, while still keeping the shape of our cloak.&lt;/p&gt;

&lt;p&gt;Since we want it to be invisible, we then invert the mask. &lt;/p&gt;

&lt;p&gt;Now, we have an 'invisible' mask, in the shape of our cloak. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjas0bkw65ooy4ryxv8wq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjas0bkw65ooy4ryxv8wq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final step is to combine the masks, with the frame, and the background and display the finished product on screen.&lt;/p&gt;

&lt;p&gt;And now you have your very own invisibility cloak!&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;I suggest editing the HSV values to suit your needs, play with lighting, and colours to get the best effect for you. In my case, the lighting in my apartment was quite nice to work with, dimmer in different areas, so I was able to play around with values and locations to come up with a an example such as this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3spyeuhq91lzuc9mk8sd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3spyeuhq91lzuc9mk8sd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/aarushikansal/status/1186759679482957824?s=20" rel="noopener noreferrer"&gt;Video here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>computervision</category>
      <category>imageprocessing</category>
    </item>
  </channel>
</rss>
