Amazon Q Developer の生成AI で日本語コーディング

Amazon Q developer の（一部で）日本語サポートが（追加で）開始したので日本語でコーディングが出来るか試してみます。

https://aws.amazon.com/jp/blogs/news/amazon-q-developer-global-capabilities/

# そもそもどの機能が日本語化したの？

Amazon Q Developerは機能が多く、使っていない人からするとどこが日本語化されたのか分かりにくい部分があります。
上記ブログではIDEとCLIに言及されていますが、実際にはCLIは元々日本語が動いていたような気がするので、今回はIDEのチャット機能からのエージェントを呼び出したコーディング時に日本語が使えるようになった感じです。

# 試した環境

Windows + Visual Studio Code + Amazon Q拡張 + Python
※Amazon Q拡張のインストール手順と設定手順は省きます

# 一発目

左下のチャット部分に、`/dev`コマンドの後に
`streamlitを使って2024年のGAFAの株価推移を比較できるグラフを作って`
と日本語で雑に指示してみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/85afb40c-079a-4930-b764-a1c68e325938.png" width="50%">

実行します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/111ebf6d-1faa-4908-befd-56328a7df250.png" width="50%">

何やら考えています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/87ac4214-1b18-4527-a917-75e5c231dd6f.png" width="50%">

Streamlitを指定したのでPythonのコードとrequirements.txtが生成されました。とりあえずAcceptします。

### 生成されたコード

```requirements.txt
streamlit
yfinance
pandas
plotly
```
```Python:gafa_stocks.py
import streamlit as st
import yfinance as yf
import pandas as pd
import plotly.express as px
from datetime import datetime, timedelta

# Page configuration
st.set_page_config(page_title="GAFA Stocks Comparison 2024", layout="wide")
st.title("GAFA Stocks Price Comparison 2024")

# Define GAFA stock symbols
gafa_symbols = {
    "Google (Alphabet)": "GOOGL",
    "Apple": "AAPL",
    "Meta (Facebook)": "META",
    "Amazon": "AMZN"
}

# Get data for each stock
start_date = "2024-01-01"
end_date = datetime.now().strftime("%Y-%m-%d")

# Create empty DataFrame to store all stock data
df_combined = pd.DataFrame()

# Fetch data for each stock
for company, symbol in gafa_symbols.items():
    stock = yf.Ticker(symbol)
    df = stock.history(start=start_date, end=end_date)
    df["Company"] = company
    df_combined = pd.concat([df_combined, df])

# Create interactive plot using Plotly
fig = px.line(df_combined, 
              x=df_combined.index, 
              y="Close",
              color="Company",
              title="GAFA Stock Prices in 2024",
              labels={"Close": "Stock Price (USD)", "index": "Date"},
              template="plotly_dark")

# Display the plot
st.plotly_chart(fig, use_container_width=True)

# Add additional statistics
st.subheader("Stock Price Statistics (2024)")

# Calculate statistics for each company
for company, symbol in gafa_symbols.items():
    company_data = df_combined[df_combined["Company"] == company]
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        st.metric(f"{company} - Current Price", 
                 f"${company_data['Close'].iloc[-1]:.2f}",
                 f"{((company_data['Close'].iloc[-1] - company_data['Close'].iloc[0]) / company_data['Close'].iloc[0] * 100):.2f}%")
    
    with col2:
        st.metric(f"{company} - Highest Price", 
                 f"${company_data['High'].max():.2f}")
    
    with col3:
        st.metric(f"{company} - Lowest Price", 
                 f"${company_data['Low'].min():.2f}")
```
YahooファイナンスのAPIで値を取得してなにやら描画している雰囲気がします。
とりあえず `pip install -r requirements.txt` してstreamlitから実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/aa9a2dd2-bc17-4d47-b160-6785c6060495.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/0dfe96f6-cd12-43b9-8201-a2d45a665901.png)

すごない？

縦軸がドルになっている点が気になるのでそこの修正を頼んでみます。

# 二発目

I have another taskを選んだ後に、`Y軸は金額ではなくて株価の上昇率に変更して`と指示してみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/24bbb10f-5855-4c9b-8183-ae61c50d2c7c.png" width="50%">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/078e7d49-934b-4733-8cd4-8cf830b48e7b.png)

gafa_stock.pyの変更案が示され、diffが表示されています。終値ではなくパーセンテージに変えている雰囲気がするのでAcceptして実行してみます。

