æè¡blogã®ãªã³ã¯ãæãããChatGPTãèŠçŽããŠãããæãã«æŽåœ¢ããŠãã£ã³ãã«æçš¿ããŠãããbotã瀟å Slackã«çããããæã£ã話
ããã«ã¡ã¯ãæ ªåŒäŒç€Ÿã·ã°ãã¢ã€ã®ãšã³ãžãã¢ã®@k_muroã§ãã
ä»åã®èšäºã¯æè¿å°å
¥ãããæè¡blogãè¯ãæãã«å
±æããŠãããSlack botãã®ã玹ä»ãã
ã¯ããã«
æè¡ã®é²åã¯æ¢ãŸããªãã(çé¢ç®ãªè©±ãAIç³»ã®é²æãããžã§ããããŠå
šç¶è¿œããªã)
æ¯æ¥ã®ããã«æ°ããæè¡ããã¬ãŒã ã¯ãŒã¯ãã©ã€ãã©ãªãããŒã«ãçãŸããŠããŸãããããªäžã§ãšã³ãžãã¢ãšããŠåããŠãããšããã®æ
å ±ã®æ³¢ã«ç²ããæããããšããããŸãããïŒ ãããŸãããïŒ(è
è¿«)
å®éç§ããã®äžäººã§ããã®å°ããªç²ããç©ã¿éãªã£ãŠå€§ããªã¹ãã¬ã¹ãšãªãããšã«æ°ã¥ããŸããã
ãæ°ããæè¡æ å ±ã远ãã€ããããªïŒã
ããã®ããã°èšäºãåŸã§èªãããšæã£ãŠãã®ã«ãã©ããã£ãã£ãïŒã
ãããŒã å šå¡ãåãæ å ±ãæã£ãŠããå¿é ã ãªãã
ãããªæ¥åžžã®çåãäžå®ããéããããã®äžæ©ãšããŠãç§ã¯ããSlack botãéçºããŸããããã®botã¯ãéãããæè¡ããã°ã®ãªã³ã¯ããå 容ãAIã§èŠçŽãããã®ç²ŸåºŠã®é«ãèŠçŽãèŠãããæŽåœ¢ããŠãç¹å®ã®ãã£ã³ãã«ã«æçš¿ããŠãããŸã(ã¹ãã!!)ãèšäºã¯è²åããããã«ããŽãªã§ç¬æã«åé¡ãããã«ãOGPç»åãååŸãããŠããã®å šãŠãNotionã«ä¿åããããããåŸã§èªã¿è¿ãããšãç°¡åã§ãã
ãã¯ã£ããããªãæ å ±ã远ãã€ãããšã楜ã«ãªãããïŒããšæããããªãããã®èšäºã¯ããããªããªãã«ãšã£ãŠã®æäžäž»ã«ãªããããããŸããããã¡ãã§botã®å ·äœçãªæ©èœãšå®è£ ãå®éã«ç€Ÿå ã§ã©ãã ã圱é¿ããã£ãã®ãããããŠä»åŸã®å±éã«ã€ããŠè©³ãã玹ä»ããŠãããŸãã
äœãããšãããã£ãã
ä»ã®ã¡ã³ããŒããå
±æãããèšäºãèªãã®ãã ããã£ãããChatGPTã«èŠçŽããŠãããããã£ã
ChatGPTã®æéãäŒç€Ÿã«æ¯æã£ãŠãããããã£ããã
æè¡æ
å ±ã«ãã£ããã¢ãããããã & ã³ãã¥ãã±ãŒã·ã§ã³ãå éããããã«ChatGPTãæŽ»çšããããšèããã®ããã£ããã§ãã
宿ã€ã¡ãŒãž
äœ¿ãæ¹ã¯ç°¡åïŒ

âbotå®ãŠã«DMã§æè¡blogã®URLãéããšã

10^4300幎ãŸã§ã«è§£æ±ºããªããšãããªãåé¡
botãè¯ãæãã«èŠçŽ & æŽåœ¢ãããã®ãç¹å®ã®ãã£ã³ãã«ã«æçš¿ããŠããã!!(ã¹ãã!!)
èšäºã®å
容ã§ãã£ããã«ããŽã©ã€ãºããŠããã®ã«ããŽãªããšã«è²åãããªãããŠããŸãã(ããšãã°ããã¶ã€ã³ç³»ã¯é»è²ã¿ãããª)
ãããªæãã®è²åãã§ã



ãã£ã³ãã«å
ã§ãbotå®ãŠã«çŽæ¥URLãæãã€ããŠãåå¿ããŠãããŸãã

Notion
æçš¿ãããèšäºã¯ãNotionã«ãŸãšããããŠããŸãã(ãªããããŸãNotionã¯èŠãããŠãªãæ°ãããŸã)
æ§æ
ã©ã®ãããªæ§æããã£ãã玹ä»ã
Slack Boltãäžå¿ãšãªã£ãŠãSlack, ChatGPT, Notionã®APIãå©ããŠããŸãã

å
šäœæ§æå³
䜿ã£ãŠããæè¡ã«ã€ããŠ
èªãã ããšããªããªãã®ã§ãããããã€ãèŠç¹ãçµã£ãŠç޹ä»ã
ChatGPT: Function calling
Function callingãšã¯ãChatGPTã®åŒã³åºãã«ãããŠãããã³ããã«å¿ãã颿°ãåŒã³åºããããã«ããŠãããæ©èœã§ãããããããšèª¬æããã£é£ã°ããçµè«ãæžããšChatGPTããè¿ã£ãŠãããè¿äºãããã¡ããæ³å®ãããã©ãŒãããã«åŸãããããŸãã
ä»åã¯ãã®Function callingã䜿ã£ãŠããèšäºã®å
容ã®èŠçŽãšã¿ã°ãå¿
ãJSON圢åŒã§è¿çããããšããçŽæãããŠããŸãã
Function callingã®èª¬æã«ã€ããŠã¯ä»¥äžã®èšäºã詳ããã®ã§åèã«ããŠãã ããã
- OpenAIã®FunctionCallingãçè§£ãã
- [OpenAI] Function callingã§éãã§ã¿ããæ¬è³ªãèŠããŠããã®ã§ãŸãšããŠã¿ã | DevelopersIO
- ChatGPT ã® Function calling ã§ç¢ºå®ã« JSON 圢åŒã§åºåã§ããã®ãã·ã¥ããšç¢ºèªããŠã¿ãïœbbz
Slack: Bolt
Slack Boltã¯ãSlackã§åäœããBotãç°¡åã«äœæããããã®ãã¬ãŒã ã¯ãŒã¯ã§ããæ®éã«ããã°ã©ãã³ã°ãããããç°¡åã«ãç¹å®ã®åäœãæ©èœãSlackå
ã§å®è¡ã§ããããã«ããããšãã§ããŸãã
äŸãã°ã誰ããç¹å®ã®ã¯ãŒãããã£ããã§äœ¿ã£ããèªåçã«å¿çããããŸãã¯æ¯æå®æã«ããã¯ããããšã¡ãã»ãŒãžãéãããªã©ãã§ããŸãã
ä»åã®å®è£
ã§ã¯ããŠãŒã¶ãŒããã®Slackã®æçš¿ãåãä»ããŠããã®äžé£ã®æµããSlack Boltãæ
ã£ãŠããŸãã
ãã®åŠçã¯Slack Blotã®æ©èœã®åãã®éšåã«ããããã·ã§ãŒãã«ããã®æ©èœãå®è£
ããããã¢ãŒãã«ã䜿ã£ãŠSlackã«ç䌌çãªGUIãæäŸããããšãã§ããŸãã
Slack Boltã®èª¬æã«ã€ããŠã¯ã以äžã®èšäºã詳ããã®ã§åèã«ããŠãã ããã
äœã£ãŠã¿ããïŒ
å®è£ ã«ã€ããŠã話ããŸãïŒ
çšæãããã®
Slack
-
SLACK_APP_TOKEN- Slack Boltããœã±ããã¢ãŒãã§å®è¡ããããã«å¿ èŠãªToken
- ãã¡ããåèã«ååŸããŠãã ãã:Slack ãœã±ããã¢ãŒãã®æãç°¡åãªå§ãæ¹ #Slack - Qiita
-
SLACK_BOT_TOKEN- Slackã®Botã®Token
- ãã¡ããåèã«ååŸããŠãã ãã:Slack Python SDK ã§ãã£ã³ãã«ã«ã¡ãã»ãŒãžãæçš¿ããã #Python - Qiita
ChatGPT
-
OPENAI_API_KEY- ChatGPT APIã䜿ãããã®API Key
- â»ææã§ãããç§ã¯äŒç€Ÿã®çµè²»ã§èœãšããŠããŸãâ圡
- ãã¡ããåèã«ååŸããŠãã ãã:openAIã®APIããŒã®ååŸãšPython openaiã¢ãžã¥ãŒã«ã®åäœç¢ºèªã¡ã¢ | Oval Design Studio
- ChatGPT APIã䜿ãããã®API Key
Notion
-
NOTION_APP_TOKEN- Notion APIã䜿ãããã®API Token
- ãã¡ããåèã«ååŸããŠãã ãã:Notion API à Python
-
NOTION_DATABASE_URL- ããŒã¿ã远å ããå ã®NotionããŒã¿ããŒã¹ãããããŒãžã®URL
- ãã¡ããåèã«ååŸããŠãã ãã:Notion API à Python
-
NOTION_DATABASE_ID- ããŒã¿ã远å ããå ã®NotionããŒã¿ããŒã¹ã®ID
- ãã¡ããåèã«ååŸããŠãã ãã:Notion API à Python
å®éã®ã³ãŒã
å®è£
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from extractcontent3 import ExtractContent
import requests
import re
from bs4 import BeautifulSoup
import openai
import tiktoken
from tiktoken.core import Encoding
from notion_client import Client
from slack_sdk import WebClient
import traceback
import json
from dotenv import load_dotenv
load_dotenv()
SLACK_APP_TOKEN = os.environ["SLACK_APP_TOKEN"]
SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"]
ADMIN_SLACK_ID = os.environ["ADMIN_SLACK_ID"] # 管çè
ã®SlackãŠãŒã¶ãŒID
TECH_RANDOM_CH_ID = os.environ["TECH_RANDOM_CH_ID"] # æçš¿å
ã®Slackãã£ã³ãã«ã®ID
TECH_RANDOM_CH_NAME = "#tech-random"
# OGPã€ã¡ãŒãžãååŸã§ããªãã£ããšãã«è¡šç€ºããç»å
DEFAULT_OGP_IMAGE = os.environ["DEFAULT_OGP_IMAGE"]
NOTION_APP_TOKEN = os.environ["NOTION_APP_TOKEN"]
NOTION_DATABASE_ID = os.environ["NOTION_DATABASE_ID"]
NOTION_DATABASE_URL = os.environ["NOTION_DATABASE_URL"]
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
openai.api_key = OPENAI_API_KEY
category_json_file = open("category_dict.json", 'r')
CATEGORY_DICT = json.load(category_json_file)
functions_json_file = open("functions_dict.json", 'r')
FUNCTIONS_DICT = json.load(functions_json_file)
app = App(token=SLACK_BOT_TOKEN)
class ArticleSummarizer:
"""
äžããããã€ãã³ãã«åºã¥ããŠãèšäºã®ãµããªãŒãçæããé¢é£æ
å ±ãååŸã»æçš¿ããã¯ã©ã¹ã
"""
MAX_TOKENS = 20000
TOKEN_LIMIT = 16000
MESSAGE_TRUNCATE_LENGTH = 1000
def __init__(self, event, say, thread_ts=None):
"""
åæåã¡ãœãããã€ãã³ãæ
å ±ãåºã«ãé¢é£ãã屿§ãèšå®ããã
"""
def get_link(text):
pattern = "https?://[\w/:%#\$&\?\(\)~\.=\+\-]+"
return re.findall(pattern, text)
def get_title_from_url():
r = requests.get(self.url)
soup = BeautifulSoup(r.content, "html.parser")
return soup.find("title").text
self.event = event
self.say = say
self.thread_ts = thread_ts
self.url = get_link(event['text'])[0]
self.user = event['user']
self.title_origin = get_title_from_url()
self.title = ""
self.summary_json, self.ogp_image = self.generate_summary_from_url(self.url)
def handle_error(self, e):
"""
ãšã©ãŒãã³ããªã³ã°ãè¡ãããšã©ãŒã¡ãã»ãŒãžãéç¥ããã
"""
self.say(
f"Error occurred. Contact <{ADMIN_SLACK_ID}>:\n{traceback.format_exc()}")
print(f"Error occurred: {traceback.format_exc()}")
def generate_summary_from_url(self, url):
"""
URLãåŒæ°ã«åãããã®ã³ã³ãã³ããæœåºããŠèŠçŽãšã¿ã°ãçæããã
è¿ãå€: èŠçŽãšã¿ã°ã®jsonãªããžã§ã¯ããèšäºã®ã¿ã€ãã«ãogpç»åã
"""
def extract_content_from_url(url):
"""URLããã³ã³ãã³ããšã¿ã€ãã«ãæœåºãããã«ããŒé¢æ°"""
res = requests.get(url)
html = res.text
extractor = ExtractContent()
opt = {"threshold": 0}
extractor.set_option(opt)
extractor.analyse(html)
text, _ = extractor.as_text()
soup = BeautifulSoup(html, "html.parser")
title = soup.find("title").text
return text, title, soup
def extract_ogp_image(soup):
"""OGPç»åãæœåºãããã«ããŒé¢æ°"""
og_image_elems = soup.select('[property="og:image"]')
for og_image_elem in og_image_elems:
return og_image_elem.get("content")
return None
def get_tag_existing_list():
notion = Client(auth=NOTION_APP_TOKEN)
db = notion.databases.query(
**{
'database_id': NOTION_DATABASE_ID # ããŒã¿ããŒã¹ID
}
)
tag_existing_list = []
for i in db["results"]:
for j in i["properties"]["ã¿ã°"]['multi_select']:
tag_existing_list.append(j["name"])
tag_existing_list = list(set(tag_existing_list))
return tag_existing_list
text, title, soup = extract_content_from_url(url)
ogp_image = extract_ogp_image(soup)
# æ¢åã®ã¿ã°ãæœåº
tag_existing_list = get_tag_existing_list()
# GPT-3.5-turboãåŒã³åºããŠèŠçŽãšã¿ã°ãçæ
tag_attention_str = "ã¿ã°ã®äŸã¯ä»¥äžã§ããã¿ã°ã®åæ°ã¯5å以äžã§ãé¡ãããããŸãã" + \
''.join("\n- " + i for i in tag_existing_list)
tokens_count = self.MAX_TOKENS
while tokens_count >= self.TOKEN_LIMIT:
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "assistant", "content": f"ãTitleã{title}\n###\n{text}"},
{"role": "user", "content": f"ãã®èšäºã®å
容ã«ã€ããŠãæè¡çãªèŠç¹ã§èŠçŽãšã¿ã°ä»ããããŠãã ããã{tag_attention_str}\nlang:ja"},
]
messages_txt = ''.join(message["content"] for message in messages)
encoding: Encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
tokens = encoding.encode(messages_txt)
tokens_count = len(tokens)
text = text[:-self.MESSAGE_TRUNCATE_LENGTH]
functions = [FUNCTIONS_DICT]
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-16k",
temperature=0.0,
messages=messages,
functions=functions,
function_call={"name": "i_am_json"},
)
message = response["choices"][0]["message"]
return json.loads(message["function_call"]["arguments"]), ogp_image
def generate_and_send_summary(self):
"""
ãµããªãŒãšé¢é£æ
å ±ãååŸããã¬ã¹ãã³ã¹ãšããŠæçš¿ããã¡ã€ã³ã¡ãœããã
"""
try:
summaries, tag_str, category_name, notion_url = self.prepare_summary()
self.send_summary_to_slack(summaries, tag_str, category_name, notion_url)
except Exception as e:
# ã©ããã§ã³ã±ãããšã©ãŒåŠçãã
self.handle_error(e)
def prepare_summary(self):
"""
ãµããªãŒãšé¢é£æ
å ±ãæºåãããOGPç»åã®èšå®ããµããªãŒã®çæãã«ããŽãªãŒã®å€å®ãNotionãžã®æ¿å
¥ãè¡ãã
"""
def judge_category(text):
"""
äžããããããã¹ããããæãé¢é£æ§ãé«ãã«ããŽãªãŒã決å®ããã
"""
def calculate_category_score(category_words):
# ã«ããŽãªãŒã®åèªãªã¹ããåºã«ãããã¹ããšã®é¢é£æ§ã¹ã³ã¢ãèšç®ããã
return sum(word_score for word, word_score in category_words.items() if word in text)
categories_scores = {
category_name: calculate_category_score(category_data["word_dict"])
for category_name, category_data in CATEGORY_DICT.items()
}
return max(categories_scores, key=categories_scores.get, default="12.ãã®ä»")
def make_summary_tag():
# ãµããªãŒã®äœæ
summaries = "\n".join(
"⢠" + (self.summary_json["summary"][f"summary{i+1}"][:125] + "(以äžç¥)" if len(self.summary_json["summary"][f"summary{i+1}"]) >= 125 else self.summary_json["summary"][f"summary{i+1}"])
for i in range(5) if f"summary{i+1}" in self.summary_json["summary"]
)
# ã¿ã°listã®äœæ
tag_list = []
for tag_data in self.summary_json["tags"]:
tag = tag_data["tag"] if isinstance(tag_data, dict) else tag_data
tag_list.append({"name": tag})
tag_str = " / ".join([tag["name"] for tag in tag_list])
return summaries, tag_str, tag_list
def insert_notion_database(summaries, tag_list, category_name):
ogp_image = self.ogp_image
if "https://qiita-user-contents.imgix.net" in self.ogp_image:
ogp_image = self.ogp_image.replace("%", "%25")
notion = Client(auth=os.environ['NOTION_APP_TOKEN'])
response = notion.pages.create(
**{
'parent': {'database_id': NOTION_DATABASE_ID},
'properties': {
'åå': {'title': [{'text': {'content': self.title}}]},
'èŠçŽ': {'rich_text': [{'text': {'content': summaries}}]},
'URL': {'url': self.url},
'ã¿ã°': {'multi_select': tag_list},
'ã«ããŽãª': {"select": {"name": category_name}},
},
"children": [
{
"object": 'block',
"type": 'image',
"image": {"type": "external", "external": {"url": ogp_image}}
}
]
}
)
notion_url = response["url"]
return summaries, notion_url
if self.ogp_image is None:
self.ogp_image = DEFAULT_OGP_IMAGE
summaries, tag_str, tag_list = make_summary_tag()
category_name = judge_category(self.title + "\n" + summaries + "\n" + tag_str)
summaries, notion_url = insert_notion_database(summaries, tag_list, category_name)
return summaries, tag_str, category_name, notion_url
def send_summary_to_slack(self, summaries, tag_str, category_name, notion_url):
"""
çæããããµããªãŒãšé¢é£æ
å ±ãåºã«ãã¬ã¹ãã³ã¹ã¡ãã»ãŒãžãäœæããŠæçš¿ããã
"""
self.title = f"<{self.url}|*{self.title_origin}*> "
tag_str = f"*[ã¿ã°]* {tag_str} "
summaries = f"```{summaries}```"
text_notion = f":notion: <{notion_url}|èšäº>ã<https://www.notion.so/{NOTION_DATABASE_URL}|ãŸãšã>"
if self.thread_ts is None:
# DMã§è¿ä¿¡
self.say(self.title + "\n" + summaries + "\n" + tag_str + "\n`" + category_name + "`\n" + text_notion)
# ãã£ã³ãã«ã«æçš¿
self.send_message_to_channel(
summaries, tag_str, category_name, text_notion, self.user, self.ogp_image)
def send_message_to_channel(self, text_summary, text_tag, text_category, text_notion, user, ogp_image, thread_ts=None):
"""
Slackã®ç¹å®ã®ãã£ã³ãã«ã«ã¡ãã»ãŒãžãéä¿¡ããã
"""
def send_message(client, text_title, attachments, thread_ts=None):
"""Slackãžã®ã¡ãã»ãŒãžã®æçš¿ãå©ãããã«ããŒé¢æ°"""
params = {
"text": text_title,
"channel": TECH_RANDOM_CH_NAME,
"attachments": attachments
}
if thread_ts:
params["thread_ts"] = thread_ts
response = client.chat_postMessage(**params)
return response
attachments_0 = [
{
"color": CATEGORY_DICT[text_category]["color"],
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": self.title+"\n"+text_tag
},
"accessory": {
"type": "image",
"image_url": ogp_image,
"alt_text": "ogp_image"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": f"{text_notion} by <@{user}> `{text_category}`"
}
]
}
]
}
]
attachments_1 = [
{
"color": CATEGORY_DICT[text_category]["color"],
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": text_summary
}
}
]
}
]
client = WebClient(os.environ["SLACK_BOT_TOKEN"])
if thread_ts is None:
response = send_message(client, None, attachments_0)
send_message(client,self.title_origin, attachments_1, response["ts"])
else:
send_message(client, None,attachments_0, thread_ts)
send_message(client, self.title_origin, attachments_1, thread_ts)
@app.message("") # DMã§ãªã³ã¯ãéããããšãã®ãã³ãã©
def reply_message(event, say):
if event['channel_type'] == "im":
asc = ArticleSummarizer(event, say)
asc.generate_and_send_summary()
@app.event("app_mention")
def reply_mention(event, say):
thread_ts = event["ts"]
if event["channel"] == TECH_RANDOM_CH_ID:
asc = ArticleSummarizer(event, say, thread_ts)
asc.generate_and_send_summary()
@app.event("message")
def handle_message_events(body, logger):
logger.info(body)
SocketModeHandler(app, SLACK_APP_TOKEN).start()
ãã®ä»ã®ã³ãŒã
SLACK_BOT_TOKEN="xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"
SLACK_APP_TOKEN="xapp-1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NOTION_APP_TOKEN="secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NOTION_DATABASE_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NOTION_DATABASE_URL="https://www.notion.so/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ADMIN_SLACK_ID="@U0XXXXXXXXX"
DEFAULT_OGP_IMAGE="https://xxxxxxxxxxxx.jpg"
TECH_RANDOM_CH_ID="C0XXXXXXXXX"
以äžã¯ãèšäºã®ã«ããŽãªåããããããã®ç¹æ°ã®èšå®ã®jsonã§ãã
èå³ã®ããåéããšã«åèªãšç¹æ°ãèšå®ããã¯ãŒããããã³ã°ã§ã¹ã³ã¢ãèšç®ããåèšç¹ãæãé«ãã£ãã«ããŽãªãèšå®ããŠããŸãã(æ£çŽããªãã¢ããã°ã§ã)
ã¡ãªã¿ã«ããã®åèªã®åæã¯ChatGPTå çã«ãã£ãŠããããŸããããhttps://chat.openai.com/share/274f788a-a1ea-410a-89f6-36815b61ee58
{
"11.æè¡ãšç€ŸäŒ": {
"color": "#F3A9A4",
"word_dict": {
"åœæ
å ±å¯Ÿç": 100,
"èªæ²»äœæ¥å": 70,
"瀟äŒ": 90,
"æ¿ç": 80,
"æ¿æ²»": 85,
"ããžã¿ã«ããã€ã": 60,
"ãã¯ãããžãŒã€ãŒãµãªãšã³ã": 65,
"ããŒã¿ãã©ã€ãã·ãŒ": 75,
"AIå«ç": 80
}
},
"10.æ
å ±ãšç¥è": {
"color": "#F3D1A4",
"word_dict": {
"ã¡ã³ã¿ã«ããã": 90,
"ç¥èå®ç": 100,
"æè²": 95,
"ã¢ãŠãããã": 70,
"æ
å ±ç§åŠ": 85,
"ã³ã³ãã³ãã«ã¬ãŒã·ã§ã³": 75,
"ç¥èã°ã©ã": 80,
"èªç¥å¿çåŠ": 60,
"ããã¥ã¡ã³ã": 45
}
},
"09.ãã¶ã€ã³ãšUX": {
"color": "#EEF3A4",
"word_dict": {
"ããã³ããšã³ã": 40,
"UX": 100,
"UI": 50,
"ãã¶ã€ã³": 55,
"Figma": 80,
"CSS": 85,
"ãŠãŒã¶ãŒã¬ã€ã¢ãŠã": 70,
"ã³ã³ããŒãã³ã": 75,
"ã¯ã€ã€ãŒãã¬ãŒã ": 65,
"ãããã¿ã€ãã³ã°": 60,
"ããã¬ãŒã ã¯ãŒã¯": 30
}
},
"08.ããŒã¿åæãšããŒã¿ãµã€ãšã³ã¹": {
"color": "#C7F3A4",
"word_dict": {
"ããŒã¿ãµã€ãšã³ãã£ã¹ã": 90,
"ææ
åé¡": 70,
"ããŒã¿åæ": 100,
"å¯èŠå": 75,
"ããŒã¿ãµã€ãšã³ã¹": 95,
"èªç¶èšèªåŠç": 85,
"æ°å€è§£æ": 65,
"ããã¹ãåæ": 80,
"ããã°ããŒã¿": 60,
"ã¯ã©ã¹ã¿ãªã³ã°": 55,
"çµ±èšåŠ": 80,
"ç¹åŸŽé": 70,
"ãã·ã³ã©ãŒãã³ã°": 90
}
},
"07.ãœãããŠã§ã¢éçºãšãããžã§ã¯ã管ç": {
"color": "#A4F3A9",
"word_dict": {
"ãœãããŠã§ã¢": 90,
"ãããžã§ã¯ã": 85,
"æè¡çè² åµ": 70,
"ãããžã¡ã³ã": 80,
"éçº": 50,
"ã¬ã¬ã·ãŒã³ãŒã": 60,
"ã³ãã¥ãã±ãŒã·ã§ã³": 75,
"æé·": 65,
"è©äŸ¡": 55,
"SQL": 75,
"ã¢ãžã£ã€ã«": 70,
"ã¹ã¯ã©ã ": 65,
"DevOps": 80,
"ãã¹ãé§åéçº": 60,
"ãªãã¡ã¯ã¿ãªã³ã°": 55
}
},
"06.ã»ãã¥ãªãã£": {
"color": "#A4F3D1",
"word_dict": {
"ã»ãã¥ãªãã£": 100,
"SSH": 70,
"æ»æ": 80,
"URLèšèš": 60,
"èªèšŒ": 85,
"ãªã¢ãŒãæ¥ç¶": 65,
"éµ": 55,
"æå·å": 90,
"ãããã³ã°": 75,
"ããŒãã¡ã¯ã¿èªèšŒ": 80,
"VPN": 70,
"ãã¡ã€ã¢ãŠã©ãŒã«": 60
}
},
"05.éçºç°å¢": {
"color": "#A4EEF3",
"word_dict": {
"Linux": 100,
"ç°å¢": 10,
"Ubuntu": 10,
"Windows": 10,
"Visual Studio Code": 80,
"Docker": 95,
"Dockerfile": 75,
"ã€ã¡ãŒãž": 70,
"ã³ã³ãã": 75,
"ä»®æ³å": 60,
"Docker Compose": 65,
"GitHub": 85,
"git": 80,
"CI/CD": 90,
"Jenkins": 70,
"ç°å¢å€æ°": 65,
"ã·ã§ã«ã¹ã¯ãªãã": 60,
"Git": 50
}
},
"04.ã¯ã©ãŠã": {
"color": "#A4C7F3",
"word_dict": {
"AWS": 100,
"GCP": 90,
"Azure": 90,
"ã¯ã©ãŠã": 95,
"EC2": 80,
"ãµãŒããŒã¬ã¹": 70,
"Lambda": 75,
"VPC": 65,
"S3": 80,
"ãã€ã¯ããµãŒãã¹": 70,
"ããŒããã©ã³ãµãŒ": 30
}
},
"03.AIãšæ©æ¢°åŠç¿": {
"color": "#A9A4F3",
"word_dict": {
"ChatGPT": 85,
"AI": 100,
"人工ç¥èœ": 95,
"æ©æ¢°åŠç¿": 90,
"ããã³ãã": 70,
"ãã€ãº": 75,
"ãã£ãŒãã©ãŒãã³ã°": 80,
"ãã¥ãŒã©ã«ãããã¯ãŒã¯": 75,
"匷ååŠç¿": 65,
"æåž«ããåŠç¿": 60,
"æåž«ãªãåŠç¿": 60,
"OpenAI": 40,
"LLM": 50,
"GPT": 15
}
},
"02.æé©åãšéåã³ã³ãã¥ãŒã¿": {
"color": "#D1A4F3",
"word_dict": {
"éåã³ã³ãã¥ãŒã¿": 100,
"æé©": 85,
"QUBO": 70,
"ã¢ããŒãªã³ã°": 75,
"éåã¢ã«ãŽãªãºã ": 80,
"éåããã": 65,
"ã¹ãŒããŒããžã·ã§ã³": 60,
"éåãšã³ã¿ã³ã°ã«ã¡ã³ã": 55
}
},
"01.åå
«çª": {
"color": "#E4A4F3",
"word_dict": {
"API": 15,
"ã¢ã«ãŽãªãºã ": 15,
"ã³ãŒãã£ã³ã°": 15,
"Python": 100,
"REST": 80,
"flask": 70,
"ããã°ã©ãã³ã°": 95,
"æè¡": 90,
"Slack": 65,
"ã³ãŒã": 10
}
},
"12.ãã®ä»": {
"color": "#E8E8E8",
"word_dict": {
"â¢": 10
}
}
}
以äžã¯ãFunction callingãããéã«ChatGPTã«æããéã®æç€ºæžã§ããjsonã§ãã
{
"name": "i_am_json",
"description": "èŠçŽã®çæãšãã¿ã°ä»ããè¡ããŸãã",
"parameters": {
"type": "object",
"properties": {
"summary": {
"type": "object",
"description": "4ã€ã®æç« ã§æ§æãããèŠçŽã§ã",
"properties": {
"summary1": {
"type": "string",
"description": "ç®æ¡æžãã§æ§æãããèŠçŽæã®1æç®ã§ãã"
},
"summary2": {
"type": "string",
"description": "ç®æ¡æžãã§æ§æãããèŠçŽæã®2æç®ã§ãã"
},
"summary3": {
"type": "string",
"description": "ç®æ¡æžãã§æ§æãããèŠçŽæã®3æç®ã§ãã"
},
"summary4": {
"type": "string",
"description": "ç®æ¡æžãã§æ§æãããèŠçŽæã®3æç®ã§ãã"
}
}
},
"tags": {
"type": "array",
"description": "æè¡blogã«æçš¿ããéã«èšå®ãããã¿ã°ã§ããåæ°ã¯5ã€ä»¥äžã§ã",
"maxItems": 5,
"minItems": 1,
"items": {
"type": "object",
"properties": {
"tag": {
"description": "æè¡blogã«æçš¿ããéã®ã¿ã°ã®ã²ãšã€ã§ãã",
"type": "string"
}
}
}
}
}
}
}
è¿ã£ãŠããjsonã®äŸ
{
"role": "assistant",
"content": null,
"function_call": {
"name": "i_am_json",
"arguments": "{\n \"summary\": {\n \"summary1\": \"VS Codeæ¡åŒµæ©èœã䜿çšããŠãã¯ãŒã¯ã¹ããŒã¹å
ã®ãã¹ãŠã®CãããããŒãã¡ã€ã«ã«42headerã远å ããæ¹æ³ã玹ä»\",\n \"summary2\": \"VS Codeã®æ¡åŒµæ©èœéçºã®æé ãAPIã®æŽ»çšæ¹æ³ã«ã€ããŠè§£èª¬\",\n \"summary3\": \"ãã«ãã¯ãŒã¯ã¹ããŒã¹çšã®äŸ¿å©ãªAPIãNode.jsã®fsã¢ãžã¥ãŒã«ã®ä»£æ¿æ¹æ³ã«ã€ããŠèª¬æ\",\n \"summary4\": \"Moment.jsã䜿çšããŠæ¥æã®åŠçãè¡ãã宿ããæ¡åŒµæ©èœãMarketplaceã«å
¬éããæé ã玹ä»\"\n },\n \"tags\": [\n {\"tag\": \"VS Codeæ¡åŒµæ©èœ\"},\n {\"tag\": \"éçºæé \"},\n {\"tag\": \"API掻çš\"},\n {\"tag\": \"Node.js\"},\n {\"tag\": \"Moment.js\"},\n {\"tag\": \"Marketplaceå
Ž\"}\n ]\n}"
}
}
çæ§ã®å£°
æ®æ®µãããã®botã䜿ã£ãŠããã ããŠããçæ§ã®å£°ã玹ä»ããŸãã

