Skip to content

Commit 422c7ea

Browse files
authored
Merge pull request #187 from ut-code/generate-question-examples
geminiで質問例を事前作成
2 parents fbc0519 + aaa6538 commit 422c7ea

File tree

715 files changed

+3238
-289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

715 files changed

+3238
-289
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Generate Question Examples
2+
3+
on:
4+
pull_request:
5+
branches: [ "main" ]
6+
# paths:
7+
# - 'public/docs/**'
8+
9+
jobs:
10+
question-example:
11+
runs-on: ubuntu-latest
12+
# Push権限を付与
13+
permissions:
14+
contents: write
15+
16+
steps:
17+
- uses: actions/checkout@v6
18+
with:
19+
ref: ${{ github.head_ref }}
20+
- uses: actions/setup-node@v4
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
cache: 'npm'
24+
- run: npm ci
25+
26+
- run: npx tsx ./scripts/questionExample.ts 4
27+
env:
28+
API_KEY: ${{ secrets.API_KEY }}
29+
30+
- name: Commit and Push changes
31+
# 前のステップが成功・失敗どちらでも必ず実行
32+
if: always()
33+
run: |
34+
git config user.name "github-actions[bot]"
35+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
36+
git add .
37+
git diff --staged --exit-code || (git commit -m "[ci] generate question examples" && git push)

app/(docs)/@docs/[lang]/[pageId]/chatForm.tsx

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { useState, FormEvent, useEffect, useRef, useCallback } from "react";
3+
import { useState, FormEvent, useEffect, useRef, useCallback, useMemo } from "react";
44
// import useSWR from "swr";
55
// import {
66
// getQuestionExample,
@@ -26,8 +26,6 @@ export function ChatForm({ path, sectionContent, close }: ChatFormProps) {
2626
const [isLoading, setIsLoading] = useState(false);
2727
const [errorMessage, setErrorMessage] = useState<string | null>(null);
2828

29-
// const lang = getLanguageName(docs_id);
30-
3129
const { files, replOutputs, execResults } = useEmbedContext();
3230

3331
const router = useRouter();
@@ -64,42 +62,43 @@ export function ChatForm({ path, sectionContent, close }: ChatFormProps) {
6462
}
6563
}, [pathname]);
6664

67-
// const documentContentInView = sectionContent
68-
// .filter((s) => s.inView)
69-
// .map((s) => s.rawContent)
70-
// .join("\n\n");
71-
// const { data: exampleData, error: exampleError } = useSWR(
72-
// // 質問フォームを開いたときだけで良い
73-
// {
74-
// lang,
75-
// documentContent: documentContentInView,
76-
// } satisfies QuestionExampleParams,
77-
// getQuestionExample,
78-
// {
79-
// // リクエストは古くても構わないので1回でいい
80-
// revalidateIfStale: false,
81-
// revalidateOnFocus: false,
82-
// revalidateOnReconnect: false,
83-
// }
84-
// );
85-
// if (exampleError) {
86-
// console.error("Error getting question example:", exampleError);
87-
// }
65+
const exampleData = useMemo(
66+
() =>
67+
sectionContent
68+
.filter((s) => s.inView)
69+
.map((s) => s.question)
70+
.filter((qe) => qe !== undefined)
71+
.flat(),
72+
// eslint-disable-next-line react-hooks/exhaustive-deps
73+
[]
74+
);
8875
// 質問フォームを開くたびにランダムに選び直し、
8976
// exampleData[Math.floor(exampleChoice * exampleData.length)] を採用する
90-
const [exampleChoice, setExampleChoice] = useState<number>(0); // 0〜1
77+
const [exampleChoice, setExampleChoice] = useState<number | undefined>(
78+
undefined
79+
); // 0〜1
9180
useEffect(() => {
92-
if (exampleChoice === 0) {
81+
if (exampleChoice === undefined) {
9382
setExampleChoice(Math.random());
9483
}
9584
}, [exampleChoice]);
9685

9786
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
87+
88+
let userQuestion = inputValue;
89+
if (!userQuestion && exampleData.length > 0 && exampleChoice) {
90+
// 質問が空欄なら、質問例を使用
91+
userQuestion =
92+
exampleData[Math.floor(exampleChoice * exampleData.length)];
93+
setInputValue(userQuestion);
94+
}
95+
if (!userQuestion) {
96+
return;
97+
}
98+
9899
e.preventDefault();
99100
setIsLoading(true);
100-
setErrorMessage(null);
101-
102-
const userQuestion = inputValue;
101+
setErrorMessage(null); // Clear previous error message
103102

104103
let response: Response;
105104
try {
@@ -214,10 +213,10 @@ export function ChatForm({ path, sectionContent, close }: ChatFormProps) {
214213
<textarea
215214
className="textarea textarea-ghost textarea-md rounded-box bg-transparent!"
216215
placeholder={
217-
"質問を入力してください" /* +
218-
(exampleData
216+
"質問を入力してください" +
217+
(exampleData.length > 0 && exampleChoice !== undefined
219218
? ` (例:「${exampleData[Math.floor(exampleChoice * exampleData.length)]}」)`
220-
: "")*/
219+
: "")
221220
}
222221
style={{
223222
width: "100%",

app/actions/questionExample.ts

Lines changed: 0 additions & 42 deletions
This file was deleted.

app/lib/docs.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,26 @@ export interface PagePath {
3030
page: PageSlug;
3131
}
3232

33-
export const MarkdownSectionSchema = z.object({
34-
/**
35-
* セクションのmdファイル名
36-
*/
37-
file: z.string(),
33+
export const SectionFrontMatterSchema = z.object({
3834
/**
3935
* frontmatterに書くセクションid
4036
* (データベース上の sectionId)
4137
*/
4238
id: z.string().transform((s) => s as SectionId),
4339
level: z.number(),
4440
title: z.string(),
41+
/**
42+
* そのセクションに対する質問例
43+
* scripts/questionExample.ts で生成する
44+
*/
45+
question: z.array(z.string()).optional(),
46+
});
47+
export type SectionFrontMatter = z.output<typeof SectionFrontMatterSchema>;
48+
export const MarkdownSectionSchema = SectionFrontMatterSchema.extend({
49+
/**
50+
* セクションのmdファイル名
51+
*/
52+
file: z.string(),
4553
/**
4654
* frontmatterを除く、見出しも含めたもとのmarkdownの内容
4755
*/
@@ -304,11 +312,7 @@ function parseFrontmatter(content: string, file: string): MarkdownSection {
304312
if (endIdx === -1) {
305313
throw new Error(`File ${file} has invalid frontmatter`);
306314
}
307-
const fm = yaml.load(content.slice(4, endIdx)) as {
308-
id: SectionId;
309-
title: string;
310-
level: number;
311-
};
315+
const fm = yaml.load(content.slice(4, endIdx)) as SectionFrontMatter;
312316
// TODO: validation of frontmatter using zod
313317
// replコードブロックにはセクションidをターミナルidとして与える。
314318
const rawContent = content
@@ -319,6 +323,7 @@ function parseFrontmatter(content: string, file: string): MarkdownSection {
319323
id: fm.id,
320324
title: fm.title,
321325
level: fm.level,
326+
question: fm.question,
322327
rawContent,
323328
md5: crypto.createHash("md5").update(rawContent).digest("base64"),
324329
};
File renamed without changes.

public/docs/cpp/0-intro/1-0-about.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
id: cpp-intro-about
33
title: C++とは?
44
level: 2
5+
question:
6+
- C++はC言語を拡張したとありますが、C言語とは何が違うのですか?
7+
- パワフルで汎用性が高いとは、具体的にどのような意味ですか?
58
---
69

710
## C++とは?

public/docs/cpp/0-intro/1-1-feature.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
id: cpp-intro-feature
33
title: 特徴
44
level: 3
5+
question:
6+
- 低レベルな操作とは具体的に何を指しますか?
7+
- 静的型付けの反対は動的型付けですか?それらの違いは何ですか?
8+
- マルチパラダイムとは、複数のプログラミングスタイルを自由に選べるということですか?
9+
- オブジェクト指向プログラミングやジェネリックプログラミングとは何ですか?
510
---
611

712
### 特徴

public/docs/cpp/0-intro/1-2-usage.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
id: cpp-intro-usage
33
title: C++が使われる分野
44
level: 3
5+
question:
6+
- 組み込みシステムでリソースが限られているとはどういう意味ですか?
57
---
68

79
### C++が使われる分野

public/docs/cpp/0-intro/2-0-env-about.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
id: cpp-intro-env-about
33
title: 開発環境のセットアップ
44
level: 2
5+
question:
6+
- コンパイラがないとプログラムは実行できないのですか?
7+
- ソースコードと機械語の違いは何ですか?
58
---
69

710
## 開発環境のセットアップ

public/docs/cpp/0-intro/2-1-ide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
id: cpp-intro-ide
33
title: コンパイラとIDE
44
level: 3
5+
question:
6+
- 複数のコンパイラがありますが、どれを使えば良いですか?
7+
- IDEとエディタは同じものですか?それとも違いがありますか?
8+
- Visual StudioとVisual Studio Codeは、名前が似ていますが何が違いますか?
9+
- エラーメッセージが分かりやすいClangは初心者におすすめですか?
510
---
611

712
### コンパイラとIDE

0 commit comments

Comments
 (0)