Skip to content

Instantly share code, notes, and snippets.

@ryo-rm
Created June 21, 2023 09:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryo-rm/55bd812f7858f3e871b7bf1ecda414d7 to your computer and use it in GitHub Desktop.
Save ryo-rm/55bd812f7858f3e871b7bf1ecda414d7 to your computer and use it in GitHub Desktop.
ESMで動作確認用の画面を作るやつ
from flask import (
Flask,
request,
)
app = Flask(__name__)
@app.route("/chat", methods=["POST"])
def chat_post():
args = request.json
question = args["question"]
id = args["id"]
# 適当な回答を返す
return {"id": id, "message": f"{question}って何?"}
@app.route("/chat", methods=["GET"])
def chat_get():
return """
<html>
<head>
<title>Chat</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import {
html,
render,
useState,
useReducer,
} from "https://esm.sh/htm/preact/standalone";
function App() {
const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case "INPUT_QUESTION": {
return {
...state,
question: action.payload.question,
};
}
case "SUCCESS": {
const next = state.messages.slice(0, -1);
return {
...state,
id: action.payload.id,
question: "",
messages: [
...next,
{
content: action.payload.message,
user: "system",
}
],
submitting: false,
error: null,
};
}
case "SUBMIT": {
return {
...state,
messages: [
...state.messages,
{
content: action.payload.question,
user: "user",
},
{
content: "質問を送信しています...",
user: "system",
}
],
submitting: true,
error: null,
};
}
case "ERROR": {
const next = state.messages.slice(0, -1);
return {
...state,
submitting: false,
error: action.payload.error,
messages: [
...next,
{
content: action.payload.error,
user: "system",
}
],
};
}
default:
return state;
}
},
{
id: "",
messages: [],
submitting: false,
question: "",
error: null,
}
);
const sendQuestion = async () => {
if (state.submitting) {
return;
}
if (!state.question) {
dispatch({
type: "ERROR",
payload: {
error: "質問を入力してください",
},
});
return;
}
dispatch({
type: "SUBMIT",
payload: {
question: state.question,
},
});
const response = await fetch("/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
question: state.question,
id: state.id,
}),
});
if (response.ok) {
const json = await response.json();
dispatch({
type: "SUCCESS",
payload: {
id: json.id,
message: json.message,
},
});
} else {
dispatch({
type: "ERROR",
payload: {
error: response.statusText,
},
});
}
};
return html`
<div>
<div>${state.error}</div>
<div>${state.messages.map((message) => html`<div
style=${{
whiteSpace: "pre-wrap",
wordBreak: "break-all",
maxWidth: "70%",
textAlign: message.user === "system" ? "left" : "right",
marginLeft: message.user === "system" ? "0" : "auto",
marginRight: message.user === "system" ? "auto" : "0",
}}
>
${message.content}</div>
`)}</div>
<div>
<input
type="text"
value=${state.question}
onInput=${(e) => dispatch({ type: "INPUT_QUESTION", payload: { question: e.target.value } })}
/>
<button onClick=${sendQuestion} disabled=${state.submitting}>${state.submitting ? "送信中" : "送信"}</button>
</div>
</div>
`;
}
render(html`<${App} name="App" />`, document.getElementById("app"));
</script>
</body>
</html>
"""
if __name__ == "__main__":
print("start")
app.run(debug=True, host="0.0.0.0", port=3000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment