๋ง์ฝ ์ด ์๋ฐ ๋ด์ ์ด์ฉํด ์ฌ๋์ด๋ ๋ ธ์ ์ด์ฉ๊ตฌ ๋ด์ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ํด๋น ์ค๋๊ณผ ๋ ธ์ ์ ์ถ๋ ฅ ํ์์ ๋ง๊ฒ ๊ณ ์ณ์ผ ํ๋ค. ๋๋ java ๋ด ๋ง ํ ๊ฒ์ด๋ค.
์๋ ๊ตฌ๊ธ api
์ด๋ ๊ฒ ๋ชจ๋ ๊ฒ์๋ api๊ฐ ์๋ค.
๊ทธ ์ค์์ ๋๋ ๊ทธ๋ก api๋ฅผ ์ธ ๊ฒ์ด๋ค.
๊ทธ๋กฏ ํํ
์์ ์ api keys๋ผ๋ ๊ณณ์์ apiํค๋ฅผ ๋ฐ์๋ค๊ฐ ์ด๋๊ฐ ์ ์ฅ์ ํด๋์๋ค๊ฐ.
๋ชจ๋ธ์ ์ ํํ๊ณ view code ๋ถ๋ถ์ ๋ค์ด๊ฐ์ ์ค์ ์ ํด์ค์ผ ํฉ๋๋ค.
๊ทธ๋ผ ์ฝ๋๊ฐ ๋์ค๋๋ฐ ๊ทธ๊ฒ์ ๊ธฐ์ตํด์ผํฉ๋๋ค.
gsk_xoYjD2j8JhXl -- LLM_API_KEY
curl "https://api.groq.com/openai/v1/chat/completions" -- LLM_API_URL \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${GROQ_API_KEY}" \
-d '{
"messages": [
{
"role": "user",
"content": " ๋ฉ๋กฑ"
},
{
"role": "assistant",
"content": "๋ฉ๋กฑ!์ ํ๊ตญ์์ ์ ๋ช
ํ ๋ฐฐ์ฐ์
๋๋ค. ๊ทธ์ ์ฐ๊ธฐ๋ ฅ๊ณผ ์นด๋ฆฌ์ค๋ง๋ก ๋ง์ ํฌ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๊ฐ ์ถ์ฐํ ๋๋ผ๋ง๋ ์ํ๋ฅผ ๋ณด์
จ๋์?"
}
],
"model": "llama-3.3-70b-versatile", -- LLM_MODEL
"temperature": 1,
"max_completion_tokens": 1024,
"top_p": 1,
"stream": true,
"stop": null
}'
์ด๋ ๊ฒ ๋์ต๋๋ค.
์ ๋ ๊ฒ ๋ถ๋ถ์ ํด๋นํ๋ ์ ๋ค์ ์๊ณ ์์ด์ผ ํฉ๋๋ค. ์ ๋ชจ๋ธ ์น๊ตฌ๋ ์ ํ๋กฌํํธ์ ๋ณธ๋ฌธ ๊ธ ์น๊ตฌ์
๋๋ค.
์ ์์๋ค๋ฉด ์ด์ ๊ทธ๋ฆผ ์น๊ตฌ๋ชจ๋ธ์ ๊ฐ์ ธ์ต๋๋ค.
ํฌ๊ฒ๋
457afd2f0c997b28 --LLM2_API_KEY
curl -X POST "https://api.together.xyz/v1/images/generations" --LLM2_API_URL
-H "Authorization: Bearer $TOGETHER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "black-forest-labs/FLUX.1-schnell-Free", --LLM2_MODEL
"prompt": "[]",
"width": 640,
"height": 640,
"steps": 4,
"n": 1,
"response_format": "b64_json"
}'
๋ญ ์ด๋ ๊ฒ ๊ฐ์ ธ์ต๋๋ค. ํด๋นํ๋ ๋ถ๋ถ์ ์ ๊ธฐ์ตํด ๋๋ค๊ฐ ์ด์
์๋๋ ์ธํ
๋ฆฌ j ๋ผ๋ ์ ํํ
์ ํด์ผํ๋๋ฐ ๊ท์ฐฎ์ผ๋ vscode์์ ํฉ๋๋ค.
์ด์ ํ์ผ๋ค์ .github ์๋์ ๋ง๋ญ๋๋ค. ์ฐ๋ฆฌ์ bot์ ๊นํ๋ธ์์ ๋๋ฆด ๊บผ๋๊น์.
๊นํ๋ธ์์๋ ์
ํ
์ฆ์์ secrets and variavles์ ๋ด ์์คํ key๋ค๊ณผ ์ฃผ์๋ค์ secrets์ variables์ ๋๋ ์ ์ ์ฅ์ ํด๋๋ค.
๋ญ.. ๋์ค์ ๋ฐ๋๋ ์ฐ์ ์ฒ๋ผ ๊บผ๋ด ๋์ธ์.
๋ง์๊ฒ ๋ค.
๋ฌดํผ
ํ์ผ์์ Send-message.yml ์ด๋ผ๋ ํ์ผ์ด ์๋๋ฐ
์ด๋ ๊ฒ ์ํฌ ํ๋ก์ฐ์ JavaBot์ด๋ผ๊ณ ๋์จ๋ค.
-----------------------------------------------------------------------------------------------------------------------------
on:
workflow_dispatch: # ์๋ ์คํ์ ํ์ฉ (GitHub์์ ์ง์ ์คํ ๊ฐ๋ฅ)
schedule:
- cron: '0 * * * *' # โฐ ๋งค ์ ๊ฐ(00๋ถ)์ ์คํ (์: 00:00, 01:00, 02:00 ...)
# ๐ก cron ํํ์: '0 * * * *'
# - ์ฒซ ๋ฒ์งธ ๊ฐ(0): ๋งค ์๊ฐ ์ ๊ฐ(00๋ถ)์ ์คํ
# - ๋ ๋ฒ์งธ ๊ฐ(*): ๋งค ์๊ฐ์ ์๋ฏธ
# - ๋๋จธ์ง ๊ฐ(* * *): ๋งค์ผ, ๋งค์, ์์ผ ๋ฌด๊ดํ๊ฒ ์คํ
# → ์ฆ, ๋งค 1์๊ฐ๋ง๋ค ์คํ๋จ.
jobs:
create-issue: # "create-issue"๋ผ๋ ์ด๋ฆ์ ์์ ์ ์
runs-on: ubuntu-latest # ์ต์ Ubuntu ํ๊ฒฝ์์ ์คํ
steps: # ์์ ๋จ๊ณ ์ ์
- name: Checkout Repository # ๐น ํ์ฌ GitHub ๋ฆฌํฌ์งํ ๋ฆฌ์ ์ฝ๋๋ฅผ ๊ฐ์ ธ์ด
uses: actions/checkout@v4 # GitHub์ ๊ณต์ checkout ์ก์ ์ฌ์ฉ (์ฝ๋ ๋ณต์ฌ)
- name: Setup Java 17 # ๐น Java 17 ํ๊ฒฝ์ ์ค์
uses: actions/setup-java@v4 # Java๋ฅผ ์ค์ ํ๋ GitHub ์ก์ ์ฌ์ฉ
with:
distribution: temurin # OpenJDK ๊ธฐ๋ฐ์ Temurin ๋ฐฐํฌํ ์ฌ์ฉ
java-version: '17' # Java ๋ฒ์ ์ 17๋ก ์ค์
# ๐ก ๋ง์ฝ ์ธํ ๋ฆฌ์ ์ด ๋ฑ์์ 23๋ฒ์ ์ผ๋ก ์ฌ๋ฆฌ๊ณ ์ถ๋ค๋ฉด ์ฌ๊ธฐ์ ์์ ๊ฐ๋ฅ
- name: Compile and Run Bot # ๐น JavaBot ์คํ
run: | # ์ฌ๋ฌ ๋ช ๋ น์ด๋ฅผ ์์ฐจ์ ์ผ๋ก ์คํ
javac JavaBot.java # Java ์์ค ํ์ผ(JavaBot.java)์ ์ปดํ์ผ
java JavaBot # ์ปดํ์ผ๋ Java ํ๋ก๊ทธ๋จ ์คํ
env: # ์คํ ํ๊ฒฝ ๋ณ์ ์ค์ (Java ํ๋ก๊ทธ๋จ ์คํ ์ ํ์ํ ๊ฐ๋ค)
GITHUB_TOKEN: ${{ secrets.GIT_TOKEN }} # GitHub API ์ธ์ฆ ํ ํฐ
GITHUB_REPO: ${{ vars.GIT_REPO }} # ์คํํ GitHub ๋ฆฌํฌ์งํ ๋ฆฌ ์ ๋ณด
LLM_API_URL: ${{ vars.LLM_API_URL }} # LLM API์ ๊ธฐ๋ณธ URL
LLM_API_KEY: ${{ secrets.LLM_API_KEY }} # LLM API์ ์ธ์ฆ ํค (๋ณด์ ์ ์ง ํ์)
LLM_MODEL: ${{ vars.LLM_MODEL }} # ์ฌ์ฉํ LLM ๋ชจ๋ธ ์ด๋ฆ
LLM2_API_URL: ${{ vars.LLM2_API_URL }} # ์ถ๊ฐ LLM API URL
LLM2_API_KEY: ${{ secrets.LLM2_API_KEY }} # ์ถ๊ฐ LLM API ์ธ์ฆ ํค
LLM2_MODEL: ${{ vars.LLM2_MODEL }} # ์ถ๊ฐ LLM ๋ชจ๋ธ ์ด๋ฆ
-----------------------------------------------------------------------------------------------------------------------------
๊ทธ๋ฆฌ๊ณ JavaBot.java๋ .github/workflows์ ๋ฐ์ ์์ด์ผํ๋ค.
---------------------------------------------------------------------------------------------------
// ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฌํธ
import java.net.URI; // URL์ ๋ค๋ฃจ๋ Java ํด๋์ค
import java.net.http.HttpClient; // HTTP ์์ฒญ์ ๋ณด๋ผ ๋ ์ฌ์ฉํ๋ ํด๋ผ์ด์ธํธ
import java.net.http.HttpRequest; // HTTP ์์ฒญ์ ์์ฑํ๋ ํด๋์ค
import java.net.http.HttpResponse; // HTTP ์๋ต์ ์ฒ๋ฆฌํ๋ ํด๋์ค
import java.nio.charset.StandardCharsets; // UTF-8 ๋ฑ์ ๋ฌธ์ ์ธ์ฝ๋ฉ์ ์ฌ์ฉํ๊ธฐ ์ํ ํจํค์ง
import java.util.regex.Matcher; // ์ ๊ท ํํ์์ ์ด์ฉํด ๋ฌธ์์ด์์ ์ํ๋ ํจํด์ ์ถ์ถํ๋ ํด๋์ค
import java.util.regex.Pattern; // ์ ๊ท ํํ์์ ์ ์ํ๋ ํด๋์ค
public class JavaBot { // JavaBot ํด๋์ค ์ ์ (๋ฉ์ธ ์คํ ํด๋์ค)
public static void main(String[] args) {
// ๐ข 1. LLM์ ์ด์ฉํ์ฌ ์๊ณ ๋ฆฌ์ฆ ์ถ์ฒ ๋ฐ๊ธฐ
String llmResult = useLLM("์๋ฐ ์๊ณ ๋ฆฌ์ฆ ์ค ๊ฐ๋ฐ์ ํ์
์์ ๋ง์ด ์ฌ์ฉ๋๋ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค์ผ๋ก ํ๋๋ฅผ ์ถ์ฒํ๊ณ ์ ํ์ํ์ง ์ฌ๋ก ์์ฃผ 1000์ ์ด๋ด๋ก ์์ฑ. ๋ณ๋์ ์๋ค ๋ด์ฉ ์์ด ํด๋น ๋ด์ฉ๋ง ์ถ๋ ฅ. nutshell, for slack message, in korean.");
System.out.println("llmResult = " + llmResult);
// ๐ข 2. LLM์ ์ด์ฉํ์ฌ ์ ๋ชฉ ์์ฝ ์์ฑ
String summarizedTitle = summarizeText(llmResult);
System.out.println("Summarized Title = " + summarizedTitle);
// ๐ข 3. LLM์ ์ด์ฉํด ์ด๋ฏธ์ง ์์ฑ
String image_url = useLLM2("A modern software development company's interior in Japanese manga style. The open office layout features a spacious and organized workspace where multiple developers are actively coding at their desks. Some are discussing ideas while looking at their monitors, while others are brainstorming on a whiteboard. The walls are adorned with various tech-related posters and whiteboards, and desks are cluttered with laptops, dual monitors, coffee cups, snacks, and figurines. The lighting is warm and inviting, creating a comfortable atmosphere. A cityscape can be seen through the windows. The characters are drawn in a vibrant Japanese anime style, exuding energy and liveliness.");
System.out.println("image url = " + image_url);
// ๐ข 4. GitHub Issue ์์ฑ
sendIssues(summarizedTitle, llmResult, image_url);
}
// ๐น LLM API๋ฅผ ํธ์ถํ๋ ๋ฉ์๋ (ํ
์คํธ ์์ฑ์ฉ)
public static String useLLM(String prompt) {
return callLLMApi(prompt);
}
// ๐น LLM API๋ฅผ ํธ์ถํ๋ ๋ฉ์๋ (์ด๋ฏธ์ง ์์ฑ์ฉ)
public static String useLLM2(String prompt) {
return callLLMApi2(prompt);
}
// ๐น LLM์ ์ด์ฉํด ํ
์คํธ ์์ฝ (10์ ์ด๋ด์ ์ ๋ชฉ ์์ฑ)
public static String summarizeText(String text) {
return callLLMApi("๋ค์ ๋ด์ฉ์ 10์ ๋ด์ธ์ ๊ฐ๊ฒฐํ ์ ๋ชฉ์ผ๋ก ์์ฝํด์ค. '" + text + "'");
}
// ๐น LLM API ํธ์ถ (ํ
์คํธ ๊ธฐ๋ฐ ์๋ต)
public static String callLLMApi(String prompt) {
String apiUrl = System.getenv("LLM_API_URL"); // LLM API์ URL ํ๊ฒฝ ๋ณ์
String apiKey = System.getenv("LLM_API_KEY"); // LLM API์ ์ธ์ฆ ํค
String model = System.getenv("LLM_MODEL"); // ์ฌ์ฉํ LLM ๋ชจ๋ธ
// API ์์ฒญ์ ์ํ JSON ํ์ด๋ก๋ ์์ฑ
String payload = """
{
"messages": [
{
"role": "user",
"content": "%s"
}
],
"model": "%s"
}
""".formatted(prompt, model);
HttpClient client = HttpClient.newHttpClient(); // HTTP ํด๋ผ์ด์ธํธ ์์ฑ
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiUrl)) // ์์ฒญํ API URL ์ค์
.header("Content-Type", "application/json") // JSON ์์ฒญ์์ ๋ช
์
.header("Authorization", "Bearer " + apiKey) // API ์ธ์ฆ ํค๋ ์ถ๊ฐ
.POST(HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8)) // POST ์์ฒญ
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("response.statusCode() = " + response.statusCode()); // HTTP ์ํ ์ฝ๋ ์ถ๋ ฅ
System.out.println("response.body() = " + response.body()); // ์๋ต ๋ณธ๋ฌธ ์ถ๋ ฅ
if (response.statusCode() == 200) {
return extractContent(response.body()); // ์ ๊ท์์ผ๋ก ์๋ต ๋ด์ฉ ์ถ์ถ
} else {
return "LLM API ์ค๋ฅ: " + response.statusCode();
}
} catch (Exception e) {
e.printStackTrace();
return "์์ธ ๋ฐ์: " + e.getMessage();
}
}
// ๐น LLM API ํธ์ถ (์ด๋ฏธ์ง ์์ฑ)
public static String callLLMApi2(String prompt) {
String apiUrl = System.getenv("LLM2_API_URL");
String apiKey = System.getenv("LLM2_API_KEY");
String model = System.getenv("LLM2_MODEL");
// API ์์ฒญ ํ์ด๋ก๋ (์ด๋ฏธ์ง ์์ฑ)
String payload = """
{
"prompt": "%s",
"model": "%s",
"width": 640,
"height": 640,
"steps": 4,
"n": 1
}
""".formatted(prompt, model);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiUrl))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(payload, StandardCharsets.UTF_8))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return extractImageUrl(response.body());
} else {
return "LLM API ์ค๋ฅ: " + response.statusCode();
}
} catch (Exception e) {
e.printStackTrace();
return "์์ธ ๋ฐ์: " + e.getMessage();
}
}
// ๐น JSON ์๋ต์์ "content" ๊ฐ ์ถ์ถ (ํ
์คํธ)
public static String extractContent(String json) {
Pattern pattern = Pattern.compile("\"content\":\"([^\"]+)\""); // "content":"๋ด์ฉ"
Matcher matcher = pattern.matcher(json);
if (matcher.find()) {
return matcher.group(1);
}
return "์๋ต์์ content ๊ฐ์ ์ฐพ์ ์ ์์";
}
// ๐น JSON ์๋ต์์ "url" ๊ฐ ์ถ์ถ (์ด๋ฏธ์ง URL)
public static String extractImageUrl(String json) {
Pattern pattern = Pattern.compile("\"url\"\\s*:\\s*\"(https?://[^\"]+)\"");
Matcher matcher = pattern.matcher(json);
if (matcher.find()) {
return matcher.group(1);
}
return "์๋ต์์ ์ด๋ฏธ์ง URL์ ์ฐพ์ ์ ์์";
}
// ๐น GitHub Issue ์์ฑ ํจ์
public static void sendIssues(String title, String body, String imageUrl) {
String repo = System.getenv("GITHUB_REPO");
String token = System.getenv("GITHUB_TOKEN");
String apiUrl = "https://api.github.com/repos/" + repo + "/issues";
if (repo == null || token == null) {
System.out.println("GITHUB_REPO ๋๋ GITHUB_TOKEN ํ๊ฒฝ ๋ณ์๊ฐ ์ค์ ๋์ง ์์์ต๋๋ค.");
return;
}
// ์ ๋ชฉ๊ณผ ๋ณธ๋ฌธ์์ JSON ๋ฌธ๋ฒ ์ค๋ฅ ๋ฐฉ์ง๋ฅผ ์ํด ์ด์ค์ผ์ดํ ์ฒ๋ฆฌ
String safeTitle = title.replace("\"", "\\\"").replace("\n", "\\n");
String safeBody = body.replace("\"", "\\\"").replace("\n", "\\n");
// Markdown ํ์์ผ๋ก ์ด๋ฏธ์ง ์ถ๊ฐ
String fullBody = safeBody + "\\n\\n---\\n";
String payload = "{"
+ "\"title\": \"" + safeTitle + "\","
+ "\"body\": \"" + fullBody + "\""
+ "}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiUrl))
.header("Authorization", "Bearer " + token)
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 201) {
System.out.println("โ
GitHub Issue ์์ฑ ์ฑ๊ณต!");
} else {
System.out.println("โ GitHub Issue ์์ฑ ์คํจ: " + response.body());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
์ฝ๋๋ ์์ ๊ฐ๋ค.
------------------------------------------------------------------------------------------------------------------------------------------
์ด๋ ๊ฒ ํ๋ฉด ์ด์ ๊นํ๋ธ์์ ์์์ llm์ด ๊ธ ๊ณผ ์ด๋ฏธ์ง๋ฅผ ์ค๋ค.
200์ ์ ์ 400 403 ์๋ฌ
'๐ TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JAVA๋ฅผ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด ์์์ผ ํ๋ ๊ฒ๋ค 1 (0) | 2025.03.06 |
---|---|
2์ 2์ผ (1์ 31์ผ ๋ณต์ต) ํ๋ก๊ทธ๋๋จธ์ค (0) | 2025.02.02 |
๐ 2025๋ 1์ 24์ผ - ์ค๋ ๋ฐฐ์ด ๋ด์ฉ (TIL) (1) | 2025.01.24 |