<?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>Forem: Izawa</title>
    <description>The latest articles on Forem by Izawa (@izawa).</description>
    <link>https://forem.com/izawa</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%2F1101096%2Ff40b7274-55ea-4120-abd8-ac6eb5985d1b.png</url>
      <title>Forem: Izawa</title>
      <link>https://forem.com/izawa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/izawa"/>
    <language>en</language>
    <item>
      <title>Auto-Backup Your Git Repo on Every Commit</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Tue, 24 Feb 2026 18:15:14 +0000</pubDate>
      <link>https://forem.com/izawa/auto-backup-your-git-repo-on-every-commit-3iab</link>
      <guid>https://forem.com/izawa/auto-backup-your-git-repo-on-every-commit-3iab</guid>
      <description>&lt;p&gt;AI coding tools are great, but there's a non-zero chance one of them nukes your &lt;code&gt;.git&lt;/code&gt; folder someday. Scheduled backups work, but I wanted something that just happens automatically — so I set up a bare repository on a separate drive that syncs on every commit via a post-commit hook. Here's how. (macOS, but Linux is identical.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Create the bare repository
&lt;/h2&gt;

&lt;p&gt;Pick somewhere outside your project — an external drive works well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /path/to/backup/project.git
&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/backup/project.git
git init &lt;span class="nt"&gt;--bare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A bare repo stores only history, no working files. Same format GitHub uses internally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Register it as a remote
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/path/to/project

git remote add backup /path/to/backup/project.git

&lt;span class="c"&gt;# Initial push (check your branch name first)&lt;/span&gt;
git branch &lt;span class="nt"&gt;--show-current&lt;/span&gt;
git push backup &amp;lt;branch-name&amp;gt;

&lt;span class="c"&gt;# Verify&lt;/span&gt;
git ls-remote backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Add the post-commit hook
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .git/hooks/post-commit
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x .git/hooks/post-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.git/hooks/post-commit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;current_branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;
git push backup &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;amp;&lt;/code&gt; runs it in the background so commits don't feel any slower.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verifying it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;backup_test.txt
git add backup_test.txt
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test: post-commit hook"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then compare hashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
git ls-remote backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;main&lt;/code&gt; points to the same hash in both, you're good. Clean up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm &lt;/span&gt;backup_test.txt
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: remove test file"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Recovery
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If only &lt;code&gt;.git&lt;/code&gt; was deleted (files intact):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/project
git init
git remote add backup /path/to/backup/project.git
git fetch backup
git branch &lt;span class="nt"&gt;-r&lt;/span&gt;  &lt;span class="c"&gt;# confirm branch name&lt;/span&gt;
git reset &lt;span class="nt"&gt;--mixed&lt;/span&gt; backup/&amp;lt;branch-name&amp;gt;
git status     &lt;span class="c"&gt;# commit any remaining diff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If the whole folder is gone:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone /path/to/backup/project.git my_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both cases, re-add the post-commit hook afterward since &lt;code&gt;.git/hooks/&lt;/code&gt; isn't tracked by Git.&lt;/p&gt;




&lt;p&gt;That's it. A bit of setup, but once it's running you don't think about it again.&lt;/p&gt;

</description>
      <category>git</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Getting Started with LangChain</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Tue, 27 Feb 2024 09:59:52 +0000</pubDate>
      <link>https://forem.com/izawa/getting-started-with-langchain-2m10</link>
      <guid>https://forem.com/izawa/getting-started-with-langchain-2m10</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;An introduction to how to use Langchain.&lt;br&gt;
Basic writing with LCEL will be introduced.&lt;br&gt;
The model used was gpt-3.5-turbo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reference Documents
&lt;/h2&gt;

&lt;p&gt;Official Documents&lt;br&gt;
&lt;a href="https://python.langchain.com/docs/get_started/quickstart" rel="noopener noreferrer"&gt;https://python.langchain.com/docs/get_started/quickstart&lt;/a&gt;&lt;br&gt;
LCEL&lt;br&gt;
&lt;a href="https://python.langchain.com/docs/expression_language/" rel="noopener noreferrer"&gt;https://python.langchain.com/docs/expression_language/&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -V
Python 3.11.6

pip install python-dotenv

pip install langchain
pip show langchain
Version: 0.1.9

pip install langchain-openai
pip show langchain-openai
Version: 0.0.7

pip install langchain-core
pip show langchain-core
Version: 0.1.27
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create File&lt;/strong&gt;&lt;br&gt;
Create a directory (e.g. test_langchain)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/test_langchain/.env&lt;/li&gt;
&lt;li&gt;/test_langchain/test.py&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ENV file&lt;/strong&gt;&lt;br&gt;
Set your OpenAI API Key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPENAI_API_KEY="***********"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;test.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

load_dotenv()
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY, model="gpt-3.5-turbo", temperature=0)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a culinary expert"),
        ("user", "{input}"),
    ]
)

output_parser = StrOutputParser()

# LCEL
chain1 = prompt
chain2 = prompt | llm
chain3 = prompt | llm | output_parser

response1 = chain1.invoke({"input": "Speaking of good Japanese food, name one."})
print(response1)
print("------------")
response2 = chain2.invoke({"input": "Speaking of good Japanese food, name one."})
print(response2)
print("------------")
response3 = chain3.invoke({"input": "Speaking of good Japanese food, name one."})
print(response3)
print("------------")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Execute from a terminal.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;python test.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output Result&lt;/strong&gt;&lt;br&gt;
Results are displayed for each pattern.&lt;br&gt;
If StrOutputParser() is used, the value of response is the response statement only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;messages=[SystemMessage(content='You are a culinary expert'), HumanMessage(content='Speaking of good Japanese food, name one.')]
------------
content='One popular Japanese dish is sushi. Sushi is a dish that typically consists of vinegared rice topped with various ingredients such as raw fish, seafood, vegetables, and sometimes tropical fruits. It is often served with soy sauce, wasabi, and pickled ginger. Sushi can be enjoyed in many different forms, such as nigiri (sliced fish on top of rice), sashimi (sliced raw fish without rice), maki (rolled sushi), and temaki (hand-rolled sushi).'
------------
One popular Japanese dish is sushi. It typically consists of vinegared rice topped with various ingredients such as raw fish, seafood, vegetables, and sometimes tropical fruits. Sushi is not only delicious but also visually appealing, making it a favorite choice for many people around the world.
------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This time I used ChatGPT and tried a simple description using LCEL.&lt;/p&gt;

&lt;p&gt;Langchain is updated frequently, so it is recommended that you check it regularly.&lt;/p&gt;

</description>
      <category>python</category>
      <category>langchain</category>
      <category>openai</category>
    </item>
    <item>
      <title>How to Use Microsoft AutoGen</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Wed, 18 Oct 2023 18:46:14 +0000</pubDate>
      <link>https://forem.com/izawa/how-to-use-autogen-1cpk</link>
      <guid>https://forem.com/izawa/how-to-use-autogen-1cpk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I tried AutoGen, an open source software published by Micorsoft.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;https://github.com/microsoft/autogen&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Documents
&lt;/h2&gt;

&lt;p&gt;Official Documents&lt;br&gt;
&lt;a href="https://microsoft.github.io/autogen/docs/getting-started" rel="noopener noreferrer"&gt;https://microsoft.github.io/autogen/docs/getting-started&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FAQ&lt;br&gt;
&lt;a href="https://microsoft.github.io/autogen/docs/FAQ/" rel="noopener noreferrer"&gt;https://microsoft.github.io/autogen/docs/FAQ/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multi-agent Conversation Framework&lt;br&gt;
&lt;a href="https://microsoft.github.io/autogen/docs/Use-Cases/agent_chat/" rel="noopener noreferrer"&gt;https://microsoft.github.io/autogen/docs/Use-Cases/agent_chat/&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;This time, considering the cost, I experimented with only gpt-3.5-turbo, with multiple agents just chatting. We also set max_round=4 for the number of conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;install&lt;/strong&gt;&lt;br&gt;
Python version &amp;gt;= 3.8&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pyautogen
Name: pyautogen
Version: 0.2.15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create File&lt;/strong&gt;&lt;br&gt;
Create a directory (e.g. test_autogen)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/test_autogen/OAI_CONFIG_LIST&lt;/li&gt;
&lt;li&gt;/test_autogen/app/test.py&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OAI_CONFIG_LIST&lt;/strong&gt;&lt;br&gt;
Do not add extensions to file names.&lt;br&gt;
Describe OpenAI's API KEY information.&lt;br&gt;
For an overview of LLM configurations and other implementation methods, please see below.&lt;br&gt;
&lt;a href="https://microsoft.github.io/autogen/docs/llm_configuration/" rel="noopener noreferrer"&gt;https://microsoft.github.io/autogen/docs/llm_configuration/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "model": "gpt-3.5-turbo-1106",
    "api_key": ""**********""
  },
  {
    "model": "gpt-3.5-turbo-0125",
    "api_key": "**********"
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;test.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import autogen

# OAI_CONFIG_LIST
config_list_gpt = autogen.config_list_from_json(
   "OAI_CONFIG_LIST",
   file_location="..",
   # optional
   # filter_dict={
   #     "model": {
   #         "gpt-3.5-turbo-0125",
   #     }
   # },
)

llm_config = {
   "config_list": config_list_gpt,
   "seed": 10,
   "temperature": 0.7,
}

# This time, we experimented without using user_proxy.
# user_proxy = autogen.UserProxyAgent(
#     name="User_proxy",
#     system_message="A human admin.",
#     code_execution_config={"last_n_messages": 2, "work_dir": "groupchat"},
#     human_input_mode="TERMINATE",
# )
agent_a = autogen.AssistantAgent(
    name="Agent-A",
    system_message="You love French food.",
    llm_config=llm_config,
)
agent_b = autogen.AssistantAgent(
    name="Agent-B",
    system_message="You love Japanese food!",
    llm_config=llm_config,
)
agent_c = autogen.AssistantAgent(
    name="Agent-C",
    system_message="You love Chinese food!",
    llm_config=llm_config,
)

groupchat = autogen.GroupChat(
    agents=[agent_a, agent_b, agent_c], messages=[], max_round=4
)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)

manager.initiate_chat(manager, message="Chatting about food.")

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Execute from a terminal.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;python test.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output Result&lt;/strong&gt;&lt;br&gt;
Conversations were generated up to the specified number of times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python test.py
chat_manager (to chat_manager):

Chatting about food.

--------------------------------------------------------------------------------
Agent-A (to chat_manager):

Yes, I absolutely love French food! The rich flavors, delicate techniques, and exquisite presentation of French cuisine never fail to impress me. From classic dishes like coq au vin and boeuf bourguignon to the indulgent pastries like croissants and macarons, French food is a true delight for the senses. The use of fresh, high-quality ingredients and the emphasis on balance and harmony in flavors make every bite a memorable experience. Whether it's a simple bistro meal or a fancy Michelin-starred restaurant, French food always brings me joy.

--------------------------------------------------------------------------------
Agent-B (to chat_manager):

That sounds absolutely delicious! French cuisine is renowned for its elegance and sophistication. The way they elevate simple ingredients into masterpieces is truly remarkable. The buttery croissants, rich sauces, and perfectly cooked meats are just a few examples of the culinary excellence that French cuisine offers. It's no wonder that French food is considered one of the finest in the world. Do you have a favorite French dish?

--------------------------------------------------------------------------------
Agent-C (to chat_manager):

It's hard to choose just one favorite French dish, but if I had to pick, it would probably be coq au vin. The tender chicken braised in red wine with onions, mushrooms, and herbs is simply divine. The flavors are rich and complex, and the dish is incredibly comforting. It's a classic French dish that never fails to impress. How about you? Do you have a favorite French dish?

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;GroupChat was easy to implement with sample code.&lt;/p&gt;

&lt;p&gt;This time it was just a conversation between AIs with no particular meaning, but there are several examples of using GPT-4, such as automatic task resolution for code generation, so it seems that something interesting can be created.&lt;/p&gt;

