Skip to content

Commit cfe3f21

Browse files
authoredFeb 22, 2025
Merge pull request #140 from kc3hack/yone/develop
システムプロンプト修正 拗音(ゃゅょ)は1音として扱わない
2 parents 4c94349 + 8480708 commit cfe3f21

File tree

9 files changed

+262
-3
lines changed

9 files changed

+262
-3
lines changed
 

‎backend/.env.example

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ S3_ACCESS_KEY_ID=
1414
S3_SECRET_ACCESS_KEY=
1515
S3_BUCKET_NAME=
1616

17-
OUR_ID=
17+
CURRENTS_API_KEY=
18+
NEWS_POST_API_KEY=
19+
OUR_ID=

‎backend/src/config/env.ts

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const envSchema = z.object({
88
FRONTEND_URL: z.string().url(),
99
PORT: z.coerce.number().optional(),
1010
GEMINI_API_KEY: z.string(),
11+
CURRENTS_API_KEY: z.string(),
12+
NEWS_POST_API_KEY: z.string(),
13+
NEWS_USER_ID: z.string(),
1114
RDB_HOST: z.string(),
1215
RDB_USER: z.string(),
1316
RDB_PASSWORD: z.string(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { z, type RouteHandler } from '@hono/zod-openapi';
2+
import type { Context } from 'hono';
3+
import { sampleNewsTankaSchema } from '../../schema/Sample/sampleNewsTankaSchema.js';
4+
import type { sampleNewsTankaRoute } from '../../routes/Sample/sampleNewsTankaRoute.js';
5+
import postNews from '../../lib/postNews.js';
6+
7+
type sampleNewsTankaSchema = z.infer<typeof sampleNewsTankaSchema>;
8+
9+
const sampleNewsTankaHandler: RouteHandler<typeof sampleNewsTankaRoute, {}> = async (
10+
c: Context
11+
) => {
12+
const { apiKey } = await c.req.json<sampleNewsTankaSchema>();
13+
14+
/* --- 色々処理 --- */
15+
16+
const response = await postNews(apiKey);
17+
console.log(response);
18+
19+
// レスポンス
20+
return c.json(response, 200);
21+
};
22+
23+
export default sampleNewsTankaHandler;

‎backend/src/lib/gemini.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const generateTanka = async (originalText: string): Promise<any> => {
106106
1. **五七五七七の形式厳守:** **読み(yomi0~yomi4)をカタカナに変換した上で**、五七五七七の音数になるように調整してください。字余りや字足らずは許されません。
107107
* **特にアルファベットや記号は、カタカナ読みに変換した上で音数を数えてください。** 例:「AI」→「エーアイ」(4音)
108108
* どうしても正確な音数に変換できない場合は、近い音に置き換える、または、前後の句で調整するなど、**短歌全体として五七五七七になるように工夫してください。**
109-
* 長音(ー)、促音(っ)、拗音(ゃゅょ)は1音として扱う
109+
* 長音(ー)、促音(っ)は1音として扱いますが、拗音(ゃゅょ)は1音として扱いません
110110
2. **面白さとユニークさの追求:**
111111
* **原投稿の要素を活かす:** 投稿内容のキーワード、感情、状況などを取り入れつつ、予想外の展開や表現につなげてください。
112112
* **言葉遊び:** 同音異義語、掛詞、比喩などを積極的に活用し、言葉の面白さを引き出してください。

‎backend/src/lib/getNews.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { Context } from 'hono';
2+
import { env } from '../config/env.js';
3+
4+
const printLine = (): void => {
5+
console.log('--------------------------------');
6+
};
7+
8+
const getNews = async () => {
9+
try {
10+
const response = await fetch(
11+
`https://api.currentsapi.services/v1/latest-news?language=ja&apiKey=${env.CURRENTS_API_KEY}`
12+
);
13+
14+
// HTTPエラーが発生した場合
15+
if (!response.ok) {
16+
throw new Error(`HTTPエラー: ${response.status}`);
17+
}
18+
19+
const data = await response.json();
20+
21+
console.log(data);
22+
23+
// ニュースの取得に失敗した場合
24+
if (data.status !== 'ok') {
25+
throw new Error('ニュースの取得に失敗しました。');
26+
}
27+
28+
const newsArray = data.news;
29+
30+
let news;
31+
for (let i = 0; i < newsArray.length; i++) {
32+
const newsTemp = newsArray[i];
33+
if (newsTemp.title !== '' && newsTemp.description !== '' && newsTemp.url !== '') {
34+
news = newsTemp;
35+
break;
36+
}
37+
}
38+
39+
if (!news) {
40+
throw new Error('表示できるニュースがありません。');
41+
}
42+
return {
43+
isSuccess: true,
44+
news: {
45+
title: news.title,
46+
description: news.description,
47+
url: news.url,
48+
},
49+
};
50+
} catch (error: any) {
51+
console.error(error);
52+
return {
53+
isSuccess: false,
54+
message: error.message,
55+
};
56+
}
57+
};
58+
59+
export default getNews;

‎backend/src/lib/postNews.ts

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import type { Context } from 'hono';
2+
import { env } from '../config/env.js';
3+
import getNews from './getNews.js';
4+
import generateTanka from './gemini.js';
5+
import createPostHandler from '../controllers/Post/createPostHandler.js';
6+
7+
const printLine = (): void => {
8+
console.log('--------------------------------');
9+
};
10+
11+
const postNews = async (requestApiKey: string) => {
12+
if (requestApiKey !== env.NEWS_POST_API_KEY) {
13+
return {
14+
isSuccess: false,
15+
tanka: {
16+
line0: 'APIキーが間違っています',
17+
line1: '',
18+
line2: '',
19+
line3: '',
20+
line4: '',
21+
},
22+
};
23+
}
24+
25+
const newsResponse = await getNews();
26+
27+
// ニュースの取得に失敗した場合
28+
if (!newsResponse.isSuccess || !newsResponse.news) {
29+
return {
30+
isSuccess: false,
31+
tanka: {
32+
line0: 'ニュースの取得に失敗しました',
33+
line1: '',
34+
line2: '',
35+
line3: '',
36+
line4: '',
37+
},
38+
};
39+
}
40+
41+
const news = newsResponse.news;
42+
43+
// 投稿の原文
44+
const originalText = `${news.title}\n${news.description}\n${news.url}`;
45+
46+
console.log('originalText', originalText);
47+
48+
try {
49+
const formData = new FormData();
50+
formData.append('original', originalText);
51+
formData.append('user_icon', `https://avatars.githubusercontent.com/u/${env.NEWS_USER_ID}?v=4`);
52+
formData.append('user_name', '風聞');
53+
54+
const postResponse = await fetch(`http://localhost:8080/post`, {
55+
method: 'POST',
56+
body: formData,
57+
});
58+
59+
console.log('postResponse', postResponse);
60+
61+
if (!postResponse.ok) {
62+
return {
63+
isSuccess: false,
64+
tanka: {
65+
line0: '',
66+
line1: '',
67+
line2: '',
68+
line3: '',
69+
line4: '',
70+
},
71+
};
72+
}
73+
74+
const json = await postResponse.json();
75+
76+
return {
77+
isSuccess: true,
78+
tanka: json.tanka,
79+
};
80+
} catch (error) {
81+
console.error(error);
82+
return {
83+
isSuccess: false,
84+
tanka: {
85+
line0: '投稿に失敗しました',
86+
line1: '',
87+
line2: '',
88+
line3: '',
89+
line4: '',
90+
},
91+
};
92+
}
93+
};
94+
95+
export default postNews;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { z } from '@hono/zod-openapi';
2+
import { createRoute } from '@hono/zod-openapi';
3+
import {
4+
sampleNewsTankaResponseSchema,
5+
sampleNewsTankaSchema,
6+
} from '../../schema/Sample/sampleNewsTankaSchema.js';
7+
import { errorResponseSchema } from '../../middleware/errorHandler.js';
8+
9+
type sampleNewsTankaSchema = z.infer<typeof sampleNewsTankaSchema>;
10+
11+
export const sampleNewsTankaRoute = createRoute({
12+
method: 'post',
13+
path: '/sample/news',
14+
tags: ['sample'],
15+
request: {
16+
body: {
17+
required: true,
18+
content: {
19+
'application/json': {
20+
schema: sampleNewsTankaSchema,
21+
},
22+
},
23+
},
24+
},
25+
responses: {
26+
200: {
27+
content: {
28+
'application/json': {
29+
schema: sampleNewsTankaResponseSchema,
30+
},
31+
},
32+
description: 'Successful response',
33+
},
34+
},
35+
});
36+
37+
export type SampleNewsTankaRouteResponse200 = z.infer<
38+
(typeof sampleNewsTankaRoute.responses)['200']['content']['application/json']['schema']
39+
>;
40+
41+
export type SampleNewsTankaRouteResponseError = z.infer<typeof errorResponseSchema>;

‎backend/src/routes/route.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import { sampleS3DownloadRoute } from './sampleS3Route.js';
2929
import sampleS3DownloadHandler from '../controllers/sampleS3DownloadHandler.js';
3030
import { sampleGeminiRoute } from './Sample/sampleGeminiRoute.js';
3131
import sampleGeminiHandler from '../controllers/Sample/sampleGeminiHandler.js';
32+
import { sampleNewsTankaRoute } from './Sample/sampleNewsTankaRoute.js';
33+
import sampleNewsTankaHandler from '../controllers/Sample/sampleNewsTankaHandler.js';
3234

3335
const router = new OpenAPIHono();
3436

@@ -47,5 +49,6 @@ export default router
4749
.openapi(isOurAccountRoute, isOurAccountHandler)
4850
.openapi(sampleS3UploadRoute, sampleS3UploadHandler)
4951
.openapi(sampleS3DownloadRoute, sampleS3DownloadHandler)
50-
.openapi(sampleGeminiRoute, sampleGeminiHandler);
52+
.openapi(sampleGeminiRoute, sampleGeminiHandler)
53+
.openapi(sampleNewsTankaRoute, sampleNewsTankaHandler);
5154
// .openapi(helloRoute, helloWorldHandler); //こういう感じで足していく
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { z } from '@hono/zod-openapi';
2+
3+
export const sampleNewsTankaSchema = z.object({
4+
apiKey: z.string().openapi({
5+
example: 'abc123',
6+
description: 'APIキー',
7+
}),
8+
});
9+
10+
export const sampleNewsTankaResponseSchema = z.object({
11+
isSuccess: z.boolean().openapi({
12+
example: true,
13+
description: '短歌の生成に成功したかどうか',
14+
}),
15+
tanka: z
16+
.object({
17+
line0: z.string(),
18+
line1: z.string(),
19+
line2: z.string(),
20+
line3: z.string(),
21+
line4: z.string(),
22+
})
23+
.openapi({
24+
example: {
25+
line0: '巷説の',
26+
line1: '風の便りと',
27+
line2: '聞きなして',
28+
line3: '都の噂を',
29+
line4: '語り継がんか',
30+
},
31+
description: 'ニュースを取得し、短歌にした結果',
32+
}),
33+
});

0 commit comments

Comments
 (0)
Failed to load comments.