<?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: Izawa</title>
    <description>The latest articles on DEV Community by Izawa (@izawa).</description>
    <link>https://dev.to/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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1101096%2F00f71741-87f5-4035-993b-fe4cbb4e4010.png</url>
      <title>DEV Community: Izawa</title>
      <link>https://dev.to/izawa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/izawa"/>
    <language>en</language>
    <item>
      <title>An Agent Skill that changes your question instead of answering it</title>
      <dc:creator>Izawa</dc:creator>
      <pubDate>Sat, 25 Jul 2026 17:03:26 +0000</pubDate>
      <link>https://dev.to/izawa/an-agent-skill-that-changes-your-question-instead-of-answering-it-4gp6</link>
      <guid>https://dev.to/izawa/an-agent-skill-that-changes-your-question-instead-of-answering-it-4gp6</guid>
      <description>&lt;p&gt;Ask any assistant an open-ended question — should I build this, should I take this job, how do I position this product — and you get advice that is reasonable and slightly generic. Narrow the target. Differentiate. Build an MVP. Talk to users. Test demand.&lt;/p&gt;

&lt;p&gt;None of it is wrong. It just never moves where you are standing.&lt;/p&gt;

&lt;p&gt;Insight Compiler is an Agent Skill I published that treats that generic answer as the starting line instead of the finish. It writes the ordinary answer down explicitly, then spends the rest of the run climbing off it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loop
&lt;/h2&gt;

&lt;p&gt;The skill runs seven steps every time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intent discovery&lt;/strong&gt; — separates the surface question from the real goal, and names the question you haven't asked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordinary-answer baseline&lt;/strong&gt; — writes out what a normal AI would say, explicitly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain lenses&lt;/strong&gt; — looks at the problem through distant fields: military strategy, urban design, game design, religion, investment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery operators&lt;/strong&gt; — deforms the problem: invert it, swap who acts, shift the scale, hunt for the hole nobody is looking at&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hint bank&lt;/strong&gt; — crosses lenses with operators into a dense list of raw material&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategy candidates&lt;/strong&gt; — 2-3 directions, each traced back to the specific hints it came from&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest evaluation + one validation fork&lt;/strong&gt; — ranks them without manufacturing a tie, then commits in advance to what each test outcome should change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 2 is the load-bearing one. An unstated ordinary answer is a ceiling the model quietly settles into; a written-down one is a floor you can push off. Step 7 is what keeps the whole thing from being a brainstorm — you end with one cheap test and a decision already made for either result.&lt;/p&gt;

&lt;p&gt;The internal scan is wide, but the output is curated. It shows the strongest findings rather than dumping every lens it tried.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;Here is a real run. The question I gave it was my own, and it is a small one, which makes it a good demo — I published this skill and nobody was visiting the repository, so I asked what to do about it.&lt;/p&gt;

&lt;p&gt;A plain assistant answered the question as asked: add more examples to the README, record a GIF, post it to X and Reddit, get the content ready before announcing. Solid, actionable, and it accepts every premise in the question.&lt;/p&gt;

&lt;p&gt;The skill opened by rejecting the question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Essential question:&lt;/strong&gt; Not "how do I get more repo visitors," but "where does the target person first encounter enough value to feel something move in their thinking?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is non-obvious:&lt;/strong&gt; The premise "low visits = insufficient explanation" conflates two different bottlenecks — the discovery/distribution problem and the comprehension problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, near the end, the assumption I hadn't noticed I was making:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The assumption that "GitHub repo visitor count" is the correct success metric, and that "hard to understand" is the cause of low interest, is itself questionable. For an agent skill that runs inside Claude, the person deciding whether to adopt it may never need to visit the repo at all — if they encounter a compelling output first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Side by side:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ordinary answer&lt;/th&gt;
&lt;th&gt;Insight Compiler&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Improve the README&lt;/td&gt;
&lt;td&gt;Decide who it is for, first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add 3-5 demos&lt;/td&gt;
&lt;td&gt;Produce one complete example that lands with one person&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Announce on social media&lt;/td&gt;
&lt;td&gt;Distribute the output itself as the content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grow visitor count&lt;/td&gt;
&lt;td&gt;Create the first repeat user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It also graded its own three candidates honestly — flagging its most interesting one as "unverified whether target readers are actually where you post," and admitting the boring README fix was the only one executable today. The verdict: do the boring one because it is nearly free, but it is necessary, not sufficient.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/snc2work/insight-compiler/blob/main/examples/nobody-visits-my-repository.md" rel="noopener noreferrer"&gt;full transcript is in the repo&lt;/a&gt;, unedited, both answers side by side. It is long — that is the honest shape of the output, not a teaser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;