</description>
      <category>autogen</category>
      <category>chatgpt</category>
      <category>openai</category>
    </item>
    <item>
      <title>Implement ThirdWeb Smart Wallet and Embedded Wallet in Next.js</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Thu, 05 Oct 2023 12:44:23 +0000</pubDate>
      <link>https://forem.com/izawa/implement-thirdweb-smart-wallet-and-embedded-wallet-in-nextjs-3eil</link>
      <guid>https://forem.com/izawa/implement-thirdweb-smart-wallet-and-embedded-wallet-in-nextjs-3eil</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;ThirdWeb's Wallet feature is extensive and convenient. In this case, I tried the Smart Wallet and Embedded Wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Experience with Next.js development&lt;/li&gt;
&lt;li&gt;Experience with Thirdweb dashboard&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Preparation (from Thirdweb dashboard)
&lt;/h2&gt;

&lt;p&gt;Thirdweb&lt;br&gt;
&lt;a href="https://thirdweb.com/" rel="noopener noreferrer"&gt;https://thirdweb.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step (chain uses Mumbai)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create API Keys from Settings&lt;/li&gt;
&lt;li&gt;Create a Smart wallet Account Factory from Explore in Contracts&lt;/li&gt;
&lt;li&gt;Setup Wallet and generate code from Connect in Wallets&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;1. Create API Keys from Settings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fo27ou6naqfshevrjicgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fo27ou6naqfshevrjicgc.png" alt=" " width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create a Smart wallet Account Factory from Explore in Contracts&lt;/strong&gt;&lt;br&gt;
Selecting and creating an Account Factory&lt;br&gt;
&lt;a href="https://media2.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%2F3sh99epn1k7deolp8pkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3sh99epn1k7deolp8pkz.png" alt=" " width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check what has been created.&lt;br&gt;
This contract address is required as factoryAddress when implementing the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fybhyte7wegubzcg03abe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fybhyte7wegubzcg03abe.png" alt=" " width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Flgcfj8368320n08f9aov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flgcfj8368320n08f9aov.png" alt=" " width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Setup Wallet and generate code from Connect in Wallets&lt;/strong&gt;&lt;br&gt;
In this case, I chose MetaMask, Embedded Wallets and Smart Wallet.&lt;br&gt;
(To use Smart Wallet, select at least one Wallet)&lt;br&gt;
The code generated here will be used as a reference for implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fc58lqjxqb7pamm5icdbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fc58lqjxqb7pamm5icdbm.png" alt=" " width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fc37u0lqps33smfbk8dk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fc37u0lqps33smfbk8dk6.png" alt=" " width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generated 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 {
  ThirdwebProvider,
  ConnectWallet,
  metamaskWallet,
  embeddedWallet,
} from "@thirdweb-dev/react";

const smartWalletOptions = {
  factoryAddress: "YOUR_FACTORY_ADDRESS",
  gasless: true,
};

export default function App() {
  return (
    &amp;lt;ThirdwebProvider
      activeChain="mumbai"
      clientId="YOUR_CLIENT_ID"
      supportedWallets={[
        smartWallet(
          metamaskWallet({ recommended: true }),
          smartWalletOptions,
        ),
        smartWallet(
          embeddedWallet(),
          smartWalletOptions,
        ),
      ]}
    &amp;gt;
      &amp;lt;ConnectWallet
        theme={"dark"}
        modalSize={"compact"}
      /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;Use the generated code as an implementation reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a project with Next.js + Typescript&lt;/li&gt;
&lt;li&gt;Install SDK
&lt;code&gt;yarn add @thirdweb-dev/react @thirdweb-dev/sdk ethers@^5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write the API Key and Account Factory address you created in env.local&lt;/li&gt;
&lt;li&gt;Edit _app.tsx&lt;/li&gt;
&lt;li&gt;Edit index.tx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Thirdweb Version&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;"@thirdweb-dev/react": "^3.16.2"&lt;/code&gt;&lt;br&gt;
&lt;code&gt;"@thirdweb-dev/sdk": "^3.10.64"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_app.tsx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "@/styles/globals.css";
import type { AppProps } from "next/app";
import {
  ThirdwebProvider,
  smartWallet,
  metamaskWallet,
  embeddedWallet,
} from "@thirdweb-dev/react";

const activeChain = "mumbai";
const smartWalletOptions = {
  factoryAddress: process.env.NEXT_PUBLIC_FACTORY_ADDRESS || "",
  gasless: true,
};

function MyApp({ Component, pageProps }: AppProps) {
  return (
    &amp;lt;ThirdwebProvider
      activeChain={activeChain}
      clientId={process.env.NEXT_PUBLIC_TW_CLIENT_ID}
      supportedWallets={[
        smartWallet(metamaskWallet({ recommended: true }), smartWalletOptions),
        smartWallet(embeddedWallet(), smartWalletOptions),
      ]}
    &amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/ThirdwebProvider&amp;gt;
  );
}

export default MyApp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;index.tsx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ConnectWallet } from "@thirdweb-dev/react";
import type { NextPage } from "next";

const Home: NextPage = () =&amp;gt; {
  return (
    &amp;lt;main className="flex flex-col items-center justify-center p-10"&amp;gt;
      &amp;lt;div className=""&amp;gt;
        &amp;lt;ConnectWallet
          theme={"dark"}
          modalSize={"compact"}
          btnTitle={"Connect Wallet"}
          modalTitleIconUrl={""}
        /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  );
};

export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Operation check
&lt;/h2&gt;

&lt;p&gt;Start with &lt;code&gt;yarn dev&lt;/code&gt;&lt;br&gt;
Confirm the activated URL (e.g., localhost:3000) with a PC browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fa1fbu68p985jvesyipgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fa1fbu68p985jvesyipgx.png" alt=" " width="490" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try to authenticate with your Gmail login.&lt;br&gt;
If you enter your email address, an authentication code will be sent to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2kble6t4m8z0f9ew323s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2kble6t4m8z0f9ew323s.png" alt=" " width="504" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Address generated.&lt;br&gt;
The smart wallet address will appear first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F11ibmx5d177aufhuqzzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F11ibmx5d177aufhuqzzj.png" alt=" " width="492" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, two addresses are generated: Smart Wallet and Personal Wallet (Embedded Wallet).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Wallet address&lt;/strong&gt;&lt;br&gt;
This time, the smart wallet address is gasless.&lt;br&gt;
When you click on Connectted to Smart Wallet, you will see your Account details on the Thirdweb page. You can also check the NFTs you hold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff972jzehsvbrn6fmtzw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff972jzehsvbrn6fmtzw0.png" alt=" " width="496" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personal Wallet (Embedded Wallet) Address&lt;/strong&gt;&lt;br&gt;
Wallet Users can be found on the Thirdweb dashboard under Embedded Wallets in the Wallets section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fhc5g2swf9rstpiv56pkb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhc5g2swf9rstpiv56pkb.png" alt=" " width="462" height="562"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I experimented with everything from setup to implementation and got the impression that it was very easy.&lt;br&gt;
Thirdweb has an easy to use dashboard and is evolving more and more!&lt;/p&gt;

&lt;p&gt;I did not put it here, but I tested a MATIC full amount transfer with a Smart Wallet address, and it worked without insufficient funds; with a Personal Wallet (Embedded Wallet) address, I got an insufficient funds error.&lt;/p&gt;

&lt;p&gt;I also attempted a Claim at NFT (free price) on EditionDrop with a smart wallet address with zero balance, but it was successfully processed as gasless.&lt;br&gt;
(I did not, however, see where they were processing the gasless.)&lt;/p&gt;

&lt;p&gt;They also accept credit card payments, so I will try that next time I have the opportunity.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>thirdweb</category>
      <category>web3</category>
    </item>
    <item>
      <title>Implement Vercel AI SDK and LangChain JS with Next.js</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Sun, 01 Oct 2023 10:39:31 +0000</pubDate>
      <link>https://forem.com/izawa/implement-vercel-ai-sdk-and-langchain-js-with-nextjs-6m</link>
      <guid>https://forem.com/izawa/implement-vercel-ai-sdk-and-langchain-js-with-nextjs-6m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Try to implement a chat page using ChatGPT's API.&lt;br&gt;
I will use Vercel AI SDK, but I also tried LangChain with it.&lt;/p&gt;


&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Experience with Next.js development&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Advance preparation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create an API key from OpenAI platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://platform.openai.com/" rel="noopener noreferrer"&gt;https://platform.openai.com/&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;Steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Next.js + Typescript&lt;/li&gt;
&lt;li&gt;Write OPENAI_API_KEY in env.local&lt;/li&gt;
&lt;li&gt;Create /api/aiSdkChat.ts and /api/langChainChat.ts and edit index.tsx&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Create a Next.js + Typescript
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create next-app sample-ai --typescript
cd sample-ai
yarn add ai openai-edge
yarn add langchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Implementing SDKs
&lt;/h2&gt;

&lt;p&gt;/api/aiSdkChat.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { OpenAIStream, StreamingTextResponse } from "ai";
import { Configuration, OpenAIApi } from "openai-edge";
import { NextRequest } from "next/server";

export const runtime = "edge";

const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(config);

export default async function handler(req: NextRequest) {
  const { messages } = await req.json();

  const response = await openai.createChatCompletion({
    model: "gpt-3.5-turbo",
    stream: true,
    temperature: 0.9,
    messages: messages.map((message: any) =&amp;gt; ({
      content: message.content,
      role: message.role,
    })),
  });
  const stream = OpenAIStream(response);
  return new StreamingTextResponse(stream);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;/api/langChainChat.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { StreamingTextResponse, LangChainStream, Message } from "ai";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { AIMessage, HumanMessage } from "langchain/schema";
import { NextRequest } from "next/server";

export const runtime = "edge";

export default async function handler(req: NextRequest) {
  const { messages } = await req.json();
  const { stream, handlers } = LangChainStream();

  const llm = new ChatOpenAI({
    modelName: "gpt-3.5-turbo",
    streaming: true,
    temperature: 0.9,
  });

  llm
    .call(
      (messages as Message[]).map((m) =&amp;gt;
        m.role == "user"
          ? new HumanMessage(m.content)
          : new AIMessage(m.content)
      ),
      {},
      [handlers]
    )
    .catch(console.error);
  return new StreamingTextResponse(stream);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;index.tsx&lt;br&gt;
In useChat, specify either Vercel AI SDK or LangChain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import type { NextPage } from "next";
import { useChat } from "ai/react";

const Home: NextPage = () =&amp;gt; {
  const aiSdkChat = `/api/aiSdkChat`;
  const langChainChat = `/api/langChainChat`;

  const { messages, input, isLoading, stop, handleInputChange, handleSubmit } =
    useChat({
      api: aiSdkChat,
    });

  if (!isLoading) console.log(messages);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;div className="mx-auto w-full max-w-md py-24 flex flex-col"&amp;gt;
        &amp;lt;p className="font-bold text-lg"&amp;gt;ChatGPT&amp;lt;/p&amp;gt;
        &amp;lt;br /&amp;gt;
        {messages.map((m) =&amp;gt; (
          &amp;lt;div key={m.id} className="w-96 mb-2 p-2"&amp;gt;
            {m.role === "user" ? "Human: " : "AI: "}
            {m.content}
          &amp;lt;/div&amp;gt;
        ))}

        &amp;lt;br /&amp;gt;
        &amp;lt;form onSubmit={handleSubmit}&amp;gt;
          &amp;lt;input
            name="box"
            className="w-96 flex rounded bottom-0 border border-gray-300 text-gray-700 mb-2 p-2"
            value={input}
            onChange={handleInputChange}
          /&amp;gt;
          {isLoading ? (
            &amp;lt;button
              type="submit"
              className="opacity-50 cursor-not-allowed w-96 rounded bg-sky-500 hover:bg-sky-700 mb-2 p-2"
              disabled
            &amp;gt;
              Send
            &amp;lt;/button&amp;gt;
          ) : (
            &amp;lt;button
              type="submit"
              className="w-96 rounded bg-sky-500 hover:bg-sky-700 mb-2 p-2"
            &amp;gt;
              Send
            &amp;lt;/button&amp;gt;
          )}
        &amp;lt;/form&amp;gt;
        &amp;lt;p className="w-96 text-slate-500 text-xs"&amp;gt;
          You can check the value of a message variable from the console of the
          development tool to see how the value is stored.
        &amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start with yarn dev.&lt;br&gt;
Try to display localhost:3000 in a PC browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsl7ootdh6a5ouiev0kp4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsl7ootdh6a5ouiev0kp4.png" alt=" " width="467" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conversation with AI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fw39hahv3uiyhm5iy4o48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fw39hahv3uiyhm5iy4o48.png" alt=" " width="483" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It appears to be working properly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks to the Vercel AI SDK, it was very easy to implement such a simple chat page.&lt;br&gt;
Adding further error handling would provide an opportunity for better understanding.&lt;/p&gt;

&lt;p&gt;LangChain has many interesting features such as AI Argent, which I will try again in the future.&lt;/p&gt;

&lt;p&gt;Reference site&lt;br&gt;
&lt;a href="https://sdk.vercel.ai/docs/api-reference/use-chat" rel="noopener noreferrer"&gt;https://sdk.vercel.ai/docs/api-reference/use-chat&lt;/a&gt;&lt;br&gt;
&lt;a href="https://sdk.vercel.ai/docs/api-reference/langchain-stream" rel="noopener noreferrer"&gt;https://sdk.vercel.ai/docs/api-reference/langchain-stream&lt;/a&gt;&lt;br&gt;
&lt;a href="https://js.langchain.com/docs/get_started" rel="noopener noreferrer"&gt;https://js.langchain.com/docs/get_started&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>chatgpt</category>
      <category>ai</category>
    </item>
    <item>
      <title>Deploying FastAPI app with Google Cloud Run</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Tue, 27 Jun 2023 07:13:22 +0000</pubDate>
      <link>https://forem.com/izawa/deploying-fastapi-app-with-google-cloud-run-13f3</link>
      <guid>https://forem.com/izawa/deploying-fastapi-app-with-google-cloud-run-13f3</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This post explains how to deploy a FastAPI app using Google Cloud Run.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google Cloud account&lt;/li&gt;
&lt;li&gt;gcloud CLI&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Project setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Create a FastAPI app using Poetry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install poetry
poetry new sample
cd sample
mv sample app
cd app
poetry add fastapi
poetry add 'uvicorn[standard]'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create app/main.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch app/main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit main.py 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;# main.py

from fastapi import FastAPI

app = FastAPI()


@app.get("/", tags=["root"])
async def root():
    return {"message": "Hello World"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it in uvicorn&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry shell
uvicorn app.main:app --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Google Cloud Run setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you have already installed gcloud CLI, update it 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;gcloud components update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect the gcloud CLI to your GCP account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up your project ID&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config set project PROJECT_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Region settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config set run/region REGION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth configure-docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prepare Dockerfile in the same hierarchy as the app directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.11.3
ENV PYTHONUNBUFFERED True

RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install --no-cache-dir -r  requirements.txt

ENV APP_HOME /root
WORKDIR $APP_HOME
COPY /app $APP_HOME/app

EXPOSE 8080
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

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

&lt;/div&gt;



&lt;p&gt;Prepare requirements.txt file for Dockerfile.&lt;br&gt;
(In this case, use requirements.txt in the Dockerfile.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry export -f requirements.txt --output requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that it is ready, deploy to Cloud Run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud run deploy sample --port 8080 --source .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, it will be created with the name sample.&lt;br&gt;
A URL will be created, so check the operation.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the above, you can now deploy your FastAPI app to Google Cloud Run.&lt;/p&gt;

&lt;p&gt;Although the details are omitted here, it would be a good idea to actually add CORS and headers in middleware and implement an authentication function such as Firebase Authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The path to import must be specified from the app directory.&lt;/p&gt;

&lt;p&gt;Example: app/lib/test.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/main.py
from app.lib import test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>fastapi</category>
      <category>cloudrun</category>
    </item>
    <item>
      <title>How to deploy FastAPI app using AWS CDK Typescript</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Wed, 14 Jun 2023 06:13:20 +0000</pubDate>
      <link>https://forem.com/izawa/how-to-deploy-fastapi-using-aws-cdk-typescript-1ml6</link>
      <guid>https://forem.com/izawa/how-to-deploy-fastapi-using-aws-cdk-typescript-1ml6</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this post, I will explain how to deploy FastAPI to a Lambda function, using the Typescript-based AWS CDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisite&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This article is intended for those who have experience building Lambda functions and API Gateways with Typescript-based AWS CDK.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup of AWS CDK and AWS CLI is omitted.&lt;/li&gt;
&lt;li&gt;Python setup is omitted.&lt;/li&gt;
&lt;li&gt;FastAPI description is omitted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Development Environment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;node v18.5.0&lt;/li&gt;
&lt;li&gt;CDK 2.83.1&lt;/li&gt;
&lt;li&gt;Python 3.11.3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fastapi
pip install mangum
pip install uvicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Create the app&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir sample-ts-fastapi
cd sample-ts-fastapi
cdk init --language typescript
npm install @aws-cdk/aws-lambda-python-alpha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/@aws-cdk/aws-lambda-python-alpha" rel="noopener noreferrer"&gt;@aws-cdk/aws-lambda-python-alpha&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Defining Lambda and API Gateway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Modify &lt;code&gt;lib/sample-ts-fastapi-stack.tsas&lt;/code&gt; follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";

import { PythonFunction } from "@aws-cdk/aws-lambda-python-alpha";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import { LambdaRestApi } from "aws-cdk-lib/aws-apigateway";

export class SampleTsPyFastapiStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const apiName = `SampleApi`;
    const lambdaName = `MyLambda`;

    const lambda = new PythonFunction(this, lambdaName, {
      entry: "lambda",
      runtime: Runtime.PYTHON_3_10,
      index: "main.py",
      handler: "handler",
      environment: {},
    });
    const api = new LambdaRestApi(this, apiName, {
      handler: lambda,
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Create Lambda Function&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The directory and file structure should be as follows.&lt;br&gt;
Create main.py and user.py.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lambda/
 ├ main.py
 ├ router/
   └ user.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;main.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from fastapi import FastAPI
from mangum import Mangum
from .routers import user

app = FastAPI()


@app.get("/", tags=["root"])
async def root():
    return {"message": "Hello World"}

app.include_router(user.router)

handler = Mangum(app, lifespan="off")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;user.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from fastapi import APIRouter


router = APIRouter()

@router.get("/user", tags=["user"])
async def getUser():
    return {"message": "test user"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s try to run it in this state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uvicorn lambda.main:app --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API created on this page is now displayed. &lt;code&gt;http://127.0.0.1:8000/docs&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Modify &lt;code&gt;from routers import user&lt;/code&gt; in main.py. (It did not pass at &lt;code&gt;.routers&lt;/code&gt;.)&lt;/li&gt;
&lt;li&gt;Launch Docker in advance
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Adding the lambda layer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since we are using FastAPI and Mangum, we create and add two layer.&lt;br&gt;
There is also a way to include the Lambda Layer with the CDK and deploy it, but this time we did it by creating it separately.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create s3 bucket&lt;/li&gt;
&lt;li&gt;Zip the Python library&lt;/li&gt;
&lt;li&gt;Upload zip to s3&lt;/li&gt;
&lt;li&gt;Copy its Object URL&lt;/li&gt;
&lt;li&gt;Create layers from the lambda page (Object URL is required)&lt;/li&gt;
&lt;li&gt;Once the layer is created, copy its ARN&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For 2 and 3, for example, create it this way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -t python/ fastapi
zip -r layer1.zip python
aws s3 cp layer1.zip s3://{backet name}/layer1.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have created two layers, FastAPI and Mangum, we can add them to the lambda function described earlier.&lt;/p&gt;

&lt;p&gt;From the Lambda page of the AWS console, go to the function details page and add two layers. Enter the ARN from earlier here.&lt;/p&gt;

&lt;p&gt;This completes the setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;That’s it, I was able to get Python’s FastAPI to work with Lambda on the Typescript-based AWS CDK.&lt;/p&gt;

&lt;p&gt;However, I could not figure out why the import path in the main.py code would not pass in Lambda unless I did it this way.&lt;/p&gt;

&lt;p&gt;I am a beginner in Python. If there is a way to write code that can be executed without worrying about the difference between the path environment on Lambda and the local path environment, I would appreciate it if someone could tell me.&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>serverless</category>
      <category>cdk</category>
    </item>
  </channel>
</rss>