ããããšããæŽ»æ§åããããã䟿å©ããšãããæèŠãå€ãããã£ãŠããŠãå®éã«ãã®botã®å°å
¥åŸã«ç€Ÿå
ã®ã³ãã¥ãã±ãŒã·ã§ã³ã掻çºåããŠããã®ãèã§æããããšãå€ããç§ãšããŠã¯æç¡éã®æ°æã¡ã§ãã
ä¿å®ç¥ã¯ã¡ããã£ãšæãå€ãããªïŒïœ(å§ãæãã)
ä»åŸã®å±éãšããŠæŽãªãã³ãã¥ãã±ãŒã·ã§ã³ã®å éãèããŠããŸãã
å ·äœçã«ã¯ã
- æè¡èšäºã ãã§ãªãäºæ¥ã«é¢ããèšäºã«ã€ããŠãåãä»ããŠãèŠçŽã®æçš¿å ãèªåã§å€å¥ãããã
- äœããã®åœ¢ã§èšäºããµãžã§ã¹ããã
- X(Twitter)ã§ããºã£ãŠããæè¡èšäºãååŸããŠæçš¿ãšãïŒ
- æè¡èšäºã®å 容ãåŠç¿ããŠæè¡ã³ã³ãµã«ã¿ã³ãã«ãªã£ãŠããã
ãªã©ãªã©ã
ãã²çæ§ã瀟å
Slackã«ãã®botãçãããŠã¿ãŠãã ããã
ãªã«ãã質åã»ãææã»ãããµã«ãªãããã°ãæ°è»œã«ã³ã¡ã³ããã ãã!!
Discussion