&lt;p&gt;An Agent Skill is just a directory with a &lt;code&gt;SKILL.md&lt;/code&gt; in it. For Claude Code:&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 https://github.com/snc2work/insight-compiler.git
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; insight-compiler/InsightCompiler ~/.claude/skills/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart, then &lt;code&gt;/skills&lt;/code&gt; to confirm it loaded. Any agent that supports Agent Skills works the same way — copy the directory, keeping &lt;code&gt;SKILL.md&lt;/code&gt; and &lt;code&gt;references/&lt;/code&gt; together.&lt;/p&gt;

&lt;p&gt;You never invoke it by name. It triggers on the shape of the question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Let me consult you on something. I'm deciding whether to quit my job to
build my own product.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users are complaining about our paid plan. Should we lower the price?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I have an idea for a product, but I'm not sure it's different enough from
what's already out there.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a second version, &lt;code&gt;InsightCompilerPersonal&lt;/code&gt;, that keeps a local profile at &lt;code&gt;~/.insight-compiler/profile.md&lt;/code&gt;. It records only working habits — your known constraints, whether you actually run the validations you agree to, the angle you always enter from — and never which ideas you liked, so it grounds the executability judgment without building you an echo chamber. Install one or the other, not both; they trigger on the same prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  When not to use it
&lt;/h2&gt;

&lt;p&gt;A full session is thousands of words. That length is deliberate, and it makes this the wrong tool whenever you want a quick factual answer, some code, or a decision you can act on in the next five minutes.&lt;/p&gt;

&lt;p&gt;It also cannot check reality. When it says a market gap exists, that is a hypothesis produced by reasoning, not research. Treat novelty claims as things to go verify.&lt;/p&gt;

&lt;p&gt;And if you already know what you are doing and just need it done, an ordinary answer is the correct answer. This skill is for the questions where you suspect you are solving the wrong problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  One note on the example
&lt;/h2&gt;

&lt;p&gt;There is something circular about the demo above, and it is worth saying out loud: the run told me to stop polishing the repository and put a finished output where readers already are. This post is that instruction being carried out. Whether it worked is measurable, and the session pre-committed to what each outcome means — reaction means keep producing transcripts, silence means the problem is not presentation and I should go narrow with one real user instead.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/snc2work/insight-compiler" rel="noopener noreferrer"&gt;https://github.com/snc2work/insight-compiler&lt;/a&gt; (MIT)&lt;/p&gt;

&lt;p&gt;If you try it, I would like to know what you pointed it at.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>agentskills</category>
      <category>showdev</category>
    </item>
    <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://dev.to/izawa/auto-backup-your-git-repo-on-every-commit-3iab</link>
      <guid>https://dev.to/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://dev.to/izawa/getting-started-with-langchain-2m10</link>
      <guid>https://dev.to/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://dev.to/izawa/how-to-use-autogen-1cpk</link>
      <guid>https://dev.to/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://dev.to/izawa/implement-thirdweb-smart-wallet-and-embedded-wallet-in-nextjs-3eil</link>
      <guid>https://dev.to/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="799" 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="609"&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="430"&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://dev.to/izawa/implement-vercel-ai-sdk-and-langchain-js-with-nextjs-6m</link>
      <guid>https://dev.to/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://dev.to/izawa/deploying-fastapi-app-with-google-cloud-run-13f3</link>
      <guid>https://dev.to/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://dev.to/izawa/how-to-deploy-fastapi-using-aws-cdk-typescript-1ml6</link>
      <guid>https://dev.to/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>
