Created
September 11, 2025 08:12
-
-
Save kishida/5ac71744da23f677e1eec32a958a4d4f to your computer and use it in GitHub Desktop.
LLM日英翻訳
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dev.langchain4j.data.message.SystemMessage; | |
import dev.langchain4j.data.message.UserMessage; | |
import dev.langchain4j.http.client.jdk.JdkHttpClient; | |
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; | |
import dev.langchain4j.model.openai.OpenAiStreamingChatModel; | |
import java.net.http.HttpClient; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
public abstract class LlmStreamEJJE { | |
enum MODEL { LFM2, PLAMO2 } | |
OpenAiStreamingChatModel model; | |
public abstract void translateJE(String message, StreamingChatResponseHandler handler); | |
public abstract void translateEJ(String message, StreamingChatResponseHandler handler); | |
static Map<MODEL, LlmStreamEJJE> cache = new HashMap<>(); | |
public static LlmStreamEJJE of(MODEL m) { | |
return cache.computeIfAbsent(m, md -> | |
switch (md) { | |
case LFM2 -> new Lfm2EJJE(); | |
case PLAMO2 -> new Plamo2EJJE(); | |
default -> throw new IllegalArgumentException(); | |
}); | |
} | |
private LlmStreamEJJE(String modelName) { | |
model = OpenAiStreamingChatModel.builder() | |
.baseUrl("http://localhost:1234/v1") | |
.modelName(modelName) | |
.httpClientBuilder(JdkHttpClient.builder().httpClientBuilder( | |
HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1))) | |
.build(); | |
} | |
private static class Lfm2EJJE extends LlmStreamEJJE { | |
public Lfm2EJJE() { | |
super("lfm2-350m-enjp-mt"); | |
} | |
@Override | |
public void translateJE(String message, StreamingChatResponseHandler handler) { | |
translate(message, "English", handler); | |
} | |
@Override | |
public void translateEJ(String message, StreamingChatResponseHandler handler) { | |
translate(message, "Japanese", handler); | |
} | |
private void translate(String message, String language, StreamingChatResponseHandler handler) { | |
model.chat(List.of( | |
SystemMessage.from("Translate to %s.".formatted(language)), | |
UserMessage.from(message)), handler); | |
} | |
} | |
private static class Plamo2EJJE extends LlmStreamEJJE { | |
public Plamo2EJJE() { | |
super("plamo-2-translate"); | |
} | |
@Override | |
public void translateJE(String message, StreamingChatResponseHandler handler) { | |
translate(message, "Japanese", "English", handler); | |
} | |
@Override | |
public void translateEJ(String message, StreamingChatResponseHandler handler) { | |
translate(message, "English", "Japanese", handler); | |
} | |
private void translate(String message, String from, String to, StreamingChatResponseHandler handler) { | |
var prompt = """ | |
<|plamo:op|>dataset | |
translation | |
<|plamo:op|>input lang=%s | |
%s | |
<|plamo:op|>input lang=%s | |
""".formatted(from, message, to); | |
model.chat( | |
List.of(UserMessage.from(prompt)), handler); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dev.langchain4j.model.chat.response.ChatResponse; | |
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; | |
import module java.desktop; | |
public class TranslatorFrame { | |
private void createAndShowGUI() { | |
JFrame frame = new JFrame("LLM翻訳"); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setLayout(new BorderLayout(8, 8)); | |
frame.setMinimumSize(new Dimension(400, 300)); | |
// 上下に並べるパネル(2行1列) | |
JPanel centerPanel = new JPanel(new GridLayout(2, 1, 6, 6)); | |
centerPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); | |
// テキストエリア1 | |
JTextArea area1 = new JTextArea(); | |
area1.setLineWrap(true); | |
area1.setWrapStyleWord(true); | |
area1.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); | |
area1.setText(""); | |
// テキストエリア2 | |
JTextArea area2 = new JTextArea(); | |
area2.setLineWrap(true); | |
area2.setWrapStyleWord(true); | |
area2.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); | |
area2.setText(""); | |
JScrollPane sp1 = new JScrollPane(area1, | |
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, | |
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); | |
JScrollPane sp2 = new JScrollPane(area2, | |
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, | |
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); | |
// 適度な初期高さを指定(GridLayoutなので高さは均等) | |
sp1.setPreferredSize(new Dimension(200, 150)); | |
sp2.setPreferredSize(new Dimension(200, 150)); | |
centerPanel.add(sp1); | |
centerPanel.add(sp2); | |
// 下部のボタンパネル | |
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); | |
JComboBox<LlmStreamEJJE.MODEL> combo = new JComboBox<>(LlmStreamEJJE.MODEL.values()); | |
bottomPanel.add(combo); | |
JButton jeButton = new JButton("日->英"); | |
bottomPanel.add(jeButton); | |
JButton ejButton = new JButton("英->日"); | |
bottomPanel.add(ejButton); | |
frame.add(centerPanel, BorderLayout.CENTER); | |
frame.add(bottomPanel, BorderLayout.SOUTH); | |
frame.pack(); | |
frame.setLocationRelativeTo(null); | |
frame.setVisible(true); | |
StreamingChatResponseHandler handler = new StreamingChatResponseHandler() { | |
@Override | |
public void onPartialResponse(String partialResponse) { | |
area2.append(partialResponse); | |
} | |
@Override | |
public void onCompleteResponse(ChatResponse completeResponse) { | |
jeButton.setEnabled(true); | |
ejButton.setEnabled(true); | |
} | |
@Override | |
public void onError(Throwable error) { | |
jeButton.setEnabled(true); | |
ejButton.setEnabled(true); | |
throw new RuntimeException(error); | |
} | |
}; | |
jeButton.addActionListener(_ -> { | |
jeButton.setEnabled(false); | |
ejButton.setEnabled(false); | |
LlmStreamEJJE ejje = LlmStreamEJJE.of(combo.getItemAt(combo.getSelectedIndex())); | |
area2.setText(""); | |
ejje.translateJE(area1.getText(), handler); | |
}); | |
ejButton.addActionListener(_ -> { | |
jeButton.setEnabled(false); | |
ejButton.setEnabled(false); | |
LlmStreamEJJE ejje = LlmStreamEJJE.of(combo.getItemAt(combo.getSelectedIndex())); | |
area2.setText(""); | |
ejje.translateEJ(area1.getText(), handler); | |
}); | |
} | |
public void main(String[] args) { | |
SwingUtilities.invokeLater(this::createAndShowGUI); | |
} | |
} |
Author
kishida
commented
Sep 11, 2025

Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment