Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ChatGPT as translation option #118

Merged
merged 22 commits into from
Mar 23, 2023
Merged

add ChatGPT as translation option #118

merged 22 commits into from
Mar 23, 2023

Conversation

rbenza
Copy link
Contributor

@rbenza rbenza commented Mar 14, 2023

No description provided.

@rbenza
Copy link
Contributor Author

rbenza commented Mar 14, 2023

@Airsaid I still get the error below when trying to translate a strings.xml file. I'm not fully sure if I need to add code to the SettingsComponent class. Maybe you can edit / provide feedback?

com.intellij.diagnostic.PluginException: Cannot create class com.airsaid.localization.config.SettingsState (classloader=PluginClassLoader(plugin=PluginDescriptor(name=AndroidLocalize, id=com.github.airsaid.androidlocalize, descriptorPath=plugin.xml, path=~\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-1\223.8617.56.2231.9687552.plugins\AndroidLocalizePlugin-3.0.0.jar, version=3.0.0, package=null, isBundled=false), packagePrefix=null, instanceId=137, state=active))
	at com.intellij.serviceContainer.ComponentManagerImpl.instantiateClass(ComponentManagerImpl.kt:989)
	at com.intellij.serviceContainer.ComponentManagerImpl.createLightService(ComponentManagerImpl.kt:929)
	at com.intellij.serviceContainer.ComponentManagerImpl.getOrCreateLightService(ComponentManagerImpl.kt:733)
	at com.intellij.serviceContainer.ComponentManagerImpl.doGetService(ComponentManagerImpl.kt:685)
	at com.intellij.serviceContainer.ComponentManagerImpl.getService(ComponentManagerImpl.kt:629)
	at com.intellij.openapi.components.ServiceManager.getService(ServiceManager.java:19)
	at com.airsaid.localization.config.SettingsState.getInstance(SettingsState.java:61)
	at com.airsaid.localization.action.TranslateAction.actionPerformed(TranslateAction.java:54)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.doPerformActionOrShowPopup(ActionUtil.java:327)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.lambda$performActionDumbAwareWithCallbacks$4(ActionUtil.java:306)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks(ActionUtil.java:350)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAwareWithCallbacks(ActionUtil.java:306)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.lambda$performAction$5(ActionMenuItem.java:296)
	at com.intellij.openapi.wm.impl.FocusManagerImpl.runOnOwnContext(FocusManagerImpl.java:226)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.performAction(ActionMenuItem.java:289)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.lambda$new$0(ActionMenuItem.java:64)
	at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.lambda$fireActionPerformed$4(ActionMenuItem.java:111)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
	at com.intellij.openapi.application.TransactionGuardImpl.performUserActivity(TransactionGuardImpl.java:94)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:111)
	at com.intellij.ui.plaf.beg.BegMenuItemUI.doClick(BegMenuItemUI.java:526)
	at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:558)
	at java.desktop/java.awt.Component.processMouseEvent(Component.java:6656)
	at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3385)
	at java.desktop/java.awt.Component.processEvent(Component.java:6421)
	at java.desktop/java.awt.Container.processEvent(Container.java:2266)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5026)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2804)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:788)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:737)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:731)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:761)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:759)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:758)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:909)
	at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.java:831)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:753)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$5(IdeEventQueue.java:437)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$6(IdeEventQueue.java:436)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113)
	at com.intellij.ide.IdeEventQueue.performActivity(IdeEventQueue.java:615)
	at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$7(IdeEventQueue.java:434)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:838)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:480)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
Caused by: com.intellij.diagnostic.PluginException: Cannot create class com.airsaid.localization.translate.services.TranslatorService (classloader=PluginClassLoader(plugin=PluginDescriptor(name=AndroidLocalize, id=com.github.airsaid.androidlocalize, descriptorPath=plugin.xml, path=~\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-1\223.8617.56.2231.9687552.plugins\AndroidLocalizePlugin-3.0.0.jar, version=3.0.0, package=null, isBundled=false), packagePrefix=null, instanceId=137, state=active))
	at com.intellij.serviceContainer.ComponentManagerImpl.instantiateClass(ComponentManagerImpl.kt:989)
	at com.intellij.serviceContainer.ComponentManagerImpl.createLightService(ComponentManagerImpl.kt:929)
	at com.intellij.serviceContainer.ComponentManagerImpl.getOrCreateLightService(ComponentManagerImpl.kt:733)
	at com.intellij.serviceContainer.ComponentManagerImpl.doGetService(ComponentManagerImpl.kt:685)
	at com.intellij.serviceContainer.ComponentManagerImpl.getService(ComponentManagerImpl.kt:629)
	at com.intellij.openapi.components.ServiceManager.getService(ServiceManager.java:19)
	at com.airsaid.localization.translate.services.TranslatorService.getInstance(TranslatorService.java:73)
	at com.airsaid.localization.config.SettingsState.<init>(SettingsState.java:51)
	at com.intellij.serviceContainer.ComponentManagerImpl.instantiateClass(ComponentManagerImpl.kt:950)
	... 63 more
Caused by: java.util.ServiceConfigurationError: com.airsaid.localization.translate.AbstractTranslator: Provider com.airsaid.localization.translate.impl.ali.AliTranslator could not be instantiated
	at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:586)
	at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:813)
	at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:729)
	at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1403)
	at com.airsaid.localization.translate.services.TranslatorService.<init>(TranslatorService.java:60)
	at com.intellij.serviceContainer.ComponentManagerImpl.instantiateClass(ComponentManagerImpl.kt:950)
	... 71 more
Caused by: java.lang.NoClassDefFoundError: com/aliyun/teaopenapi/models/Config
	at com.airsaid.localization.translate.impl.ali.AliTranslator.<init>(AliTranslator.java:48)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
	at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:789)
	... 75 more
Caused by: java.lang.ClassNotFoundException: com.aliyun.teaopenapi.models.Config PluginClassLoader(plugin=PluginDescriptor(name=AndroidLocalize, id=com.github.airsaid.androidlocalize, descriptorPath=plugin.xml, path=~\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-1\223.8617.56.2231.9687552.plugins\AndroidLocalizePlugin-3.0.0.jar, version=3.0.0, package=null, isBundled=false), packagePrefix=null, instanceId=137, state=active)
	... 82 more

@Airsaid
Copy link
Owner

Airsaid commented Mar 16, 2023

I don't have that problem on my end, it looks like the corresponding class is not downloaded from the maven repository.

I ran it and found that the OpenAI Icon image is a bit too big, so I will replace it.

@Airsaid
Copy link
Owner

Airsaid commented Mar 16, 2023

I made some changes, can you see if it's OK now?

@rbenza
Copy link
Contributor Author

rbenza commented Mar 18, 2023

I made some changes, can you see if it's OK now?

Yes, looks fine to me. Fixed my issue, was loading the incomplete JAR file (without external dependencies) instead of the complete ZIP file inside build\distributions

Also fixed incorrect request body formatting. I've added a system role for ChatGPT to increase the translation quality. But I do experience this issue now:

Caused by: java.net.SocketTimeoutException: Read timed out
	at java.base/java.net.SocketInputStream.socketRead0(Native Method)
	at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
	at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
	at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
	at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:478)
	at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:472)
	at java.base/sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:70)
	at java.base/sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1454)
	at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:1065)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
	at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:292)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
	at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:754)
	at java.base/sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:689)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1615)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520)
	at java.base/sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:3103)
	at java.base/java.net.URLConnection.getHeaderFieldLong(URLConnection.java:636)
	at java.base/java.net.URLConnection.getContentLengthLong(URLConnection.java:508)
	at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getContentLengthLong(HttpsURLConnectionImpl.java:398)
	at com.intellij.util.io.HttpRequests$RequestImpl.doReadBytes(HttpRequests.java:435)
	... 31 more

