Compare commits

...

17 Commits

Author SHA1 Message Date
Kota-Yamaguchi
96bdcb5013
Merge c03f8f55ed into 2fed55ae6b 2024-11-15 16:31:55 +08:00
crazywoola
2fed55ae6b
Fix: number maybe empty string (#10743) 2024-11-15 16:31:10 +08:00
Bowen Liang
51db59622c
chore(lint): cleanup repeated cause exception in logging.exception replaced by helpful message (#10425) 2024-11-15 15:41:40 +08:00
crazywoola
db1d2aaff5
Feat/add Slovensko (Slovenija) (#10731)
Co-authored-by: XHorizont.com <johnny@xhorizont.com>
2024-11-15 13:59:08 +08:00
Steven Lynn
4322fdc910
Feat/add reddit icon (#10733) 2024-11-15 13:55:46 +08:00
非法操作
2a5c5a4e15
fix: remove default model selection for audio tool (#10729) 2024-11-15 12:40:41 +08:00
非法操作
4b2abf8ac2
fix: create_blob_message of tool will always create image type file (#10701)
Some checks are pending
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/amd64, build-api-amd64) (push) Waiting to run
Build and Push API & Web / build (api, DIFY_API_IMAGE_NAME, linux/arm64, build-api-arm64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/amd64, build-web-amd64) (push) Waiting to run
Build and Push API & Web / build (web, DIFY_WEB_IMAGE_NAME, linux/arm64, build-web-arm64) (push) Waiting to run
Build and Push API & Web / create-manifest (api, DIFY_API_IMAGE_NAME, merge-api-images) (push) Blocked by required conditions
Build and Push API & Web / create-manifest (web, DIFY_WEB_IMAGE_NAME, merge-web-images) (push) Blocked by required conditions
2024-11-15 10:38:12 +08:00
Bowen Liang
365cb4b368
chore(lint): bump ruff from 0.6.9 to 0.7.3 (#10714) 2024-11-15 09:19:41 +08:00
GeorgeCaoJ
c85bff235d
fix(i18n): handle key naming error (#10713) 2024-11-15 09:01:38 +08:00
Kalo Chin
ad16180b1a
feat(tool): fal ai wizper ASR built-in tool (#10716) 2024-11-15 09:01:07 +08:00
Kota-Yamaguchi
c03f8f55ed Add gitignore 2024-11-10 22:35:56 +09:00
Kota-Yamaguchi
a42a176798 Update bin 2024-11-10 22:33:55 +09:00
Kota-Yamaguchi
e768497a23 docs: add README for code generator evaluator 2024-11-10 22:06:23 +09:00
Kota-Yamaguchi
36ec1acf7f Add executables for multi-platform build:
- Windows (.exe)
- macOS (.app)
- Linux (binary)
2024-11-10 22:00:11 +09:00
Kota-Yamaguchi
6524cfca99 add golang dependencies 2024-11-10 21:59:19 +09:00
Kota-Yamaguchi
6d2f6b6372 add testcases 2024-11-10 21:58:57 +09:00
Kota-Yamaguchi
d5afda533f Add evaluation metrics for code generator 2024-11-10 21:58:47 +09:00
118 changed files with 4955 additions and 121 deletions

View File

@ -19,6 +19,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="join Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="join Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="join Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat en Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="join Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="seguir en X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat sur Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="join Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="suivre sur X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="Discordでチャット"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="X(Twitter)でフォロー"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Follow Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Follow Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>

View File

@ -19,6 +19,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Follow Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>
@ -238,4 +241,4 @@ Para proteger sua privacidade, evite postar problemas de segurança no GitHub. E
## Licença
Este repositório está disponível sob a [Licença de Código Aberto Dify](LICENSE), que é essencialmente Apache 2.0 com algumas restrições adicionais.
Este repositório está disponível sob a [Licença de Código Aberto Dify](LICENSE), que é essencialmente Apache 2.0 com algumas restrições adicionais.

180
README_SI.md Normal file
View File

@ -0,0 +1,180 @@
![cover-v5-optimized](https://github.com/langgenius/dify/assets/13230914/f9e19af5-61ba-4119-b926-d10c4c06ebab)
<p align="center">
📌 <a href="https://dify.ai/blog/introducing-dify-workflow-file-upload-a-demo-on-ai-podcast">Predstavljamo nalaganje datotek Dify Workflow: znova ustvarite Google NotebookLM Podcast</a>
</p>
<p align="center">
<a href="https://cloud.dify.ai">Dify Cloud</a> ·
<a href="https://docs.dify.ai/getting-started/install-self-hosted">Samostojno gostovanje</a> ·
<a href="https://docs.dify.ai">Dokumentacija</a> ·
<a href="https://udify.app/chat/22L1zSxg6yW1cWQg">Povpraševanje za podjetja</a>
</p>
<p align="center">
<a href="https://dify.ai" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/Product-F04438"></a>
<a href="https://dify.ai/pricing" target="_blank">
<img alt="Static Badge" src="https://img.shields.io/badge/free-pricing?logo=free&color=%20%23155EEF&label=pricing&labelColor=%20%23528bff"></a>
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="follow on X(Twitter)"></a>
<a href="https://hub.docker.com/u/langgenius" target="_blank">
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/langgenius/dify-web?labelColor=%20%23FDB062&color=%20%23f79009"></a>
<a href="https://github.com/langgenius/dify/graphs/commit-activity" target="_blank">
<img alt="Commits last month" src="https://img.shields.io/github/commit-activity/m/langgenius/dify?labelColor=%20%2332b583&color=%20%2312b76a"></a>
<a href="https://github.com/langgenius/dify/" target="_blank">
<img alt="Issues closed" src="https://img.shields.io/github/issues-search?query=repo%3Alanggenius%2Fdify%20is%3Aclosed&label=issues%20closed&labelColor=%20%237d89b0&color=%20%235d6b98"></a>
<a href="https://github.com/langgenius/dify/discussions/" target="_blank">
<img alt="Discussion posts" src="https://img.shields.io/github/discussions/langgenius/dify?labelColor=%20%239b8afb&color=%20%237a5af8"></a>
</p>
<p align="center">
<a href="./README.md"><img alt="README in English" src="https://img.shields.io/badge/English-d9d9d9"></a>
<a href="./README_CN.md"><img alt="简体中文版自述文件" src="https://img.shields.io/badge/简体中文-d9d9d9"></a>
<a href="./README_JA.md"><img alt="日本語のREADME" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
<a href="./README_ES.md"><img alt="README en Español" src="https://img.shields.io/badge/Español-d9d9d9"></a>
<a href="./README_FR.md"><img alt="README en Français" src="https://img.shields.io/badge/Français-d9d9d9"></a>
<a href="./README_KL.md"><img alt="README tlhIngan Hol" src="https://img.shields.io/badge/Klingon-d9d9d9"></a>
<a href="./README_KR.md"><img alt="README in Korean" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
<a href="./README_AR.md"><img alt="README بالعربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
<a href="./README_TR.md"><img alt="Türkçe README" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
<a href="./README_VI.md"><img alt="README Tiếng Việt" src="https://img.shields.io/badge/Ti%E1%BA%BFng%20Vi%E1%BB%87t-d9d9d9"></a>
<a href="./README_SI.md"><img alt="README Slovenščina" src="https://img.shields.io/badge/Sloven%C5%A1%C4%8Dina-d9d9d9"></a>
</p>
Dify je odprtokodna platforma za razvoj aplikacij LLM. Njegov intuitivni vmesnik združuje agentski potek dela z umetno inteligenco, cevovod RAG, zmogljivosti agentov, upravljanje modelov, funkcije opazovanja in več, kar vam omogoča hiter prehod od prototipa do proizvodnje.
## Hitri začetek
> Preden namestite Dify, se prepričajte, da vaša naprava izpolnjuje naslednje minimalne sistemske zahteve:
>
>- CPU >= 2 Core
>- RAM >= 4 GiB
</br>
Najlažji način za zagon strežnika Dify je prek docker compose . Preden zaženete Dify z naslednjimi ukazi, se prepričajte, da sta Docker in Docker Compose nameščena na vašem računalniku:
```bash
cd dify
cd docker
cp .env.example .env
docker compose up -d
```
Po zagonu lahko dostopate do nadzorne plošče Dify v brskalniku na [http://localhost/install](http://localhost/install) in začnete postopek inicializacije.
#### Iskanje pomoči
Prosimo, glejte naša pogosta vprašanja [FAQ](https://docs.dify.ai/getting-started/install-self-hosted/faqs) če naletite na težave pri nastavitvi Dify. Če imate še vedno težave, se obrnite na [skupnost ali nas](#community--contact).
> Če želite prispevati k Difyju ali narediti dodaten razvoj, glejte naš vodnik za [uvajanje iz izvorne kode](https://docs.dify.ai/getting-started/install-self-hosted/local-source-code)
## Ključne značilnosti
**1. Potek dela**:
Zgradite in preizkusite zmogljive poteke dela AI na vizualnem platnu, pri čemer izkoristite vse naslednje funkcije in več.
https://github.com/langgenius/dify/assets/13230914/356df23e-1604-483d-80a6-9517ece318aa
**2. Celovita podpora za modele**:
Brezhibna integracija s stotinami lastniških/odprtokodnih LLM-jev ducatov ponudnikov sklepanja in samostojnih rešitev, ki pokrivajo GPT, Mistral, Llama3 in vse modele, združljive z API-jem OpenAI. Celoten seznam podprtih ponudnikov modelov najdete [tukaj](https://docs.dify.ai/getting-started/readme/model-providers).
![providers-v5](https://github.com/langgenius/dify/assets/13230914/5a17bdbe-097a-4100-8363-40255b70f6e3)
**3. Prompt IDE**:
intuitivni vmesnik za ustvarjanje pozivov, primerjavo zmogljivosti modela in dodajanje dodatnih funkcij, kot je pretvorba besedila v govor, aplikaciji, ki temelji na klepetu.
**4. RAG Pipeline**:
E Obsežne zmogljivosti RAG, ki pokrivajo vse od vnosa dokumenta do priklica, s podporo za ekstrakcijo besedila iz datotek PDF, PPT in drugih običajnih formatov dokumentov.
**5. Agent capabilities**:
definirate lahko agente, ki temeljijo na klicanju funkcij LLM ali ReAct, in dodate vnaprej izdelana orodja ali orodja po meri za agenta. Dify ponuja več kot 50 vgrajenih orodij za agente AI, kot so Google Search, DALL·E, Stable Diffusion in WolframAlpha.
**6. LLMOps**:
Spremljajte in analizirajte dnevnike aplikacij in učinkovitost skozi čas. Pozive, nabore podatkov in modele lahko nenehno izboljšujete na podlagi proizvodnih podatkov in opomb.
**7. Backend-as-a-Service**:
AVse ponudbe Difyja so opremljene z ustreznimi API-ji, tako da lahko Dify brez težav integrirate v svojo poslovno logiko.
## Uporaba Dify
- **Cloud </br>**
Gostimo storitev Dify Cloud za vsakogar, ki jo lahko preizkusite brez nastavitev. Zagotavlja vse zmožnosti različice za samostojno namestitev in vključuje 200 brezplačnih klicev GPT-4 v načrtu peskovnika.
- **Self-hosting Dify Community Edition</br>**
Hitro zaženite Dify v svojem okolju s tem [začetnim vodnikom](#quick-start) . Za dodatne reference in podrobnejša navodila uporabite našo [dokumentacijo](https://docs.dify.ai) .
- **Dify za podjetja/organizacije</br>**
Ponujamo dodatne funkcije, osredotočene na podjetja. Zabeležite svoja vprašanja prek tega klepetalnega robota ali nam pošljite e-pošto, da se pogovorimo o potrebah podjetja. </br>
> Za novoustanovljena podjetja in mala podjetja, ki uporabljajo AWS, si oglejte Dify Premium na AWS Marketplace in ga z enim klikom uvedite v svoj AWS VPC. To je cenovno ugodna ponudba AMI z možnostjo ustvarjanja aplikacij z logotipom in blagovno znamko po meri.
## Staying ahead
Star Dify on GitHub and be instantly notified of new releases.
![star-us](https://github.com/langgenius/dify/assets/13230914/b823edc1-6388-4e25-ad45-2f6b187adbb4)
## Napredne nastavitve
Če morate prilagoditi konfiguracijo, si oglejte komentarje v naši datoteki .env.example in posodobite ustrezne vrednosti v svoji .env datoteki. Poleg tega boste morda morali prilagoditi docker-compose.yamlsamo datoteko, na primer spremeniti različice slike, preslikave vrat ali namestitve nosilca, glede na vaše specifično okolje in zahteve za uvajanje. Po kakršnih koli spremembah ponovno zaženite docker-compose up -d. Celoten seznam razpoložljivih spremenljivk okolja najdete tukaj .
Če želite konfigurirati visoko razpoložljivo nastavitev, so na voljo Helm Charts in datoteke YAML, ki jih prispeva skupnost, ki omogočajo uvedbo Difyja v Kubernetes.
- [Helm Chart by @LeoQuote](https://github.com/douban/charts/tree/master/charts/dify)
- [Helm Chart by @BorisPolonsky](https://github.com/BorisPolonsky/dify-helm)
- [YAML file by @Winson-030](https://github.com/Winson-030/dify-kubernetes)
#### Uporaba Terraform za uvajanje
namestite Dify v Cloud Platform z enim klikom z uporabo [terraform](https://www.terraform.io/)
##### Azure Global
- [Azure Terraform by @nikawang](https://github.com/nikawang/dify-azure-terraform)
##### Google Cloud
- [Google Cloud Terraform by @sotazum](https://github.com/DeNA/dify-google-cloud-terraform)
## Prispevam
Za tiste, ki bi radi prispevali kodo, si oglejte naš vodnik za prispevke . Hkrati vas prosimo, da podprete Dify tako, da ga delite na družbenih medijih ter na dogodkih in konferencah.
> Iščemo sodelavce za pomoč pri prevajanju Difyja v jezike, ki niso mandarinščina ali angleščina. Če želite pomagati, si oglejte i18n README za več informacij in nam pustite komentar v global-userskanalu našega strežnika skupnosti Discord .
## Skupnost in stik
* [Github Discussion](https://github.com/langgenius/dify/discussions). Najboljše za: izmenjavo povratnih informacij in postavljanje vprašanj.
* [GitHub Issues](https://github.com/langgenius/dify/issues). Najboljše za: hrošče, na katere naletite pri uporabi Dify.AI, in predloge funkcij. Oglejte si naš [vodnik za prispevke](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md).
* [Discord](https://discord.gg/FngNHpbcY7). Najboljše za: deljenje vaših aplikacij in druženje s skupnostjo.
* [X(Twitter)](https://twitter.com/dify_ai). Najboljše za: deljenje vaših aplikacij in druženje s skupnostjo.
**Contributors**
<a href="https://github.com/langgenius/dify/graphs/contributors">
<img src="https://contrib.rocks/image?repo=langgenius/dify" />
</a>
## Star history
[![Star History Chart](https://api.star-history.com/svg?repos=langgenius/dify&type=Date)](https://star-history.com/#langgenius/dify&Date)
## Varnostno razkritje
Zaradi zaščite vaše zasebnosti se izogibajte objavljanju varnostnih vprašanj na GitHub. Namesto tega pošljite vprašanja na security@dify.ai in zagotovili vam bomo podrobnejši odgovor.
## Licenca
To skladišče je na voljo pod [odprtokodno licenco Dify](LICENSE) , ki je v bistvu Apache 2.0 z nekaj dodatnimi omejitvami.

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="Discord'da sohbet et"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Follow Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="X(Twitter)'da takip et"></a>

View File

@ -15,6 +15,9 @@
<a href="https://discord.gg/FngNHpbcY7" target="_blank">
<img src="https://img.shields.io/discord/1082486657678311454?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat trên Discord"></a>
<a href="https://reddit.com/r/difyai" target="_blank">
<img src="https://img.shields.io/reddit/subreddit-subscribers/difyai?style=plastic&logo=reddit&label=r%2Fdifyai&labelColor=white"
alt="Follow Reddit"></a>
<a href="https://twitter.com/intent/follow?screen_name=dify_ai" target="_blank">
<img src="https://img.shields.io/twitter/follow/dify_ai?logo=X&color=%20%23f5f5f5"
alt="theo dõi trên X(Twitter)"></a>
@ -235,4 +238,4 @@ Triển khai Dify lên nền tảng đám mây với một cú nhấp chuột b
## Giấy phép
Kho lưu trữ này có sẵn theo [Giấy phép Mã nguồn Mở Dify](LICENSE), về cơ bản là Apache 2.0 với một vài hạn chế bổ sung.
Kho lưu trữ này có sẵn theo [Giấy phép Mã nguồn Mở Dify](LICENSE), về cơ bản là Apache 2.0 với một vài hạn chế bổ sung.

View File

@ -589,7 +589,7 @@ def upgrade_db():
click.echo(click.style("Database migration successful!", fg="green"))
except Exception as e:
logging.exception(f"Database migration failed: {e}")
logging.exception("Failed to execute database migration")
finally:
lock.release()
else:
@ -633,7 +633,7 @@ where sites.id is null limit 1000"""
except Exception as e:
failed_app_ids.append(app_id)
click.echo(click.style("Failed to fix missing site for app {}".format(app_id), fg="red"))
logging.exception(f"Fix app related site missing issue failed, error: {e}")
logging.exception(f"Failed to fix app related site missing issue, app_id: {app_id}")
continue
if not processed_count:

View File

@ -17,6 +17,7 @@ language_timezone_mapping = {
"hi-IN": "Asia/Kolkata",
"tr-TR": "Europe/Istanbul",
"fa-IR": "Asia/Tehran",
"sl-SI": "Europe/Ljubljana",
}
languages = list(language_timezone_mapping.keys())

View File

@ -70,7 +70,7 @@ class ChatMessageAudioApi(Resource):
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error, {str(e)}.")
logging.exception("Failed to handle post request to ChatMessageAudioApi")
raise InternalServerError()
@ -128,7 +128,7 @@ class ChatMessageTextApi(Resource):
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error, {str(e)}.")
logging.exception("Failed to handle post request to ChatMessageTextApi")
raise InternalServerError()
@ -170,7 +170,7 @@ class TextModesApi(Resource):
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error, {str(e)}.")
logging.exception("Failed to handle get request to TextModesApi")
raise InternalServerError()

View File

@ -948,7 +948,7 @@ class DocumentRetryApi(DocumentResource):
raise DocumentAlreadyFinishedError()
retry_documents.append(document)
except Exception as e:
logging.exception(f"Document {document_id} retry failed: {str(e)}")
logging.exception(f"Failed to retry document, document id: {document_id}")
continue
# retry document
DocumentService.retry_document(dataset_id, retry_documents)

View File

@ -72,7 +72,10 @@ class DefaultModelApi(Resource):
model=model_setting["model"],
)
except Exception as ex:
logging.exception(f"{model_setting['model_type']} save error: {ex}")
logging.exception(
f"Failed to update default model, model type: {model_setting['model_type']},"
f" model:{model_setting.get('model')}"
)
raise ex
return {"result": "success"}
@ -156,7 +159,10 @@ class ModelProviderModelApi(Resource):
credentials=args["credentials"],
)
except CredentialsValidateFailedError as ex:
logging.exception(f"save model credentials error: {ex}")
logging.exception(
f"Failed to save model credentials, tenant_id: {tenant_id},"
f" model: {args.get('model')}, model_type: {args.get('model_type')}"
)
raise ValueError(str(ex))
return {"result": "success"}, 200

View File

@ -59,7 +59,7 @@ class AudioApi(WebApiResource):
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error: {str(e)}")
logging.exception("Failed to handle post request to AudioApi")
raise InternalServerError()
@ -117,7 +117,7 @@ class TextApi(WebApiResource):
except ValueError as e:
raise e
except Exception as e:
logging.exception(f"internal server error: {str(e)}")
logging.exception("Failed to handle post request to TextApi")
raise InternalServerError()

View File

@ -362,5 +362,5 @@ class AdvancedChatAppGenerator(MessageBasedAppGenerator):
if e.args[0] == "I/O operation on closed file.": # ignore this error
raise GenerateTaskStoppedError()
else:
logger.exception(e)
logger.exception(f"Failed to process generate task pipeline, conversation_id: {conversation.id}")
raise e

View File

@ -242,7 +242,7 @@ class AdvancedChatAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCyc
start_listener_time = time.time()
yield MessageAudioStreamResponse(audio=audio_trunk.audio, task_id=task_id)
except Exception as e:
logger.exception(e)
logger.exception(f"Failed to listen audio message, task_id: {task_id}")
break
if tts_publisher:
yield MessageAudioEndStreamResponse(audio="", task_id=task_id)

View File

@ -91,6 +91,9 @@ class BaseAppGenerator:
)
if variable_entity.type == VariableEntityType.NUMBER and isinstance(value, str):
# handle empty string case
if not value.strip():
return None
# may raise ValueError if user_input_value is not a valid number
try:
if "." in value:

View File

@ -80,7 +80,7 @@ class MessageBasedAppGenerator(BaseAppGenerator):
if e.args[0] == "I/O operation on closed file.": # ignore this error
raise GenerateTaskStoppedError()
else:
logger.exception(e)
logger.exception(f"Failed to handle response, conversation_id: {conversation.id}")
raise e
def _get_conversation_by_user(

View File

@ -298,5 +298,7 @@ class WorkflowAppGenerator(BaseAppGenerator):
if e.args[0] == "I/O operation on closed file.": # ignore this error
raise GenerateTaskStoppedError()
else:
logger.exception(e)
logger.exception(
f"Fails to process generate task pipeline, task_id: {application_generate_entity.task_id}"
)
raise e

View File

@ -216,7 +216,7 @@ class WorkflowAppGenerateTaskPipeline(BasedGenerateTaskPipeline, WorkflowCycleMa
else:
yield MessageAudioStreamResponse(audio=audio_trunk.audio, task_id=task_id)
except Exception as e:
logger.exception(e)
logger.exception(f"Fails to get audio trunk, task_id: {task_id}")
break
if tts_publisher:
yield MessageAudioEndStreamResponse(audio="", task_id=task_id)

View File

@ -86,7 +86,7 @@ class MessageCycleManage:
conversation.name = name
except Exception as e:
if dify_config.DEBUG:
logging.exception(f"generate conversation name failed: {e}")
logging.exception(f"generate conversation name failed, conversation_id: {conversation_id}")
pass
db.session.merge(conversation)

View File

@ -41,7 +41,7 @@ def check_moderation(model_config: ModelConfigWithCredentialsEntity, text: str)
if moderation_result is True:
return True
except Exception as ex:
logger.exception(ex)
logger.exception(f"Fails to check moderation, provider_name: {provider_name}")
raise InvokeBadRequestError("Rate limit exceeded, please try again later.")
return False

View File

@ -29,7 +29,7 @@ def import_module_from_source(*, module_name: str, py_file_path: AnyStr, use_laz
spec.loader.exec_module(module)
return module
except Exception as e:
logging.exception(f"Failed to load module {module_name} from {py_file_path}: {str(e)}")
logging.exception(f"Failed to load module {module_name} from script file '{py_file_path}'")
raise e

View File

@ -554,7 +554,7 @@ class IndexingRunner:
qa_documents.append(qa_document)
format_documents.extend(qa_documents)
except Exception as e:
logging.exception(e)
logging.exception("Failed to format qa document")
all_qa_documents.extend(format_documents)

View File

@ -102,7 +102,7 @@ class LLMGenerator:
except InvokeError:
questions = []
except Exception as e:
logging.exception(e)
logging.exception("Failed to generate suggested questions after answer")
questions = []
return questions
@ -148,7 +148,7 @@ class LLMGenerator:
error = str(e)
error_step = "generate rule config"
except Exception as e:
logging.exception(e)
logging.exception(f"Failed to generate rule config, model: {model_config.get('name')}")
rule_config["error"] = str(e)
rule_config["error"] = f"Failed to {error_step}. Error: {error}" if error else ""
@ -234,7 +234,7 @@ class LLMGenerator:
error_step = "generate conversation opener"
except Exception as e:
logging.exception(e)
logging.exception(f"Failed to generate rule config, model: {model_config.get('name')}")
rule_config["error"] = str(e)
rule_config["error"] = f"Failed to {error_step}. Error: {error}" if error else ""
@ -286,7 +286,9 @@ class LLMGenerator:
error = str(e)
return {"code": "", "language": code_language, "error": f"Failed to generate code. Error: {error}"}
except Exception as e:
logging.exception(e)
logging.exception(
f"Failed to invoke LLM model, model: {model_config.get('name')}, language: {code_language}"
)
return {"code": "", "language": code_language, "error": f"An unexpected error occurred: {str(e)}"}
@classmethod

View File

@ -103,7 +103,7 @@ class AzureRerankModel(RerankModel):
return RerankResult(model=model, docs=rerank_documents)
except Exception as e:
logger.exception(f"Exception in Azure rerank: {e}")
logger.exception(f"Failed to invoke rerank model, model: {model}")
raise
def validate_credentials(self, model: str, credentials: dict) -> None:

View File

@ -113,7 +113,7 @@ class SageMakerRerankModel(RerankModel):
return RerankResult(model=model, docs=rerank_documents)
except Exception as e:
logger.exception(f"Exception {e}, line : {line}")
logger.exception(f"Failed to invoke rerank model, model: {model}")
def validate_credentials(self, model: str, credentials: dict) -> None:
"""

View File

@ -78,7 +78,7 @@ class SageMakerSpeech2TextModel(Speech2TextModel):
json_obj = json.loads(json_str)
asr_text = json_obj["text"]
except Exception as e:
logger.exception(f"failed to invoke speech2text model, {e}")
logger.exception(f"failed to invoke speech2text model, model: {model}")
raise CredentialsValidateFailedError(str(e))
return asr_text

View File

@ -117,7 +117,7 @@ class SageMakerEmbeddingModel(TextEmbeddingModel):
return TextEmbeddingResult(embeddings=all_embeddings, usage=usage, model=model)
except Exception as e:
logger.exception(f"Exception {e}, line : {line}")
logger.exception(f"Failed to invoke text embedding model, model: {model}, line: {line}")
def get_num_tokens(self, model: str, credentials: dict, texts: list[str]) -> int:
"""

View File

@ -1,5 +1,6 @@
import json
import random
from collections import UserDict
from datetime import datetime
@ -10,9 +11,9 @@ class ChatRole:
FUNCTION = "function"
class _Dict(dict):
__setattr__ = dict.__setitem__
__getattr__ = dict.__getitem__
class _Dict(UserDict):
__setattr__ = UserDict.__setitem__
__getattr__ = UserDict.__getitem__
def __missing__(self, key):
return None

View File

@ -126,6 +126,6 @@ class OutputModeration(BaseModel):
result: ModerationOutputsResult = moderation_factory.moderation_for_outputs(moderation_buffer)
return result
except Exception as e:
logger.exception("Moderation Output error: %s", e)
logger.exception(f"Moderation Output error, app_id: {app_id}")
return None

View File

@ -711,7 +711,7 @@ class TraceQueueManager:
trace_task.app_id = self.app_id
trace_manager_queue.put(trace_task)
except Exception as e:
logging.exception(f"Error adding trace task: {e}")
logging.exception(f"Error adding trace task, trace_type {trace_task.trace_type}")
finally:
self.start_timer()
@ -730,7 +730,7 @@ class TraceQueueManager:
if tasks:
self.send_to_celery(tasks)
except Exception as e:
logging.exception(f"Error processing trace tasks: {e}")
logging.exception("Error processing trace tasks")
def start_timer(self):
global trace_manager_timer

View File

@ -242,7 +242,7 @@ class CouchbaseVector(BaseVector):
try:
self._cluster.query(query, named_parameters={"doc_ids": ids}).execute()
except Exception as e:
logger.exception(e)
logger.exception(f"Failed to delete documents, ids: {ids}")
def delete_by_document_id(self, document_id: str):
query = f"""

View File

@ -79,7 +79,7 @@ class LindormVectorStore(BaseVector):
existing_docs = self._client.mget(index=self._collection_name, body={"ids": batch_ids}, _source=False)
return {doc["_id"] for doc in existing_docs["docs"] if doc["found"]}
except Exception as e:
logger.exception(f"Error fetching batch {batch_ids}: {e}")
logger.exception(f"Error fetching batch {batch_ids}")
return set()
@retry(stop=stop_after_attempt(3), wait=wait_fixed(60))
@ -96,7 +96,7 @@ class LindormVectorStore(BaseVector):
)
return {doc["_id"] for doc in existing_docs["docs"] if doc["found"]}
except Exception as e:
logger.exception(f"Error fetching batch {batch_ids}: {e}")
logger.exception(f"Error fetching batch ids: {batch_ids}")
return set()
if ids is None:
@ -177,7 +177,7 @@ class LindormVectorStore(BaseVector):
else:
logger.warning(f"Index '{self._collection_name}' does not exist. No deletion performed.")
except Exception as e:
logger.exception(f"Error occurred while deleting the index: {e}")
logger.exception(f"Error occurred while deleting the index: {self._collection_name}")
raise e
def text_exists(self, id: str) -> bool:
@ -201,7 +201,7 @@ class LindormVectorStore(BaseVector):
try:
response = self._client.search(index=self._collection_name, body=query)
except Exception as e:
logger.exception(f"Error executing search: {e}")
logger.exception(f"Error executing vector search, query: {query}")
raise
docs_and_scores = []

View File

@ -142,7 +142,7 @@ class MyScaleVector(BaseVector):
for r in self._client.query(sql).named_results()
]
except Exception as e:
logging.exception(f"\033[91m\033[1m{type(e)}\033[0m \033[95m{str(e)}\033[0m")
logging.exception(f"\033[91m\033[1m{type(e)}\033[0m \033[95m{str(e)}\033[0m") # noqa:TRY401
return []
def delete(self) -> None:

View File

@ -158,7 +158,7 @@ class OpenSearchVector(BaseVector):
try:
response = self._client.search(index=self._collection_name.lower(), body=query)
except Exception as e:
logger.exception(f"Error executing search: {e}")
logger.exception(f"Error executing vector search, query: {query}")
raise
docs = []

View File

@ -69,7 +69,7 @@ class CacheEmbedding(Embeddings):
except IntegrityError:
db.session.rollback()
except Exception as e:
logging.exception("Failed transform embedding: %s", e)
logging.exception("Failed transform embedding")
cache_embeddings = []
try:
for i, embedding in zip(embedding_queue_indices, embedding_queue_embeddings):
@ -89,7 +89,7 @@ class CacheEmbedding(Embeddings):
db.session.rollback()
except Exception as ex:
db.session.rollback()
logger.exception("Failed to embed documents: %s", ex)
logger.exception("Failed to embed documents: %s")
raise ex
return text_embeddings
@ -112,7 +112,7 @@ class CacheEmbedding(Embeddings):
embedding_results = (embedding_results / np.linalg.norm(embedding_results)).tolist()
except Exception as ex:
if dify_config.DEBUG:
logging.exception(f"Failed to embed query text: {ex}")
logging.exception(f"Failed to embed query text '{text[:10]}...({len(text)} chars)'")
raise ex
try:
@ -126,7 +126,7 @@ class CacheEmbedding(Embeddings):
redis_client.setex(embedding_cache_key, 600, encoded_str)
except Exception as ex:
if dify_config.DEBUG:
logging.exception("Failed to add embedding to redis %s", ex)
logging.exception(f"Failed to add embedding to redis for the text '{text[:10]}...({len(text)} chars)'")
raise ex
return embedding_results

View File

@ -229,7 +229,7 @@ class WordExtractor(BaseExtractor):
for i in url_pattern.findall(x.text):
hyperlinks_url = str(i)
except Exception as e:
logger.exception(e)
logger.exception("Failed to parse HYPERLINK xml")
def parse_paragraph(paragraph):
paragraph_content = []

View File

@ -159,7 +159,7 @@ class QAIndexProcessor(BaseIndexProcessor):
qa_documents.append(qa_document)
format_documents.extend(qa_documents)
except Exception as e:
logging.exception(e)
logging.exception("Failed to format qa document")
all_qa_documents.extend(format_documents)

View File

@ -57,13 +57,12 @@ class ASRTool(BuiltinTool):
name="model",
label=I18nObject(en_US="Model", zh_Hans="Model"),
human_description=I18nObject(
en_US="All available ASR models",
zh_Hans="所有可用的 ASR 模型",
en_US="All available ASR models. You can config model in the Model Provider of Settings.",
zh_Hans="所有可用的 ASR 模型。你可以在设置中的模型供应商里配置。",
),
type=ToolParameter.ToolParameterType.SELECT,
form=ToolParameter.ToolParameterForm.FORM,
required=True,
default=options[0].value,
options=options,
)
)

View File

@ -77,13 +77,12 @@ class TTSTool(BuiltinTool):
name="model",
label=I18nObject(en_US="Model", zh_Hans="Model"),
human_description=I18nObject(
en_US="All available TTS models",
zh_Hans="所有可用的 TTS 模型",
en_US="All available TTS models. You can config model in the Model Provider of Settings.",
zh_Hans="所有可用的 TTS 模型。你可以在设置中的模型供应商里配置。",
),
type=ToolParameter.ToolParameterType.SELECT,
form=ToolParameter.ToolParameterForm.FORM,
required=True,
default=options[0].value,
options=options,
),
)

View File

@ -38,7 +38,7 @@ def send_mail(parmas: SendEmailToolParameters):
server.sendmail(parmas.email_account, parmas.sender_to, msg.as_string())
return True
except Exception as e:
logging.exception("send email failed: %s", e)
logging.exception("send email failed")
return False
else: # NONE or TLS
try:
@ -49,5 +49,5 @@ def send_mail(parmas: SendEmailToolParameters):
server.sendmail(parmas.email_account, parmas.sender_to, msg.as_string())
return True
except Exception as e:
logging.exception("send email failed: %s", e)
logging.exception("send email failed")
return False

View File

@ -0,0 +1,52 @@
import io
import os
from typing import Any
import fal_client
from core.file.enums import FileAttribute, FileType
from core.file.file_manager import download, get_attr
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool
class WizperTool(BuiltinTool):
def _invoke(self, user_id: str, tool_parameters: dict[str, Any]) -> ToolInvokeMessage:
audio_file = tool_parameters.get("audio_file")
task = tool_parameters.get("task", "transcribe")
language = tool_parameters.get("language", "en")
chunk_level = tool_parameters.get("chunk_level", "segment")
version = tool_parameters.get("version", "3")
if audio_file.type != FileType.AUDIO:
return [self.create_text_message("Not a valid audio file.")]
api_key = self.runtime.credentials["fal_api_key"]
os.environ["FAL_KEY"] = api_key
audio_binary = io.BytesIO(download(audio_file))
mime_type = get_attr(file=audio_file, attr=FileAttribute.MIME_TYPE)
file_data = audio_binary.getvalue()
try:
audio_url = fal_client.upload(file_data, mime_type)
except Exception as e:
return [self.create_text_message(f"Error uploading audio file: {str(e)}")]
arguments = {
"audio_url": audio_url,
"task": task,
"language": language,
"chunk_level": chunk_level,
"version": version,
}
result = fal_client.subscribe(
"fal-ai/wizper",
arguments=arguments,
with_logs=False,
)
return self.create_json_message(result)

View File

@ -0,0 +1,489 @@
identity:
name: wizper
author: Kalo Chin
label:
en_US: Wizper
zh_Hans: Wizper
description:
human:
en_US: Transcribe an audio file using the Whisper model.
zh_Hans: 使用 Whisper 模型转录音频文件。
llm: Transcribe an audio file using the Whisper model.
parameters:
- name: audio_file
type: file
required: true
label:
en_US: Audio File
zh_Hans: 音频文件
human_description:
en_US: "Upload an audio file to transcribe. Supports mp3, mp4, mpeg, mpga, m4a, wav, or webm formats."
zh_Hans: "上传要转录的音频文件。支持 mp3、mp4、mpeg、mpga、m4a、wav 或 webm 格式。"
llm_description: "Audio file to transcribe. Supported formats: mp3, mp4, mpeg, mpga, m4a, wav, or webm."
form: llm
- name: task
type: select
required: true
label:
en_US: Task
zh_Hans: 任务
human_description:
en_US: "Choose whether to transcribe the audio in its original language or translate it to English"
zh_Hans: "选择是以原始语言转录音频还是将其翻译成英语"
llm_description: "Task to perform on the audio file. Either transcribe or translate. Default value: 'transcribe'. If 'translate' is selected as the task, the audio will be translated to English, regardless of the language selected."
form: form
default: transcribe
options:
- value: transcribe
label:
en_US: Transcribe
zh_Hans: 转录
- value: translate
label:
en_US: Translate
zh_Hans: 翻译
- name: language
type: select
required: true
label:
en_US: Language
zh_Hans: 语言
human_description:
en_US: "Select the primary language spoken in the audio file"
zh_Hans: "选择音频文件中使用的主要语言"
llm_description: "Language of the audio file."
form: form
default: en
options:
- value: af
label:
en_US: Afrikaans
zh_Hans: 南非语
- value: am
label:
en_US: Amharic
zh_Hans: 阿姆哈拉语
- value: ar
label:
en_US: Arabic
zh_Hans: 阿拉伯语
- value: as
label:
en_US: Assamese
zh_Hans: 阿萨姆语
- value: az
label:
en_US: Azerbaijani
zh_Hans: 阿塞拜疆语
- value: ba
label:
en_US: Bashkir
zh_Hans: 巴什基尔语
- value: be
label:
en_US: Belarusian
zh_Hans: 白俄罗斯语
- value: bg
label:
en_US: Bulgarian
zh_Hans: 保加利亚语
- value: bn
label:
en_US: Bengali
zh_Hans: 孟加拉语
- value: bo
label:
en_US: Tibetan
zh_Hans: 藏语
- value: br
label:
en_US: Breton
zh_Hans: 布列塔尼语
- value: bs
label:
en_US: Bosnian
zh_Hans: 波斯尼亚语
- value: ca
label:
en_US: Catalan
zh_Hans: 加泰罗尼亚语
- value: cs
label:
en_US: Czech
zh_Hans: 捷克语
- value: cy
label:
en_US: Welsh
zh_Hans: 威尔士语
- value: da
label:
en_US: Danish
zh_Hans: 丹麦语
- value: de
label:
en_US: German
zh_Hans: 德语
- value: el
label:
en_US: Greek
zh_Hans: 希腊语
- value: en
label:
en_US: English
zh_Hans: 英语
- value: es
label:
en_US: Spanish
zh_Hans: 西班牙语
- value: et
label:
en_US: Estonian
zh_Hans: 爱沙尼亚语
- value: eu
label:
en_US: Basque
zh_Hans: 巴斯克语
- value: fa
label:
en_US: Persian
zh_Hans: 波斯语
- value: fi
label:
en_US: Finnish
zh_Hans: 芬兰语
- value: fo
label:
en_US: Faroese
zh_Hans: 法罗语
- value: fr
label:
en_US: French
zh_Hans: 法语
- value: gl
label:
en_US: Galician
zh_Hans: 加利西亚语
- value: gu
label:
en_US: Gujarati
zh_Hans: 古吉拉特语
- value: ha
label:
en_US: Hausa
zh_Hans: 毫萨语
- value: haw
label:
en_US: Hawaiian
zh_Hans: 夏威夷语
- value: he
label:
en_US: Hebrew
zh_Hans: 希伯来语
- value: hi
label:
en_US: Hindi
zh_Hans: 印地语
- value: hr
label:
en_US: Croatian
zh_Hans: 克罗地亚语
- value: ht
label:
en_US: Haitian Creole
zh_Hans: 海地克里奥尔语
- value: hu
label:
en_US: Hungarian
zh_Hans: 匈牙利语
- value: hy
label:
en_US: Armenian
zh_Hans: 亚美尼亚语
- value: id
label:
en_US: Indonesian
zh_Hans: 印度尼西亚语
- value: is
label:
en_US: Icelandic
zh_Hans: 冰岛语
- value: it
label:
en_US: Italian
zh_Hans: 意大利语
- value: ja
label:
en_US: Japanese
zh_Hans: 日语
- value: jw
label:
en_US: Javanese
zh_Hans: 爪哇语
- value: ka
label:
en_US: Georgian
zh_Hans: 格鲁吉亚语
- value: kk
label:
en_US: Kazakh
zh_Hans: 哈萨克语
- value: km
label:
en_US: Khmer
zh_Hans: 高棉语
- value: kn
label:
en_US: Kannada
zh_Hans: 卡纳达语
- value: ko
label:
en_US: Korean
zh_Hans: 韩语
- value: la
label:
en_US: Latin
zh_Hans: 拉丁语
- value: lb
label:
en_US: Luxembourgish
zh_Hans: 卢森堡语
- value: ln
label:
en_US: Lingala
zh_Hans: 林加拉语
- value: lo
label:
en_US: Lao
zh_Hans: 老挝语
- value: lt
label:
en_US: Lithuanian
zh_Hans: 立陶宛语
- value: lv
label:
en_US: Latvian
zh_Hans: 拉脱维亚语
- value: mg
label:
en_US: Malagasy
zh_Hans: 马尔加什语
- value: mi
label:
en_US: Maori
zh_Hans: 毛利语
- value: mk
label:
en_US: Macedonian
zh_Hans: 马其顿语
- value: ml
label:
en_US: Malayalam
zh_Hans: 马拉雅拉姆语
- value: mn
label:
en_US: Mongolian
zh_Hans: 蒙古语
- value: mr
label:
en_US: Marathi
zh_Hans: 马拉地语
- value: ms
label:
en_US: Malay
zh_Hans: 马来语
- value: mt
label:
en_US: Maltese
zh_Hans: 马耳他语
- value: my
label:
en_US: Burmese
zh_Hans: 缅甸语
- value: ne
label:
en_US: Nepali
zh_Hans: 尼泊尔语
- value: nl
label:
en_US: Dutch
zh_Hans: 荷兰语
- value: nn
label:
en_US: Norwegian Nynorsk
zh_Hans: 新挪威语
- value: no
label:
en_US: Norwegian
zh_Hans: 挪威语
- value: oc
label:
en_US: Occitan
zh_Hans: 奥克语
- value: pa
label:
en_US: Punjabi
zh_Hans: 旁遮普语
- value: pl
label:
en_US: Polish
zh_Hans: 波兰语
- value: ps
label:
en_US: Pashto
zh_Hans: 普什图语
- value: pt
label:
en_US: Portuguese
zh_Hans: 葡萄牙语
- value: ro
label:
en_US: Romanian
zh_Hans: 罗马尼亚语
- value: ru
label:
en_US: Russian
zh_Hans: 俄语
- value: sa
label:
en_US: Sanskrit
zh_Hans: 梵语
- value: sd
label:
en_US: Sindhi
zh_Hans: 信德语
- value: si
label:
en_US: Sinhala
zh_Hans: 僧伽罗语
- value: sk
label:
en_US: Slovak
zh_Hans: 斯洛伐克语
- value: sl
label:
en_US: Slovenian
zh_Hans: 斯洛文尼亚语
- value: sn
label:
en_US: Shona
zh_Hans: 修纳语
- value: so
label:
en_US: Somali
zh_Hans: 索马里语
- value: sq
label:
en_US: Albanian
zh_Hans: 阿尔巴尼亚语
- value: sr
label:
en_US: Serbian
zh_Hans: 塞尔维亚语
- value: su
label:
en_US: Sundanese
zh_Hans: 巽他语
- value: sv
label:
en_US: Swedish
zh_Hans: 瑞典语
- value: sw
label:
en_US: Swahili
zh_Hans: 斯瓦希里语
- value: ta
label:
en_US: Tamil
zh_Hans: 泰米尔语
- value: te
label:
en_US: Telugu
zh_Hans: 泰卢固语
- value: tg
label:
en_US: Tajik
zh_Hans: 塔吉克语
- value: th
label:
en_US: Thai
zh_Hans: 泰语
- value: tk
label:
en_US: Turkmen
zh_Hans: 土库曼语
- value: tl
label:
en_US: Tagalog
zh_Hans: 他加禄语
- value: tr
label:
en_US: Turkish
zh_Hans: 土耳其语
- value: tt
label:
en_US: Tatar
zh_Hans: 鞑靼语
- value: uk
label:
en_US: Ukrainian
zh_Hans: 乌克兰语
- value: ur
label:
en_US: Urdu
zh_Hans: 乌尔都语
- value: uz
label:
en_US: Uzbek
zh_Hans: 乌兹别克语
- value: vi
label:
en_US: Vietnamese
zh_Hans: 越南语
- value: yi
label:
en_US: Yiddish
zh_Hans: 意第绪语
- value: yo
label:
en_US: Yoruba
zh_Hans: 约鲁巴语
- value: yue
label:
en_US: Cantonese
zh_Hans: 粤语
- value: zh
label:
en_US: Chinese
zh_Hans: 中文
- name: chunk_level
type: select
label:
en_US: Chunk Level
zh_Hans: 分块级别
human_description:
en_US: "Choose how the transcription should be divided into chunks"
zh_Hans: "选择如何将转录内容分成块"
llm_description: "Level of the chunks to return."
form: form
default: segment
options:
- value: segment
label:
en_US: Segment
zh_Hans:
- name: version
type: select
label:
en_US: Version
zh_Hans: 版本
human_description:
en_US: "Select which version of the Whisper large model to use"
zh_Hans: "选择要使用的 Whisper large 模型版本"
llm_description: "Version of the model to use. All of the models are the Whisper large variant."
form: form
default: "3"
options:
- value: "3"
label:
en_US: Version 3
zh_Hans: 版本 3

View File

@ -175,7 +175,7 @@ class WorkflowTool(Tool):
files.append(file_dict)
except Exception as e:
logger.exception(e)
logger.exception(f"Failed to transform file {file}")
else:
parameters_result[parameter.name] = tool_parameters.get(parameter.name)

View File

@ -98,7 +98,7 @@ class ToolFileManager:
response.raise_for_status()
blob = response.content
except Exception as e:
logger.exception(f"Failed to download file from {file_url}: {e}")
logger.exception(f"Failed to download file from {file_url}")
raise
mimetype = guess_type(file_url)[0] or "octet/stream"

View File

@ -388,7 +388,7 @@ class ToolManager:
yield provider
except Exception as e:
logger.exception(f"load builtin provider {provider} error: {e}")
logger.exception(f"load builtin provider {provider}")
continue
# set builtin providers loaded
cls._builtin_providers_loaded = True

View File

@ -40,7 +40,7 @@ class ToolFileMessageTransformer:
)
)
except Exception as e:
logger.exception(e)
logger.exception(f"Failed to download image from {url}")
result.append(
ToolInvokeMessage(
type=ToolInvokeMessage.MessageType.TEXT,

View File

@ -172,7 +172,7 @@ class GraphEngine:
"answer"
].strip()
except Exception as e:
logger.exception(f"Graph run failed: {str(e)}")
logger.exception("Graph run failed")
yield GraphRunFailedEvent(error=str(e))
return
@ -692,7 +692,7 @@ class GraphEngine:
)
return
except Exception as e:
logger.exception(f"Node {node_instance.node_data.title} run failed: {str(e)}")
logger.exception(f"Node {node_instance.node_data.title} run failed")
raise e
finally:
db.session.close()

View File

@ -69,7 +69,7 @@ class BaseNode(Generic[GenericNodeData]):
try:
result = self._run()
except Exception as e:
logger.exception(f"Node {self.node_id} failed to run: {e}")
logger.exception(f"Node {self.node_id} failed to run")
result = NodeRunResult(
status=WorkflowNodeExecutionStatus.FAILED,
error=str(e),

View File

@ -1,5 +1,4 @@
from collections.abc import Mapping, Sequence
from os import path
from typing import Any
from sqlalchemy import select
@ -180,7 +179,6 @@ class ToolNode(BaseNode[ToolNodeData]):
for response in tool_response:
if response.type in {ToolInvokeMessage.MessageType.IMAGE_LINK, ToolInvokeMessage.MessageType.IMAGE}:
url = str(response.message) if response.message else None
ext = path.splitext(url)[1] if url else ".bin"
tool_file_id = str(url).split("/")[-1].split(".")[0]
transfer_method = response.meta.get("transfer_method", FileTransferMethod.TOOL_FILE)
@ -202,7 +200,6 @@ class ToolNode(BaseNode[ToolNodeData]):
)
result.append(file)
elif response.type == ToolInvokeMessage.MessageType.BLOB:
# get tool file id
tool_file_id = str(response.message).split("/")[-1].split(".")[0]
with Session(db.engine) as session:
stmt = select(ToolFile).where(ToolFile.id == tool_file_id)
@ -211,7 +208,6 @@ class ToolNode(BaseNode[ToolNodeData]):
raise ValueError(f"tool file {tool_file_id} not exists")
mapping = {
"tool_file_id": tool_file_id,
"type": FileType.IMAGE,
"transfer_method": FileTransferMethod.TOOL_FILE,
}
file = file_factory.build_from_mapping(
@ -228,13 +224,8 @@ class ToolNode(BaseNode[ToolNodeData]):
tool_file = session.scalar(stmt)
if tool_file is None:
raise ToolFileError(f"Tool file {tool_file_id} does not exist")
if "." in url:
extension = "." + url.split("/")[-1].split(".")[1]
else:
extension = ".bin"
mapping = {
"tool_file_id": tool_file_id,
"type": FileType.IMAGE,
"transfer_method": transfer_method,
"url": url,
}

View File

@ -70,7 +70,7 @@ class Storage:
try:
self.storage_runner.save(filename, data)
except Exception as e:
logging.exception("Failed to save file: %s", e)
logging.exception(f"Failed to save file {filename}")
raise e
def load(self, filename: str, /, *, stream: bool = False) -> Union[bytes, Generator]:
@ -80,42 +80,42 @@ class Storage:
else:
return self.load_once(filename)
except Exception as e:
logging.exception("Failed to load file: %s", e)
logging.exception(f"Failed to load file {filename}")
raise e
def load_once(self, filename: str) -> bytes:
try:
return self.storage_runner.load_once(filename)
except Exception as e:
logging.exception("Failed to load_once file: %s", e)
logging.exception(f"Failed to load_once file {filename}")
raise e
def load_stream(self, filename: str) -> Generator:
try:
return self.storage_runner.load_stream(filename)
except Exception as e:
logging.exception("Failed to load_stream file: %s", e)
logging.exception(f"Failed to load_stream file {filename}")
raise e
def download(self, filename, target_filepath):
try:
self.storage_runner.download(filename, target_filepath)
except Exception as e:
logging.exception("Failed to download file: %s", e)
logging.exception(f"Failed to download file {filename}")
raise e
def exists(self, filename):
try:
return self.storage_runner.exists(filename)
except Exception as e:
logging.exception("Failed to check file exists: %s", e)
logging.exception(f"Failed to check file exists {filename}")
raise e
def delete(self, filename):
try:
return self.storage_runner.delete(filename)
except Exception as e:
logging.exception("Failed to delete file: %s", e)
logging.exception(f"Failed to delete file {filename}")
raise e

View File

@ -180,6 +180,20 @@ def _get_remote_file_info(url: str):
return mime_type, filename, file_size
def _get_file_type_by_mimetype(mime_type: str) -> FileType:
if "image" in mime_type:
file_type = FileType.IMAGE
elif "video" in mime_type:
file_type = FileType.VIDEO
elif "audio" in mime_type:
file_type = FileType.AUDIO
elif "text" in mime_type or "pdf" in mime_type:
file_type = FileType.DOCUMENT
else:
file_type = FileType.CUSTOM
return file_type
def _build_from_tool_file(
*,
mapping: Mapping[str, Any],
@ -199,12 +213,13 @@ def _build_from_tool_file(
raise ValueError(f"ToolFile {mapping.get('tool_file_id')} not found")
extension = "." + tool_file.file_key.split(".")[-1] if "." in tool_file.file_key else ".bin"
file_type = mapping.get("type", _get_file_type_by_mimetype(tool_file.mimetype))
return File(
id=mapping.get("id"),
tenant_id=tenant_id,
filename=tool_file.name,
type=FileType.value_of(mapping.get("type")),
type=file_type,
transfer_method=transfer_method,
remote_url=tool_file.original_url,
related_id=tool_file.id,

View File

@ -39,13 +39,13 @@ class SMTPClient:
smtp.sendmail(self._from, mail["to"], msg.as_string())
except smtplib.SMTPException as e:
logging.exception(f"SMTP error occurred: {str(e)}")
logging.exception("SMTP error occurred")
raise
except TimeoutError as e:
logging.exception(f"Timeout occurred while sending email: {str(e)}")
logging.exception("Timeout occurred while sending email")
raise
except Exception as e:
logging.exception(f"Unexpected error occurred while sending email: {str(e)}")
logging.exception(f"Unexpected error occurred while sending email to {mail['to']}")
raise
finally:
if smtp:

View File

@ -679,7 +679,7 @@ class DatasetKeywordTable(db.Model):
return json.loads(keyword_table_text.decode("utf-8"), cls=SetDecoder)
return None
except Exception as e:
logging.exception(str(e))
logging.exception(f"Failed to load keyword table from file: {file_key}")
return None

115
api/poetry.lock generated
View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
@ -932,6 +932,10 @@ files = [
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2"},
{file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec"},
{file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"},
{file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"},
{file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"},
@ -944,8 +948,14 @@ files = [
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0"},
{file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b"},
{file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"},
{file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"},
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28"},
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f"},
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"},
{file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"},
{file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"},
@ -956,8 +966,24 @@ files = [
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111"},
{file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839"},
{file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"},
{file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"},
{file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5"},
{file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8"},
{file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f"},
{file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648"},
{file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0"},
{file = "Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089"},
{file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368"},
{file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c"},
{file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284"},
{file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7"},
{file = "Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0"},
{file = "Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b"},
{file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"},
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"},
{file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"},
@ -967,6 +993,10 @@ files = [
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:aea440a510e14e818e67bfc4027880e2fb500c2ccb20ab21c7a7c8b5b4703d75"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:6974f52a02321b36847cd19d1b8e381bf39939c21efd6ee2fc13a28b0d99348c"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:a7e53012d2853a07a4a79c00643832161a910674a893d296c9f1259859a289d2"},
{file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:d7702622a8b40c49bffb46e1e3ba2e81268d5c04a34f460978c6b5517a34dd52"},
{file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"},
{file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"},
{file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"},
@ -978,6 +1008,10 @@ files = [
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:cb1dac1770878ade83f2ccdf7d25e494f05c9165f5246b46a621cc849341dc01"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:3ee8a80d67a4334482d9712b8e83ca6b1d9bc7e351931252ebef5d8f7335a547"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:5e55da2c8724191e5b557f8e18943b1b4839b8efc3ef60d65985bcf6f587dd38"},
{file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:d342778ef319e1026af243ed0a07c97acf3bad33b9f29e7ae6a1f68fd083e90c"},
{file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"},
{file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"},
{file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"},
@ -990,6 +1024,10 @@ files = [
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d2b35ca2c7f81d173d2fadc2f4f31e88cc5f7a39ae5b6db5513cf3383b0e0ec7"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:af6fa6817889314555aede9a919612b23739395ce767fe7fcbea9a80bf140fe5"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2feb1d960f760a575dbc5ab3b1c00504b24caaf6986e2dc2b01c09c87866a943"},
{file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4410f84b33374409552ac9b6903507cdb31cd30d2501fc5ca13d18f73548444a"},
{file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"},
{file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"},
{file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"},
@ -1002,6 +1040,10 @@ files = [
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0737ddb3068957cf1b054899b0883830bb1fec522ec76b1098f9b6e0f02d9419"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4f3607b129417e111e30637af1b56f24f7a49e64763253bbc275c75fa887d4b2"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6c6e0c425f22c1c719c42670d561ad682f7bfeeef918edea971a79ac5252437f"},
{file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:494994f807ba0b92092a163a0a283961369a65f6cbe01e8891132b7a320e61eb"},
{file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"},
{file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"},
{file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"},
@ -2411,6 +2453,26 @@ files = [
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "fal-client"
version = "0.5.6"
description = "Python client for fal.ai"
optional = false
python-versions = ">=3.8"
files = [
{file = "fal_client-0.5.6-py3-none-any.whl", hash = "sha256:631fd857a3c44753ee46a2eea1e7276471453aca58faac9c3702f744c7c84050"},
{file = "fal_client-0.5.6.tar.gz", hash = "sha256:d3afc4b6250023d0ee8437ec504558231d3b106d7aabc12cda8c39883faddecb"},
]
[package.dependencies]
httpx = ">=0.21.0,<1"
httpx-sse = ">=0.4.0,<0.5"
[package.extras]
dev = ["fal-client[docs,test]"]
docs = ["sphinx", "sphinx-autodoc-typehints", "sphinx-rtd-theme"]
test = ["pillow", "pytest", "pytest-asyncio"]
[[package]]
name = "fastapi"
version = "0.115.4"
@ -4049,6 +4111,17 @@ http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "httpx-sse"
version = "0.4.0"
description = "Consume Server-Sent Event (SSE) messages with HTTPX."
optional = false
python-versions = ">=3.8"
files = [
{file = "httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721"},
{file = "httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f"},
]
[[package]]
name = "huggingface-hub"
version = "0.16.4"
@ -8466,29 +8539,29 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
version = "0.6.9"
version = "0.7.3"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd"},
{file = "ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec"},
{file = "ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f"},
{file = "ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa"},
{file = "ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb"},
{file = "ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0"},
{file = "ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625"},
{file = "ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039"},
{file = "ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d"},
{file = "ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117"},
{file = "ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93"},
{file = "ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2"},
{file = "ruff-0.7.3-py3-none-linux_armv6l.whl", hash = "sha256:34f2339dc22687ec7e7002792d1f50712bf84a13d5152e75712ac08be565d344"},
{file = "ruff-0.7.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fb397332a1879b9764a3455a0bb1087bda876c2db8aca3a3cbb67b3dbce8cda0"},
{file = "ruff-0.7.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:37d0b619546103274e7f62643d14e1adcbccb242efda4e4bdb9544d7764782e9"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59f0c3ee4d1a6787614e7135b72e21024875266101142a09a61439cb6e38a5"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44eb93c2499a169d49fafd07bc62ac89b1bc800b197e50ff4633aed212569299"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d0242ce53f3a576c35ee32d907475a8d569944c0407f91d207c8af5be5dae4e"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6b6224af8b5e09772c2ecb8dc9f3f344c1aa48201c7f07e7315367f6dd90ac29"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c50f95a82b94421c964fae4c27c0242890a20fe67d203d127e84fbb8013855f5"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f3eff9961b5d2644bcf1616c606e93baa2d6b349e8aa8b035f654df252c8c67"},
{file = "ruff-0.7.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8963cab06d130c4df2fd52c84e9f10d297826d2e8169ae0c798b6221be1d1d2"},
{file = "ruff-0.7.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:61b46049d6edc0e4317fb14b33bd693245281a3007288b68a3f5b74a22a0746d"},
{file = "ruff-0.7.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:10ebce7696afe4644e8c1a23b3cf8c0f2193a310c18387c06e583ae9ef284de2"},
{file = "ruff-0.7.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3f36d56326b3aef8eeee150b700e519880d1aab92f471eefdef656fd57492aa2"},
{file = "ruff-0.7.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5d024301109a0007b78d57ab0ba190087b43dce852e552734ebf0b0b85e4fb16"},
{file = "ruff-0.7.3-py3-none-win32.whl", hash = "sha256:4ba81a5f0c5478aa61674c5a2194de8b02652f17addf8dfc40c8937e6e7d79fc"},
{file = "ruff-0.7.3-py3-none-win_amd64.whl", hash = "sha256:588a9ff2fecf01025ed065fe28809cd5a53b43505f48b69a1ac7707b1b7e4088"},
{file = "ruff-0.7.3-py3-none-win_arm64.whl", hash = "sha256:1713e2c5545863cdbfe2cbce21f69ffaf37b813bfd1fb3b90dc9a6f1963f5a8c"},
{file = "ruff-0.7.3.tar.gz", hash = "sha256:e1d1ba2e40b6e71a61b063354d04be669ab0d39c352461f3d789cac68b54a313"},
]
[[package]]
@ -11005,4 +11078,4 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<3.13"
content-hash = "f20bd678044926913dbbc24bd0cf22503a75817aa55f59457ff7822032139b77"
content-hash = "2ba4b464eebc26598f290fa94713acc44c588f902176e6efa80622911d40f0ac"

View File

@ -35,6 +35,7 @@ select = [
"S506", # unsafe-yaml-load
"SIM", # flake8-simplify rules
"TRY400", # error-instead-of-exception
"TRY401", # verbose-log-message
"UP", # pyupgrade rules
"W191", # tab-indentation
"W605", # invalid-escape-sequence
@ -122,6 +123,7 @@ celery = "~5.4.0"
chardet = "~5.1.0"
cohere = "~5.2.4"
dashscope = { version = "~1.17.0", extras = ["tokenizer"] }
fal-client = "0.5.6"
flask = "~3.0.1"
flask-compress = "~1.14"
flask-cors = "~4.0.0"
@ -278,4 +280,4 @@ pytest-mock = "~3.14.0"
optional = true
[tool.poetry.group.lint.dependencies]
dotenv-linter = "~0.5.0"
ruff = "~0.6.9"
ruff = "~0.7.3"

View File

@ -779,7 +779,7 @@ class RegisterService:
db.session.query(Tenant).delete()
db.session.commit()
logging.exception(f"Setup failed: {e}")
logging.exception(f"Setup account failed, email: {email}, name: {name}")
raise ValueError(f"Setup failed: {e}")
@classmethod
@ -821,7 +821,7 @@ class RegisterService:
db.session.rollback()
except Exception as e:
db.session.rollback()
logging.exception(f"Register failed: {e}")
logging.exception("Register failed")
raise AccountRegisterError(f"Registration failed: {e}") from e
return account

View File

@ -88,7 +88,7 @@ class AppService:
except (ProviderTokenNotInitError, LLMBadRequestError):
model_instance = None
except Exception as e:
logging.exception(e)
logging.exception(f"Get default model instance failed, tenant_id: {tenant_id}")
model_instance = None
if model_instance:

View File

@ -195,7 +195,7 @@ class ApiToolManageService:
# try to parse schema, avoid SSRF attack
ApiToolManageService.parser_api_schema(schema)
except Exception as e:
logger.exception(f"parse api schema error: {str(e)}")
logger.exception("parse api schema error")
raise ValueError("invalid schema, please check the url you provided")
return {"schema": schema}

View File

@ -183,7 +183,7 @@ class ToolTransformService:
try:
username = db_provider.user.name
except Exception as e:
logger.exception(f"failed to get user name for api provider {db_provider.id}: {str(e)}")
logger.exception(f"failed to get user name for api provider {db_provider.id}")
# add provider into providers
credentials = db_provider.credentials
result = UserToolProvider(

View File

@ -38,4 +38,4 @@ def delete_annotation_index_task(annotation_id: str, app_id: str, tenant_id: str
click.style("App annotations index deleted : {} latency: {}".format(app_id, end_at - start_at), fg="green")
)
except Exception as e:
logging.exception("Annotation deleted index failed:{}".format(str(e)))
logging.exception("Annotation deleted index failed")

View File

@ -60,7 +60,7 @@ def disable_annotation_reply_task(job_id: str, app_id: str, tenant_id: str):
click.style("App annotations index deleted : {} latency: {}".format(app_id, end_at - start_at), fg="green")
)
except Exception as e:
logging.exception("Annotation batch deleted index failed:{}".format(str(e)))
logging.exception("Annotation batch deleted index failed")
redis_client.setex(disable_app_annotation_job_key, 600, "error")
disable_app_annotation_error_key = "disable_app_annotation_error_{}".format(str(job_id))
redis_client.setex(disable_app_annotation_error_key, 600, str(e))

View File

@ -93,7 +93,7 @@ def enable_annotation_reply_task(
click.style("App annotations added to index: {} latency: {}".format(app_id, end_at - start_at), fg="green")
)
except Exception as e:
logging.exception("Annotation batch created index failed:{}".format(str(e)))
logging.exception("Annotation batch created index failed")
redis_client.setex(enable_app_annotation_job_key, 600, "error")
enable_app_annotation_error_key = "enable_app_annotation_error_{}".format(str(job_id))
redis_client.setex(enable_app_annotation_error_key, 600, str(e))

View File

@ -103,5 +103,5 @@ def batch_create_segment_to_index_task(
click.style("Segment batch created job: {} latency: {}".format(job_id, end_at - start_at), fg="green")
)
except Exception as e:
logging.exception("Segments batch created index failed:{}".format(str(e)))
logging.exception("Segments batch created index failed")
redis_client.setex(indexing_cache_key, 600, "error")

View File

@ -1,4 +1,5 @@
import os
from collections import UserDict
from unittest.mock import MagicMock
import pytest
@ -11,7 +12,7 @@ from pymochow.model.table import Table
from requests.adapters import HTTPAdapter
class AttrDict(dict):
class AttrDict(UserDict):
def __getattr__(self, item):
return self.get(item)

View File

@ -1,4 +1,5 @@
import os
from collections import UserDict
from typing import Optional
import pytest
@ -50,7 +51,7 @@ class MockIndex:
return AttrDict({"dimension": 1024})
class AttrDict(dict):
class AttrDict(UserDict):
def __getattr__(self, item):
return self.get(item)

View File

@ -1,4 +1,5 @@
import os
from collections import UserDict
from unittest.mock import MagicMock
import pytest
@ -14,7 +15,7 @@ from tests.unit_tests.oss.__mock.base import (
)
class AttrDict(dict):
class AttrDict(UserDict):
def __getattr__(self, item):
return self.get(item)

View File

@ -0,0 +1,7 @@
# MODEL_PROVIDER=anthropic
# MODEL_NAME=claude-3-5-sonnet-20241022
MODEL_PROVIDER=openai
MODEL_NAME=gpt-4o-mini
CODE_EXECUTION_ENDPOINT=http://127.0.0.1:8194
CODE_EXECUTION_API_KEY=dify-sandbox
CONSOLE_API_URL=http://127.0.0.1:5001

2
evaluate/code-generator/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.env
.env.local

View File

@ -0,0 +1,68 @@
# Code Generator Evaluator
## Getting Started
1. Move to the evaluator directory
```bash
cd dify/evaluate/code-generator
```
2. Set up your `.env` file with required variables
```bash
cp .env.example .env
```
3. Add your test cases to `testdata/testcases.json`
4. Execute the evaluator
```bash
# For Linux
./bin/evaluate-code-linux
# For macOS (Intel)
./bin/evaluate-code-mac
# For macOS (Apple Silicon)
./bin/evaluate-code-mac-arm64
# For Windows
./bin/evaluate-code.exe
```
## Build Instructions
### 1. Prepare Build Script
First, grant execution permissions to the build script:
```bash
chmod +x build.sh
```
### 2. Prerequisites
- Go 1.20 or higher
- Properly configured `GOPATH`
### 3. Build Process
Run the cross-platform build with the following command:
```bash
./build.sh
```
## Running the Evaluator
Execute the Code Generator evaluation on your platform using:
```bash
# For Linux
./bin/evaluate-code-linux
# For macOS (Intel)
./bin/evaluate-code-mac
# For macOS (Apple Silicon)
./bin/evaluate-code-mac-arm64
# For Windows
./bin/evaluate-code.exe
```

View File

@ -0,0 +1,62 @@
package auth
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type LoginRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
type LoginResponse struct {
Result string `json:"result"`
Data struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
} `json:"data"`
}
func Login(email, password string) (string, error) {
client := &http.Client{
Timeout: 10 * time.Second,
}
loginPayload := LoginRequest{
Email: email,
Password: password,
}
loginJSON, err := json.Marshal(loginPayload)
if err != nil {
return "", fmt.Errorf("failed to convert to JSON: %w", err)
}
baseUrl := os.Getenv("CONSOLE_API_URL")
loginReq, err := http.NewRequest("POST", baseUrl+"/console/api/login", bytes.NewBuffer(loginJSON))
if err != nil {
return "", fmt.Errorf("failed to create request: %w", err)
}
loginReq.Header.Set("Content-Type", "application/json")
loginResp, err := client.Do(loginReq)
if err != nil {
return "", fmt.Errorf("failed to send request: %w", err)
}
defer loginResp.Body.Close()
var loginResult LoginResponse
if err := json.NewDecoder(loginResp.Body).Decode(&loginResult); err != nil {
return "", fmt.Errorf("failed to decode response: %w", err)
}
if loginResult.Result != "success" {
return "", fmt.Errorf("login failed")
}
return loginResult.Data.AccessToken, nil
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,17 @@
#!/bin/bash
mkdir -p bin
echo "Building for Linux (amd64)..."
GOOS=linux GOARCH=amd64 go build -o bin/evaluate-code-linux ./cmd/
echo "Building for macOS (amd64)..."
GOOS=darwin GOARCH=amd64 go build -o bin/evaluate-code-mac ./cmd/
echo "Building for macOS (arm64)..."
GOOS=darwin GOARCH=arm64 go build -o bin/evaluate-code-mac-arm64 ./cmd/
echo "Building for Windows (amd64)..."
GOOS=windows GOARCH=amd64 go build -o bin/evaluate-code.exe ./cmd/
echo "Build complete! Binaries are in the bin directory."

View File

@ -0,0 +1,121 @@
package main
import (
"evaluate/auth"
"evaluate/coderuntime"
"evaluate/testdata"
"fmt"
"os"
"strings"
"syscall"
"github.com/joho/godotenv"
"golang.org/x/term"
)
func main() {
if err := godotenv.Load("./.env"); err != nil {
fmt.Printf("Failed to load .env file: %v\n", err)
return
}
fmt.Print("Please enter your email address: ")
var email string
fmt.Scanln(&email)
fmt.Print("Please enter your password: ")
password, err := term.ReadPassword(int(syscall.Stdin))
if err != nil {
fmt.Printf("\nFailed to read password: %v\n", err)
return
}
fmt.Println()
accessToken, err := auth.Login(email, string(password))
testCases, err := testdata.LoadTestCases("./testdata/testcases.json")
if err != nil {
fmt.Printf("Failed to load test cases: %v\n", err)
return
}
metrics := testdata.NewTestMetrics()
modelProvider := os.Getenv("MODEL_PROVIDER")
modelName := os.Getenv("MODEL_NAME")
fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━")
fmt.Printf("📱 Model Provider: %s\n", modelProvider)
fmt.Printf("🤖 Model Name: %s\n", modelName)
fmt.Println("━━━━━━━━━━━━━━━━━━━━━━━━━━━")
for _, tc := range testCases {
fmt.Printf("\nExecuting test case: %s\n", tc.Name)
codegenRequest := coderuntime.GenerateCodeRequest{
Instruction: tc.Instruction,
CodeLanguage: tc.CodeLanguage,
NoVariable: false,
ModelConfig: coderuntime.ModelConfig{
Provider: modelProvider,
Name: modelName,
Mode: "chat",
CompletionParams: coderuntime.CompletionParams{
Temperature: 0.7,
MaxTokens: 0,
TopP: 0,
Echo: false,
Stop: []string{},
PresencePenalty: 0,
FrequencyPenalty: 0,
},
},
}
generatedCode, err := coderuntime.GenerateCode(
codegenRequest,
coderuntime.AccessToken{
Value: accessToken,
},
)
if err != nil {
metrics.AddResult(testdata.TestResult{
TestCase: tc,
Success: false,
Error: err,
})
continue
}
language := generatedCode.Language
if language == "python" {
language += "3"
}
request := coderuntime.SandboxRequest{
Language: language,
Code: generatedCode.Code,
EnableNetwork: true,
}
result, err := coderuntime.ExecuteCode(request, tc.Inputs)
if result.Error != nil {
metrics.AddResult(testdata.TestResult{
TestCase: tc,
Success: false,
Error: result.Error,
})
continue
}
normalizedResult := strings.ReplaceAll(strings.ReplaceAll(result.Body, " ", ""), "\n", "")
normalizedTruth := strings.ReplaceAll(strings.ReplaceAll(tc.GroundTruth, " ", ""), "\n", "")
metrics.AddResult(testdata.TestResult{
TestCase: tc,
Success: normalizedResult == normalizedTruth,
ActualValue: result.Body,
})
}
metrics.Finish()
metrics.PrintSummary()
}

View File

@ -0,0 +1,142 @@
package coderuntime
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
type SandboxRequest struct {
Language string `json:"language"`
Code string `json:"code"`
Preload string `json:"preload,omitempty"`
EnableNetwork bool `json:"enable_network"`
}
type ExecutionResult struct {
StatusCode int
Body string
Error error
}
func ExtractResult(response string) (string, error) {
const resultTag = "<<RESULT>>"
startIndex := strings.Index(response, resultTag) + len(resultTag)
endIndex := strings.LastIndex(response, resultTag)
if startIndex == -1 || endIndex == -1 {
return "", fmt.Errorf("invalid result format")
}
jsonStr := response[startIndex:endIndex]
var result map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
return "", fmt.Errorf("failed to parse JSON: %v", err)
}
// Format output
prettyJSON, err := json.MarshalIndent(result, "", " ")
if err != nil {
return "", fmt.Errorf("failed to format JSON: %v", err)
}
return string(prettyJSON), nil
}
func ExecuteCode(request SandboxRequest, inputs map[string]interface{}) (ExecutionResult, error) {
apiKey := os.Getenv("CODE_EXECUTION_API_KEY")
endpoint := os.Getenv("CODE_EXECUTION_ENDPOINT")
if apiKey == "" || endpoint == "" {
fmt.Println("必要な環境変数が設定されていません")
return ExecutionResult{}, fmt.Errorf("missing required environment variables")
}
var transformer TemplateTransformer
switch request.Language {
case "python3":
transformer = NewPython3TemplateTransformer()
case "javascript":
transformer = NewJavaScriptTemplateTransformer()
default:
return ExecutionResult{}, fmt.Errorf("unsupported language: %s", request.Language)
}
// transformer := NewPython3TemplateTransformer()
finalCode, preload, err := transformer.TransformCaller(request.Code, inputs)
if err != nil {
return ExecutionResult{}, fmt.Errorf("failed to transform code: %v", err)
}
execRequest := SandboxRequest{
Language: request.Language,
Code: finalCode,
Preload: preload,
EnableNetwork: request.EnableNetwork,
}
client := &http.Client{
Timeout: 10 * time.Second,
}
jsonData, err := json.Marshal(execRequest)
if err != nil {
return ExecutionResult{}, fmt.Errorf("failed to convert to JSON: %v", err)
}
url := endpoint + "/v1/sandbox/run"
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return ExecutionResult{}, fmt.Errorf("failed to create request: %v", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", apiKey)
resp, err := client.Do(req)
if err != nil {
return ExecutionResult{}, fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return ExecutionResult{}, fmt.Errorf("failed to read response: %v", err)
}
result := ExecutionResult{
StatusCode: resp.StatusCode,
Body: string(body),
}
if resp.StatusCode == 200 {
var response struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
Error string `json:"error"`
Stdout string `json:"stdout"`
} `json:"data"`
}
if err := json.Unmarshal(body, &response); err != nil {
return result, fmt.Errorf("failed to parse response: %v", err)
}
if response.Data.Error != "" {
result.Error = fmt.Errorf("execution error: %s", response.Data.Error)
} else if prettyResult, err := ExtractResult(response.Data.Stdout); err != nil {
result.Error = fmt.Errorf("failed to process result: %v", err)
} else {
result.Body = prettyResult
}
}
return result, nil
}

View File

@ -0,0 +1,73 @@
package coderuntime
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func GenerateCode(request GenerateCodeRequest, accessToken AccessToken) (*GenerateCodeResponse, error) {
baseUrl := os.Getenv("CONSOLE_API_URL")
url := baseUrl + "/console/api/rule-code-generate"
jsonData, err := json.Marshal(request)
if err != nil {
return nil, fmt.Errorf("JSON encoding error: %v", err)
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("request creation error: %v", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+accessToken.Value)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("request sending error: %v", err)
}
defer resp.Body.Close()
var response GenerateCodeResponse
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, fmt.Errorf("response decoding error: %v", err)
}
return &response, nil
}
type GenerateCodeRequest struct {
Instruction string `json:"instruction"`
CodeLanguage string `json:"code_language"`
NoVariable bool `json:"no_variable"`
ModelConfig ModelConfig `json:"model_config"`
}
type AccessToken struct {
Value string
}
type GenerateCodeResponse struct {
Code string `json:"code"`
Error string `json:"error"`
Language string `json:"language"`
}
type ModelConfig struct {
Provider string `json:"provider"`
Name string `json:"name"`
Mode string `json:"mode"`
CompletionParams CompletionParams `json:"completion_params"`
}
type CompletionParams struct {
Temperature float64 `json:"temperature"`
MaxTokens int `json:"max_tokens"`
TopP float64 `json:"top_p"`
Echo bool `json:"echo"`
Stop []string `json:"stop"`
PresencePenalty float64 `json:"presence_penalty"`
FrequencyPenalty float64 `json:"frequency_penalty"`
}

View File

@ -0,0 +1,28 @@
package coderuntime
type JavaScriptTemplateTransformer struct {
*BaseTemplateTransformer
}
func NewJavaScriptTemplateTransformer() *JavaScriptTemplateTransformer {
t := &JavaScriptTemplateTransformer{}
t.BaseTemplateTransformer = NewBaseTemplateTransformer(t)
return t
}
func (j *JavaScriptTemplateTransformer) GetRunnerScript() string {
return `
// declare main function
{{code}}
// decode and prepare input object
const inputs_obj = JSON.parse(Buffer.from('{{inputs}}', 'base64').toString('utf-8'))
// execute main function
const output_obj = main(inputs_obj)
// convert output to json and print
const output_json = JSON.stringify(output_obj, null, 4)
const result = '<<RESULT>>' + output_json + '<<RESULT>>'
console.log(result)
`
}

View File

@ -0,0 +1,32 @@
package coderuntime
type Python3TemplateTransformer struct {
*BaseTemplateTransformer
}
func NewPython3TemplateTransformer() *Python3TemplateTransformer {
t := &Python3TemplateTransformer{}
t.BaseTemplateTransformer = NewBaseTemplateTransformer(t)
return t
}
func (p *Python3TemplateTransformer) GetRunnerScript() string {
return `
# declare main function
{{code}}
import json
from base64 import b64decode
# decode and prepare input dict
inputs_obj = json.loads(b64decode('{{inputs}}').decode('utf-8'))
# execute main function
output_obj = main(**inputs_obj)
# convert output to json and print
output_json = json.dumps(output_obj, indent=4)
result = f'''<<RESULT>>{output_json}<<RESULT>>'''
print(result)
`
}

View File

@ -0,0 +1,63 @@
package coderuntime
import (
"bytes"
"encoding/base64"
"encoding/json"
"strings"
)
type TemplateTransformer interface {
TransformCaller(code string, inputs map[string]interface{}) (string, string, error)
GetRunnerScript() string
GetPreloadScript() string
}
type BaseTemplateTransformer struct {
CodePlaceholder string
InputsPlaceholder string
ResultTag string
transformer TemplateTransformer
}
func NewBaseTemplateTransformer(t TemplateTransformer) *BaseTemplateTransformer {
return &BaseTemplateTransformer{
CodePlaceholder: "{{code}}",
InputsPlaceholder: "{{inputs}}",
ResultTag: "<<RESULT>>",
transformer: t,
}
}
func (t *BaseTemplateTransformer) GetRunnerScript() string {
return ""
}
func (t *BaseTemplateTransformer) GetPreloadScript() string {
return ""
}
func (t *BaseTemplateTransformer) TransformCaller(code string, inputs map[string]interface{}) (string, string, error) {
inputsJSON, err := json.Marshal(inputs)
if err != nil {
return "", "", err
}
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetEscapeHTML(false)
if err := encoder.Encode(inputs); err != nil {
return "", "", err
}
inputsJSON = bytes.TrimSpace(buf.Bytes()) // 末尾の改行を削除
inputsBase64 := base64.StdEncoding.EncodeToString(inputsJSON)
runnerScript := t.transformer.GetRunnerScript()
runnerScript = strings.ReplaceAll(runnerScript, t.CodePlaceholder, code)
runnerScript = strings.ReplaceAll(runnerScript, t.InputsPlaceholder, inputsBase64)
preloadScript := t.GetPreloadScript()
return runnerScript, preloadScript, nil
}

View File

@ -0,0 +1,10 @@
module evaluate
go 1.23.0
require (
github.com/joho/godotenv v1.5.1
golang.org/x/term v0.26.0
)
require golang.org/x/sys v0.27.0 // indirect

View File

@ -0,0 +1,6 @@
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=

View File

@ -0,0 +1,62 @@
package testdata
import (
"fmt"
"time"
)
type TestMetrics struct {
TotalTests int
SuccessfulTests int
FailedTests int
StartTime time.Time
EndTime time.Time
Results []TestResult
}
func NewTestMetrics() *TestMetrics {
return &TestMetrics{
StartTime: time.Now(),
Results: make([]TestResult, 0),
}
}
func (m *TestMetrics) AddResult(result TestResult) {
m.TotalTests++
if result.Success {
m.SuccessfulTests++
} else {
m.FailedTests++
}
m.Results = append(m.Results, result)
}
func (m *TestMetrics) Finish() {
m.EndTime = time.Now()
}
func (m *TestMetrics) PrintSummary() {
duration := m.EndTime.Sub(m.StartTime)
accuracy := float64(m.SuccessfulTests) / float64(m.TotalTests) * 100
fmt.Printf("\n=== Detailed Results ===\n")
for _, result := range m.Results {
if result.Success {
fmt.Printf("✅ %s\n", result.TestCase.Name)
} else {
fmt.Printf("❌ %s\n", result.TestCase.Name)
if result.Error != nil {
fmt.Printf(" Error: %v\n", result.Error)
} else {
fmt.Printf(" Expected: %s\n Actual: %s\n",
result.TestCase.GroundTruth, result.ActualValue)
}
}
}
fmt.Printf("\n=== Test Execution Summary ===\n")
fmt.Printf("Total Tests: %d\n", m.TotalTests)
fmt.Printf("Successful: %d\n", m.SuccessfulTests)
fmt.Printf("Failed: %d\n", m.FailedTests)
fmt.Printf("Accuracy: %.2f%%\n", accuracy)
fmt.Printf("Execution Time: %.2f seconds\n", duration.Seconds())
}

View File

@ -0,0 +1,35 @@
package testdata
import (
"encoding/json"
"os"
)
type TestCase struct {
Name string `json:"name"`
Inputs map[string]interface{} `json:"inputs"`
Instruction string `json:"instruction"`
CodeLanguage string `json:"code_language"`
GroundTruth string `json:"ground_truth"`
}
type TestResult struct {
TestCase TestCase
Success bool
ActualValue string
Error error
}
func LoadTestCases(filePath string) ([]TestCase, error) {
file, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
var testCases []TestCase
if err := json.Unmarshal(file, &testCases); err != nil {
return nil, err
}
return testCases, nil
}

View File

@ -0,0 +1,20 @@
[
{
"name": "Positive Number Check",
"inputs": {
"x": 10
},
"instruction": "if x > 0: return 'positive'",
"code_language": "python",
"ground_truth": "{\"result\": \"positive\"}"
},
{
"name": "Negative Number Check",
"inputs": {
"x": -5
},
"instruction": "if x > 0: return 'positive' else: return 'negative'",
"code_language": "python",
"ground_truth": "{\"result\": \"negative\"}"
}
]

View File

@ -72,7 +72,7 @@ export type I18nText = {
}
```
4. Add the new language to the `language.ts` file.
4. Add the new language to the `language.json` file.
```typescript

View File

@ -24,6 +24,7 @@ export type I18nText = {
'pl-PL': string
'hi-IN': string
'fa-IR': string
'sl-SI': string
}
export const languages = data.languages
@ -53,6 +54,7 @@ export const NOTICE_I18N = {
vi_VN: 'Thông báo quan trọng',
it_IT: 'Avviso Importante',
fa_IR: 'هشدار مهم',
sl_SI: 'Pomembno obvestilo',
},
desc: {
en_US:
@ -83,6 +85,8 @@ export const NOTICE_I18N = {
'Sistemimiz, 28 Ağustos\'ta 19:00 ile 24:00 UTC saatleri arasında güncelleme nedeniyle kullanılamayacaktır. Sorularınız için lütfen destek ekibimizle iletişime geçin (support@dify.ai). Sabrınız için teşekkür ederiz.',
fa_IR:
'سیستم ما از ساعت 19:00 تا 24:00 UTC در تاریخ 28 اوت برای ارتقاء در دسترس نخواهد بود. برای سؤالات، لطفاً با تیم پشتیبانی ما (support@dify.ai) تماس بگیرید. ما برای صبر شما ارزش قائلیم.',
sl_SI:
'Naš sistem ne bo na voljo od 19:00 do 24:00 UTC 28. avgusta zaradi nadgradnje. Za vprašanja se obrnite na našo skupino za podporo (support@dify.ai). Cenimo vašo potrpežljivost.',
},
href: '#',
}

View File

@ -139,6 +139,13 @@
"prompt_name": "Farsi",
"example": "سلام, دیفای!",
"supported": true
},
{
"value": "sl-SI",
"name": "Slovensko (Slovenija)",
"prompt_name": "Slovensko",
"example": "Zdravo, Dify!",
"supported": true
}
]
}

View File

@ -86,8 +86,8 @@ const translation = {
agenteLogDetail: {
agentMode: 'Modo Agente',
toolUsed: 'Ferramenta usada',
iterações: 'Iterações',
iteração: 'Iteração',
iterations: 'Iterações',
iteration: 'Iteração',
finalProcessing: 'Processamento Final',
},
agentLogDetail: {

View File

@ -0,0 +1,87 @@
const translation = {
title: 'Opombe',
name: 'Odgovor na opombo',
editBy: 'Odgovor je uredil {{author}}',
noData: {
title: 'Brez opomb',
description: 'Opombe lahko urejate med odpravljanjem napak v aplikaciji ali jih množično uvozite tukaj za visokokakovosten odgovor.',
},
table: {
header: {
question: 'vprašanje',
answer: 'odgovor',
createdAt: 'ustvarjeno ob',
hits: 'zadetki',
actions: 'dejanja',
addAnnotation: 'Dodaj opombo',
bulkImport: 'Množični uvoz',
bulkExport: 'Množični izvoz',
clearAll: 'Počisti vse opombe',
},
},
editModal: {
title: 'Uredi odgovor na opombo',
queryName: 'Uporabniško vprašanje',
answerName: 'Pripovedovalec Bot',
yourAnswer: 'Vaš odgovor',
answerPlaceholder: 'Vnesite svoj odgovor tukaj',
yourQuery: 'Vaše vprašanje',
queryPlaceholder: 'Vnesite svoje vprašanje tukaj',
removeThisCache: 'Odstrani to opombo',
createdAt: 'Ustvarjeno ob',
},
addModal: {
title: 'Dodaj odgovor na opombo',
queryName: 'Vprašanje',
answerName: 'Odgovor',
answerPlaceholder: 'Vnesite odgovor tukaj',
queryPlaceholder: 'Vnesite vprašanje tukaj',
createNext: 'Dodaj še en odgovor z opombo',
},
batchModal: {
title: 'Množični uvoz',
csvUploadTitle: 'Povlecite in spustite svoj CSV datoteko tukaj ali ',
browse: 'poiščite',
tip: 'CSV datoteka mora ustrezati naslednji strukturi:',
question: 'vprašanje',
answer: 'odgovor',
contentTitle: 'vsebina fragmenta',
content: 'vsebina',
template: 'Prenesite predlogo tukaj',
cancel: 'Prekliči',
run: 'Zaženi množično obdelavo',
runError: 'Napaka pri množičnem zagonu',
processing: 'V množični obdelavi',
completed: 'Uvoz zaključen',
error: 'Napaka pri uvozu',
ok: 'V redu',
},
errorMessage: {
answerRequired: 'Odgovor je obvezen',
queryRequired: 'Vprašanje je obvezno',
},
viewModal: {
annotatedResponse: 'Odgovor na opombo',
hitHistory: 'Zgodovina zadetkov',
hit: 'Zadetek',
hits: 'Zadetki',
noHitHistory: 'Ni zgodovine zadetkov',
},
hitHistoryTable: {
query: 'Vprašanje',
match: 'Ujemanje',
response: 'Odgovor',
source: 'Vir',
score: 'Rezultat',
time: 'Čas',
},
initSetup: {
title: 'Začetna nastavitev odgovora na opombo',
configTitle: 'Nastavitev odgovora na opombo',
confirmBtn: 'Shrani in omogoči',
configConfirmBtn: 'Shrani',
},
embeddingModelSwitchTip: 'Model za vektorizacijo besedila opomb, preklapljanje modelov bo ponovno vektoriziralo, kar bo povzročilo dodatne stroške.',
}
export default translation

84
web/i18n/sl-SI/app-api.ts Normal file
View File

@ -0,0 +1,84 @@
const translation = {
apiServer: 'API Strežnik',
apiKey: 'API Ključ',
status: 'Status',
disabled: 'Onemogočeno',
ok: 'V uporabi',
copy: 'Kopiraj',
copied: 'Kopirano',
regenerate: 'Regeneriraj',
play: 'Predvajaj',
pause: 'Premor',
playing: 'Predvajanje',
loading: 'Nalaganje',
merMaid: {
rerender: 'Ponovno izrisi',
},
never: 'Nikoli',
apiKeyModal: {
apiSecretKey: 'API Skrivni ključ',
apiSecretKeyTips: 'Da bi preprečili zlorabo API-ja, zaščitite svoj API ključ. Izogibajte se uporabi v navadnem besedilu v sprednji kodi. :)',
createNewSecretKey: 'Ustvari nov skrivni ključ',
secretKey: 'Skrivni ključ',
created: 'USTVARJENO',
lastUsed: 'ZADNJA UPORABA',
generateTips: 'Hranite ta ključ na varnem in dostopnem mestu.',
},
actionMsg: {
deleteConfirmTitle: 'Izbrisati ta skrivni ključ?',
deleteConfirmTips: 'To dejanje ni mogoče razveljaviti.',
ok: 'V redu',
},
completionMode: {
title: 'API za dokončanje aplikacije',
info: 'Za visokokakovostno generiranje besedil, kot so članki, povzetki in prevodi, uporabite API za dokončanje sporočil z vnosom uporabnika. Generiranje besedil temelji na parametrih modela in predlogah pozivov, določenih v Dify Prompt Engineering.',
createCompletionApi: 'Ustvari sporočilo o dokončanju',
createCompletionApiTip: 'Ustvari sporočilo o dokončanju za podporo načinu vprašanj in odgovorov.',
inputsTips: '(Neobvezno) Navedite vnosna polja uporabnikov kot ključ-vrednost pare, ki ustrezajo spremenljivkam v Prompt Eng. Ključ je ime spremenljivke, vrednost pa vrednost parametra. Če je vrsta polja Izberi, mora biti posredovana vrednost ena izmed vnaprej določenih možnosti.',
queryTips: 'Vsebina besedila vnosa uporabnika.',
blocking: 'Vrsta blokiranja, čakanje na dokončanje izvajanja in vračanje rezultatov. (Zahteve se lahko prekinejo, če je postopek dolg)',
streaming: 'streaming povratki. Implementacija povratkov pretakanja na podlagi SSE (Server-Sent Events).',
messageFeedbackApi: 'Povratne informacije o sporočilih (všeč)',
messageFeedbackApiTip: 'Ocenite prejeta sporočila v imenu končnih uporabnikov z všečki ali nevšečki. Ti podatki so vidni na strani Dnevniki in opombe ter se uporabljajo za nadaljnje fino prilagajanje modela.',
messageIDTip: 'ID sporočila',
ratingTip: 'všeč ali nevšeč, null je preklic',
parametersApi: 'Pridobite informacije o parametrih aplikacije',
parametersApiTip: 'Pridobite konfigurirane vhodne parametre, vključno z imeni spremenljivk, imeni polj, vrstami in privzetimi vrednostmi. Običajno se uporablja za prikaz teh polj v obrazcu ali izpolnjevanje privzetih vrednosti po nalaganju odjemalca.',
},
chatMode: {
title: 'API za klepet aplikacije',
info: 'Za vsestranske pogovorne aplikacije, ki uporabljajo obliko vprašanj in odgovorov, pokličite API za klepetna sporočila, da začnete dialog. Ohranite tekoče pogovore tako, da prenesete vrnjeni conversation_id. Parametri odgovorov in predloge so odvisni od nastavitev Dify Prompt Eng.',
createChatApi: 'Ustvari klepetno sporočilo',
createChatApiTip: 'Ustvari novo pogovorno sporočilo ali nadaljuj obstoječi pogovor.',
inputsTips: '(Neobvezno) Navedite vnosna polja uporabnikov kot ključ-vrednost pare, ki ustrezajo spremenljivkam v Prompt Eng. Ključ je ime spremenljivke, vrednost pa vrednost parametra. Če je vrsta polja Izberi, mora biti posredovana vrednost ena izmed vnaprej določenih možnosti.',
queryTips: 'Vsebina vnosa/uporabniškega vprašanja',
blocking: 'Vrsta blokiranja, čakanje na dokončanje izvajanja in vračanje rezultatov. (Zahteve se lahko prekinejo, če je postopek dolg)',
streaming: 'streaming povratki. Implementacija povratkov pretakanja na podlagi SSE (Server-Sent Events).',
conversationIdTip: '(Neobvezno) ID pogovora: pustite prazno za prvi pogovor; prenesite conversation_id iz konteksta, da nadaljujete dialog.',
messageFeedbackApi: 'Povratne informacije končnih uporabnikov o sporočilu, všeč',
messageFeedbackApiTip: 'Ocenite prejeta sporočila v imenu končnih uporabnikov z všečki ali nevšečki. Ti podatki so vidni na strani Dnevniki in opombe ter se uporabljajo za nadaljnje fino prilagajanje modela.',
messageIDTip: 'ID sporočila',
ratingTip: 'všeč ali nevšeč, null je preklic',
chatMsgHistoryApi: 'Pridobi zgodovino klepetnih sporočil',
chatMsgHistoryApiTip: 'Prva stran vrne najnovejše `limit` zapise, ki so v obratnem vrstnem redu.',
chatMsgHistoryConversationIdTip: 'ID pogovora',
chatMsgHistoryFirstId: 'ID prvega klepeta na trenutni strani. Privzeto ni.',
chatMsgHistoryLimit: 'Koliko klepetov je vrnjenih na eno zahtevo',
conversationsListApi: 'Pridobi seznam pogovorov',
conversationsListApiTip: 'Pridobi seznam sej trenutnega uporabnika. Privzeto je vrnjenih zadnjih 20 sej.',
conversationsListFirstIdTip: 'ID zadnjega zapisa na trenutni strani, privzeto ni.',
conversationsListLimitTip: 'Koliko klepetov je vrnjenih na eno zahtevo',
conversationRenamingApi: 'Preimenovanje pogovora',
conversationRenamingApiTip: 'Preimenujte pogovore; ime je prikazano v večsejnih odjemalskih vmesnikih.',
conversationRenamingNameTip: 'Novo ime',
parametersApi: 'Pridobite informacije o parametrih aplikacije',
parametersApiTip: 'Pridobite konfigurirane vhodne parametre, vključno z imeni spremenljivk, imeni polj, vrstami in privzetimi vrednostmi. Običajno se uporablja za prikaz teh polj v obrazcu ali izpolnjevanje privzetih vrednosti po nalaganju odjemalca.',
},
develop: {
requestBody: 'Telo zahteve',
pathParams: 'Parametri poti',
query: 'Poizvedba',
},
}
export default translation

242
web/i18n/sl-SI/app-debug.ts Normal file
View File

@ -0,0 +1,242 @@
const translation = {
pageTitle: {
line1: 'PROMPT',
line2: 'Inženiring',
},
orchestrate: 'Orkestriraj',
promptMode: {
simple: 'Preklopi na strokovni način, da urejaš celoten PROMPT',
advanced: 'Strokovni način',
switchBack: 'Preklopi nazaj',
advancedWarning: {
title: 'Preklopil si na strokovni način. Ko spremeniš PROMPT, ne moreš več preklopiti nazaj v osnovni način.',
description: 'V strokovnem načinu lahko urejaš celoten PROMPT.',
learnMore: 'Preberi več',
ok: 'V redu',
},
operation: {
addMessage: 'Dodaj sporočilo',
},
contextMissing: 'Manjka komponenta konteksta, zato učinkovitost PROMPT-a morda ne bo najboljša.',
},
operation: {
applyConfig: 'Objavi',
resetConfig: 'Ponastavi',
debugConfig: 'Odpravljanje napak',
addFeature: 'Dodaj funkcionalnost',
automatic: 'Generiraj',
stopResponding: 'Prenehaj odgovarjati',
agree: 'všeč',
disagree: 'ni všeč',
cancelAgree: 'Prekliči všeček',
cancelDisagree: 'Prekliči nevšečnost',
userAction: 'Uporabnik ',
},
notSetAPIKey: {
title: 'Ključ ponudnika LLM ni nastavljen',
trailFinished: 'Preizkus končan',
description: 'Ključ ponudnika LLM ni nastavljen. Pred odpravljanjem napak je treba nastaviti ključ.',
settingBtn: 'Pojdi v nastavitve',
},
trailUseGPT4Info: {
title: 'GPT-4 trenutno ni podprt',
description: 'Za uporabo GPT-4 je treba nastaviti API ključ.',
},
feature: {
groupChat: {
title: 'Izboljšanje klepeta',
description: 'Dodajanje prednastavitev klepeta lahko izboljša uporabniško izkušnjo.',
},
groupExperience: {
title: 'Izboljšanje izkušnje',
},
conversationOpener: {
title: 'Začetek pogovora',
description: 'V klepetu AI običajno začne pogovor z uporabnikom z dobrodošlico.',
},
suggestedQuestionsAfterAnswer: {
title: 'Nadaljnja vprašanja',
description: 'Nastavitev predlogov za naslednja vprašanja lahko uporabnikom izboljša klepet.',
resDes: '3 predlogi za naslednje vprašanje uporabnika.',
tryToAsk: 'Poskusi vprašati',
},
moreLikeThis: {
title: 'Več takšnih',
description: 'Ustvari več besedil naenkrat, nato pa jih urejaj in nadaljuj z ustvarjanjem.',
generateNumTip: 'Število generacij vsakič',
tip: 'Uporaba te funkcije povzroča dodatno porabo žetonov.',
},
speechToText: {
title: 'Govor v besedilo',
description: 'Ko je omogočeno, lahko uporabljaš glasovni vnos.',
resDes: 'Glasovni vnos je omogočen.',
},
textToSpeech: {
title: 'Besedilo v govor',
description: 'Ko je omogočeno, lahko besedilo pretvoriš v govor.',
resDes: 'Pretvorba besedila v zvok je omogočena.',
},
citation: {
title: 'Citati in pripisovanja',
description: 'Ko je omogočeno, prikaži izvorni dokument in pripisani del generirane vsebine.',
resDes: 'Citati in pripisovanja so omogočeni.',
},
annotation: {
title: 'Odgovor z opombami',
description: 'Ročno lahko dodate visokokakovostne odgovore v predpomnilnik za prednostno ujemanje s podobnimi vprašanji uporabnikov.',
resDes: 'Odgovor z opombami je omogočen.',
scoreThreshold: {
title: 'Prag ujemanja',
description: 'Uporabljeno za nastavitev praga podobnosti za odgovor z opombami.',
easyMatch: 'Lahko ujemanje',
accurateMatch: 'Natančno ujemanje',
},
matchVariable: {
title: 'Spremenljivka za ujemanje',
choosePlaceholder: 'Izberi spremenljivko za ujemanje',
},
cacheManagement: 'Upravljanje opomb',
cached: 'Z opombo',
remove: 'Odstrani',
removeConfirm: 'Izbrisati to opombo?',
add: 'Dodaj opombo',
edit: 'Uredi opombo',
},
dataSet: {
title: 'Kontekst',
noData: 'Uvozi znanje kot kontekst',
words: 'Besede',
textBlocks: 'Bloki besedila',
selectTitle: 'Izberi referenčno znanje',
selected: 'Izbrano znanje',
noDataSet: 'Znanje ni bilo najdeno',
toCreate: 'Pojdi na ustvarjanje',
notSupportSelectMulti: 'Trenutno je podprto le eno znanje',
queryVariable: {
title: 'Spremenljivka poizvedbe',
tip: 'Ta spremenljivka bo uporabljena kot vnos poizvedbe za pridobitev kontekstnih informacij.',
choosePlaceholder: 'Izberi spremenljivko poizvedbe',
noVar: 'Ni spremenljivk',
noVarTip: 'ustvari spremenljivko v razdelku Spremenljivke',
unableToQueryDataSet: 'Neuspešna poizvedba po znanju',
unableToQueryDataSetTip: 'Neuspešna poizvedba po znanju, izberi spremenljivko poizvedbe v razdelku kontekst.',
ok: 'V redu',
contextVarNotEmpty: 'Spremenljivka poizvedbe ne sme biti prazna',
deleteContextVarTitle: 'Izbrisati spremenljivko “{{varName}}”?',
deleteContextVarTip: 'Ta spremenljivka je nastavljena kot spremenljivka za poizvedbo po kontekstu. Če jo odstraniš, bo to vplivalo na uporabo znanja. Če jo želiš izbrisati, ponovno izberi v razdelku kontekst.',
},
},
tools: {
title: 'Orodja',
tips: 'Orodja nudijo standardiziran način klicanja API-jev, pri čemer se uporabniški vnos ali spremenljivke uporabijo kot parametri za poizvedovanje zunanjih podatkov.',
toolsInUse: '{{count}} orodij v uporabi',
modal: {
title: 'Orodje',
toolType: {
title: 'Tip orodja',
placeholder: 'Izberi tip orodja',
},
name: {
title: 'Ime',
placeholder: 'Vnesi ime',
},
variableName: {
title: 'Ime spremenljivke',
placeholder: 'Vnesi ime spremenljivke',
},
},
},
conversationHistory: {
title: 'Zgodovina pogovorov',
description: 'Nastavi predpone imen za vloge v pogovoru',
tip: 'Zgodovina pogovorov ni omogočena. Dodaj <histories> v zgornji PROMPT.',
learnMore: 'Preberi več',
editModal: {
title: 'Uredi imena vlog v pogovoru',
userPrefix: 'Predpona uporabnika',
assistantPrefix: 'Predpona pomočnika',
},
},
toolbox: {
title: 'ORODJA',
},
moderation: {
title: 'Moderiranje vsebine',
description: 'Zagotovi varno izhodno vsebino s pomočjo API-ja za moderiranje ali vzdrževanja seznama občutljivih besed.',
allEnabled: 'VSEBINA VNOSA/IZHODA omogočena',
inputEnabled: 'VSEBINA VNOSA omogočena',
outputEnabled: 'VSEBINA IZHODA omogočena',
modal: {
title: 'Nastavitve moderiranja vsebine',
provider: {
title: 'Ponudnik',
openai: 'OpenAI Moderiranje',
openaiTip: {
prefix: 'OpenAI Moderiranje zahteva nastavljen API ključ pri ',
suffix: '.',
},
keywords: 'Ključne besede',
},
keywords: {
tip: 'Vsaka beseda na lastni vrstici, ločena z vrsticami. Največ 100 znakov na vrstico.',
placeholder: 'Vsaka beseda na lastni vrstici, ločena z vrsticami',
line: 'Vrstica',
},
content: {
input: 'Moderiraj VSEBINO VNOSA',
output: 'Moderiraj VSEBINO IZHODA',
},
},
},
debug: {
title: 'Odpravljanje napak',
description: 'Debugiranje omogoča pregled podrobnih informacij, kot so podatki API-jev, vklop dnevnikov, opozorila in še več.',
},
agent: {
title: 'Pomočnik',
description: 'Osnovne informacije in odgovorne naloge pomočnika.',
prompts: 'Temeljni PROMPT',
message: {
title: 'Vrstice sporočila',
user: 'Uporabnik',
assistant: 'Pomočnik',
},
},
history: {
title: 'Zgodovina',
notFound: 'Zgodovina ni bila najdena',
notOpen: 'Zgodovina ni odprta',
},
prompt: {
title: 'Vsebina PROMPT-a',
},
message: {
title: 'Sporočilo',
description: 'Način nastavitve formatiranega pogovora.',
tryChat: 'Preizkusi klepet',
},
theme: {
title: 'Tema',
themes: {
default: 'Osnovna tema',
light: 'Svetla tema',
dark: 'Temna tema',
custom: 'Prilagodi temo',
},
modal: {
title: 'Nastavitve teme',
primaryColor: {
title: 'Primarna barva',
placeholder: 'Izberi primarno barvo',
},
textColor: {
title: 'Barva besedila',
placeholder: 'Izberi barvo besedila',
},
ok: 'V redu',
},
},
},
}
module.exports = translation

95
web/i18n/sl-SI/app-log.ts Normal file
View File

@ -0,0 +1,95 @@
const translation = {
title: 'Dnevniki',
description: 'Dnevniki beležijo stanje delovanja aplikacije, vključno z vnosi uporabnikov in odgovori umetne inteligence.',
dateTimeFormat: 'DD.MM.YYYY hh:mm A',
table: {
header: {
updatedTime: 'Čas posodobitve',
time: 'Čas ustvarjanja',
endUser: 'Končni uporabnik ali račun',
input: 'Vnos',
output: 'Izhod',
summary: 'Naslov',
messageCount: 'Število sporočil',
userRate: 'Ocena uporabnika',
adminRate: 'Ocena operaterja',
startTime: 'ZAČETNI ČAS',
status: 'STATUS',
runtime: 'ČAS DELOVANJA',
tokens: 'ŽETONI',
user: 'Končni uporabnik ali račun',
version: 'VERZIJA',
},
pagination: {
previous: 'Prejšnja',
next: 'Naslednja',
},
empty: {
noChat: 'Še ni pogovora',
noOutput: 'Ni izhoda',
element: {
title: 'Je kdo tam?',
content: 'Opazujte in označite interakcije med končnimi uporabniki in aplikacijami umetne inteligence, da stalno izboljšujete natančnost AI. Lahko <shareLink>delite</shareLink> ali <testLink>preizkusite</testLink> spletno aplikacijo sami, nato pa se vrnete na to stran.',
},
},
},
detail: {
time: 'Čas',
conversationId: 'ID pogovora',
promptTemplate: 'Predloga PROMPT-a',
promptTemplateBeforeChat: 'Predloga PROMPT-a pred pogovorom · Kot sistemsko sporočilo',
annotationTip: 'Izboljšave, ki jih je označil {{user}}',
timeConsuming: 'Porabljen čas',
second: 's',
tokenCost: 'Porabljeni žetoni',
loading: 'nalaganje',
operation: {
like: 'všeč',
dislike: 'ni všeč',
addAnnotation: 'Dodaj izboljšavo',
editAnnotation: 'Uredi izboljšavo',
annotationPlaceholder: 'Vnesite pričakovan odgovor, ki ga želite, da AI odgovori, kar se lahko uporabi za izboljšanje modela in kakovosti generiranja besedil v prihodnje.',
},
variables: 'Spremenljivke',
uploadImages: 'Naložene slike',
},
filter: {
period: {
today: 'Danes',
last7days: 'Zadnjih 7 dni',
last4weeks: 'Zadnje 4 tedne',
last3months: 'Zadnji 3 meseci',
last12months: 'Zadnjih 12 mesecev',
monthToDate: 'Mesec do danes',
quarterToDate: 'Četrtletje do danes',
yearToDate: 'Leto do danes',
allTime: 'Vse obdobje',
},
annotation: {
all: 'Vse',
annotated: 'Označene izboljšave ({{count}} elementov)',
not_annotated: 'Neoznačene',
},
sortBy: 'Razvrsti po:',
descending: 'padajoče',
ascending: 'naraščajoče',
},
workflowTitle: 'Dnevniki poteka dela',
workflowSubtitle: 'Dnevnik beleži delovanje avtomatizacije.',
runDetail: {
title: 'Dnevnik pogovora',
workflowTitle: 'Podrobnosti dnevnika',
},
promptLog: 'Dnevnik PROMPT-ov',
agentLog: 'Dnevnik pomočnika',
viewLog: 'Ogled dnevnika',
agentLogDetail: {
agentMode: 'Način pomočnika',
toolUsed: 'Uporabljeno orodje',
iterations: 'Iteracije',
iteration: 'Iteracija',
finalProcessing: 'Končna obdelava',
},
}
export default translation

Some files were not shown because too many files have changed in this diff Show More