```Python:gafa_stocks.py
import streamlit as st
import yfinance as yf
import pandas as pd
import plotly.express as px
from datetime import datetime, timedelta

# Page configuration
st.set_page_config(page_title="GAFA Stocks Comparison 2024", layout="wide")
st.title("GAFA Stocks Price Comparison 2024")

# Define GAFA stock symbols
gafa_symbols = {
    "Google (Alphabet)": "GOOGL",
    "Apple": "AAPL",
    "Meta (Facebook)": "META",
    "Amazon": "AMZN"
}

# Get data for each stock
start_date = "2024-01-01"
end_date = datetime.now().strftime("%Y-%m-%d")

# Create empty DataFrame to store all stock data
df_combined = pd.DataFrame()

# Fetch data for each stock
for company, symbol in gafa_symbols.items():
    stock = yf.Ticker(symbol)
    df = stock.history(start=start_date, end=end_date)
    # Calculate percentage change from initial price
    initial_price = df['Close'].iloc[0]
    df['Price_Change_Percent'] = ((df['Close'] - initial_price) / initial_price * 100)
    df["Company"] = company
    df_combined = pd.concat([df_combined, df])

# Create interactive plot using Plotly
fig = px.line(df_combined, 
              x=df_combined.index, 
              y="Price_Change_Percent",
              color="Company",
              title="GAFA Stock Price Changes in 2024",
              labels={"Price_Change_Percent": "Price Change (%)", "index": "Date"},
              template="plotly_dark")

# Display the plot
st.plotly_chart(fig, use_container_width=True)

# Add additional statistics
st.subheader("Stock Price Statistics (2024)")

# Calculate statistics for each company
for company, symbol in gafa_symbols.items():
    company_data = df_combined[df_combined["Company"] == company]
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        st.metric(f"{company} - Current Price", 
                 f"${company_data['Close'].iloc[-1]:.2f}",
                 f"{((company_data['Close'].iloc[-1] - company_data['Close'].iloc[0]) / company_data['Close'].iloc[0] * 100):.2f}%")
    
    with col2:
        st.metric(f"{company} - Highest Price", 
                 f"${company_data['High'].max():.2f}")
    
    with col3:
        st.metric(f"{company} - Lowest Price", 
                 f"${company_data['Low'].min():.2f}")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/c5c96dff-3533-4983-9ed1-bc82258d8882.png)

なんか合ってそうな雰囲気です！

# 三発目

プログラムの変更が出来る＝ローカルのファイルが読めるという事が分かったので、プログラムではないファイルをローカルに置いて実行してみます。

以下のファイルを配置します。

```:api.txt
気象庁の天気予報 東京のURL
https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json

応答項目の仕様
{
"publishingOffice":"気象庁",
"reportDatetime":応答日時,
"targetArea":"東京都","
headlineText":"",
"text":概況
}
```
また`/dev`に続けて、
`api.txtを参考に、気象庁のAPIを呼び出して東京の天気予報概況を表示して。streamlitを使って`と雑に指示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/db26d208-1aee-40dc-8515-ce5f0da9a388.png" width="50%">

pythonファイルとrequirements.txtが生成されたのでAcceptします。

### 生成されたコード

```:requirements.txt
streamlit
requests
```
`requests`を呼んでるのでHTTPアクセスしようとしてるなという感じです。

```Python:weather_app.py
import streamlit as st
import requests
import json

# Set page config
st.set_page_config(
    page_title="東京天気予報",
    page_icon="🌤️",
)

# Add title
st.title("東京の天気予報概況")

# JMA API endpoint for Tokyo (area code 130000)
API_URL = "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json"

try:
    # Get weather forecast data
    response = requests.get(API_URL)
    response.raise_for_status()  # Raise an exception for bad status codes
    data = response.json()

    # Display weather information
    st.subheader("気象情報")
    st.write(f"発表時刻: {data['reportDatetime']}")
    
    # Display headline
    if data.get('headlineText'):
        st.markdown("### 概況")
        st.write(data['headlineText'])
    
    # Display detailed text
    if data.get('text'):
        st.markdown("### 詳細")
        st.write(data['text'])

except requests.exceptions.RequestException as e:
    st.error("天気予報データの取得に失敗しました。")
    st.error(f"エラー: {str(e)}")
except json.JSONDecodeError:
    st.error("データの解析に失敗しました。")
except KeyError as e:
    st.error(f"データの形式が不正です: {str(e)}")
```
HTTPで取得してベタッと表示するシンプルなアプリです。実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573242/6317b00c-1ee6-4bd6-8dc8-1866b7e402a3.png)

動きました！

# 雑感

幾つか試した感じ、コード生成前のエージェントがローカルのファイル（リポジトリ？）を読んでくれるので、修正対象のプログラムを探したりサジェストさせたりするのにも使えそうです。

また、`/dev`コマンドは自由度が高そうなので、このコマンドを入れた後は「ローカルリポジトリに対するエージェントへの指示」だと思って入力すれば良さそうです。

ちなみに上記のファイルは一発で表示されたかのように書いていますが、実際には上手くいかないケースもちょいちょいあります。もちろんバグ修正をさせることも出来ますが、一発目の生成が上手くいってないと修正させても上手くいかないことがままあるので、そういうときは`/clear`して再生成した方が速いかもしれません。