@Airsaid is it correct to use connection.setConnectTimeout(0); on the requestBuilder to prevent this issue? Does your library wait to move to the next string value until the server response is received? Regardless on how long it takes?

@Airsaid
Copy link
Owner

Airsaid commented Mar 21, 2023

It's great, I ran the latest version and it works fine.

Using the infinite timeout I don't think is very good, it does block the currently translated string.

The timeout issue is usually a problem with the user's network or translation API service, and there is nothing we can do on the plugin side to fix it. Maybe we could set a slightly longer timeout instead of an infinite timeout?

Also, what is the approximate increase in accuracy after adding system roles to ChatGPT? Because currently, every translation will carry the system role command, which will significantly increase the token usage.

@rbenza
Copy link
Contributor Author

rbenza commented Mar 21, 2023

It's great, I ran the latest version and it works fine.

Using the infinite timeout I don't think is very good, it does block the currently translated string.

The timeout issue is usually a problem with the user's network or translation API service, and there is nothing we can do on the plugin side to fix it. Maybe we could set a slightly longer timeout instead of an infinite timeout?

Also, what is the approximate increase in accuracy after adding system roles to ChatGPT? Because currently, every translation will carry the system role command, which will significantly increase the token usage.

Think the ChatGPT system role is important to get the best result. It's around 100 tokens so only 0.0002 dollar per translated string. If you translate 500 strings this would be 0.10 dollar. That's acceptable to me. Maybe we can shorten it a bit.

However I still often get timeout errors. Can not be my connection since i'm on high end 1gbit/s connection. One thing we should add is at least return all the currently translated strings, before the error happens.. Since now everytime an error occurs all the previously translated strings are not being returned. So you waste money each time a error happens since OpenAI is a paid service.

Another thing that would be great is make the notification dynamic. So 'translating to Italian... (string 2 of 423)' that keeps updating so you know the current progress.

@Airsaid
Copy link
Owner

Airsaid commented Mar 22, 2023

It's great, I ran the latest version and it works fine.
Using the infinite timeout I don't think is very good, it does block the currently translated string.
The timeout issue is usually a problem with the user's network or translation API service, and there is nothing we can do on the plugin side to fix it. Maybe we could set a slightly longer timeout instead of an infinite timeout?
Also, what is the approximate increase in accuracy after adding system roles to ChatGPT? Because currently, every translation will carry the system role command, which will significantly increase the token usage.

Think the ChatGPT system role is important to get the best result. It's around 100 tokens so only 0.0002 dollar per translated string. If you translate 500 strings this would be 0.10 dollar. That's acceptable to me. Maybe we can shorten it a bit.

However I still often get timeout errors. Can not be my connection since i'm on high end 1gbit/s connection. One thing we should add is at least return all the currently translated strings, before the error happens.. Since now everytime an error occurs all the previously translated strings are not being returned. So you waste money each time a error happens since OpenAI is a paid service.

Another thing that would be great is make the notification dynamic. So 'translating to Italian... (string 2 of 423)' that keeps updating so you know the current progress.

I've seen the last few commits shorten the command.

The problem of interruption after an error is indeed a big optimization point, I will optimize the logic of this piece in the next few days.

Also about optimizing the notification content, this is also a good suggestion, I should be able to optimize it in the next version.

I don't think this PR is much of a problem anymore. Is there anything else to optimize on your end? If not, I think it can be merged.

@rbenza
Copy link
Contributor Author

rbenza commented Mar 22, 2023

Yes, you can merge the PR. But I would only do a release if you fix the issue that the translated (and paid for) strings are returned when an error occurs.

@Airsaid
Copy link
Owner

Airsaid commented Mar 23, 2023

I merged it, thanks again for your contribution!

@Airsaid Airsaid merged commit c56e306 into Airsaid:master Mar 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants