Naruto123321 commited on
Commit
d7527be
·
1 Parent(s): 1d7c988
app.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ from languageexport.crew import LanguagesExport
4
+ import tempfile
5
+ import os
6
+
7
+ def process_excel(file, output_name):
8
+ if not file or not output_name.strip():
9
+ return "Please upload a file and provide a valid name.", None, None
10
+
11
+ try:
12
+ df = pd.read_excel(file.name)
13
+ table = [df.columns.tolist()] + df.values.tolist()
14
+
15
+ result = LanguagesExport().crew().kickoff(inputs={"data": table})
16
+ result_df = pd.DataFrame(data=result["data"][1:], columns=result["data"][0])
17
+
18
+ temp_dir = tempfile.mkdtemp()
19
+ output_file_path = os.path.join(temp_dir, f"{output_name.strip()}.xlsx")
20
+ result_df.to_excel(output_file_path, index=False)
21
+
22
+ return "✅ Export completed successfully!", result_df, output_file_path
23
+
24
+ except Exception as e:
25
+ return f"❌ Error: {str(e)}", None, None
26
+
27
+
28
+ def show_input_table(file):
29
+ if file is None:
30
+ return gr.update(visible=True, value=None)
31
+ try:
32
+ df = pd.read_excel(file.name)
33
+ return gr.update(visible=True, value=df)
34
+ except Exception as e:
35
+ return gr.update(visible=True, value=None)
36
+
37
+ with gr.Blocks() as demo:
38
+ gr.Markdown("# 📄 Language Export Assistant")
39
+ gr.Markdown("Upload an Excel file, define the export filename, and run the export process.")
40
+
41
+ with gr.Row():
42
+ file_input = gr.File(label="Upload Excel File", file_types=[".xlsx", ".xls"])
43
+ file_name = gr.Textbox(label="Output file name (without extension)", placeholder="e.g. translated_table")
44
+
45
+ run_button = gr.Button("Run Export")
46
+
47
+ status_output = gr.Textbox(label="Status", interactive=False)
48
+
49
+ # Luôn hiển thị layout, chỉ update nội dung
50
+ with gr.Row():
51
+ table_input = gr.Dataframe(label="Input Table")
52
+ table_output = gr.Dataframe(label="Result Table")
53
+
54
+ download_output = gr.File(label="Download Result File", visible=False)
55
+
56
+ file_input.change(fn=show_input_table, inputs=file_input, outputs=table_input)
57
+
58
+ def on_run(file, name):
59
+ status, df, path = process_excel(file, name)
60
+ is_valid_df = df is not None and not df.empty
61
+ return (
62
+ status,
63
+ gr.update(value=df if is_valid_df else None),
64
+ gr.update(value=path if path else None, visible=path is not None),
65
+ )
66
+
67
+ run_button.click(on_run, inputs=[file_input, file_name], outputs=[status_output, table_output, download_output])
68
+
69
+ if __name__ == "__main__":
70
+ demo.launch(share=True)
languageexport/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (157 Bytes). View file
 
languageexport/__pycache__/crew.cpython-312.pyc ADDED
Binary file (2.73 kB). View file
 
languageexport/__pycache__/flow.cpython-312.pyc ADDED
Binary file (3.34 kB). View file
 
languageexport/__pycache__/main.cpython-312.pyc ADDED
Binary file (4.07 kB). View file
 
languageexport/config/agents.yaml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ translator_researcher:
2
+ role: >
3
+ Translation Data Specialist & Localization Engineer
4
+ (Expert Level)
5
+ goal: >
6
+ Ensure the entire 2D translation table is accurately completed:
7
+ - Automatically generate and refine any missing English phrases from the 'String' keys.
8
+ - Accurately fill all remaining translation cells with fluent, natural translations in Title Case, without copying English phrases directly.
9
+ - Preserve the table's structure exactly (no new columns, no reordering).
10
+ backstory: >
11
+ You are a translation and localization expert with 20 years of experience working on multilingual software projects.
12
+ You have reviewed tens of thousands of translation entries across over 40 languages.
13
+ You master the principles of high-quality localization and take extra care to avoid machine-like or unnatural results.
14
+ Your working style is meticulous—reviewing every cell without omission, never altering or adding columns unnecessarily.
15
+ You always double-check every translation
16
+ You never leave cells half-done.
17
+ You **never** assume a missing language exists.
18
+ Your translations feel human — thoughtful, localized, and clean.
19
+
languageexport/config/tasks.yaml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ research_task:
2
+ description: >
3
+ You will be given {data}, a 2D Python List[List[str|None]] structured as follows:
4
+ - Row 0 is the header: the first column is always 'String', and the rest are language names.
5
+ - Rows 1…n contain translation data for each key.
6
+ YOU MUST identify the list of language columns **explicitly** from the header row for translating later.
7
+ ONLY and must translate into languages that are actually present — do NOT assume or invent or copy (for example copy English phase to French language).
8
+
9
+ Your responsibilities:
10
+ 1. Parse the headers to identify all **existing** language columns.
11
+ → DO NOT assume the existence of any column unless explicitly present.
12
+ → DO NOT create new columns (e.g., 'English').
13
+
14
+ 2. For each row:
15
+ a. Derive the English phrase from the 'String' key:
16
+ - Remove the prefix 'STR_'
17
+ - Replace all underscores with spaces
18
+ - Convert the phrase to Title Case
19
+ b. Use this derived phrase as the translation base.
20
+ c. IMPORTANT STEP: For each language cell:
21
+ - If the cell is:
22
+ • Empty
23
+ • Null
24
+ • Whitespace
25
+ • **OR exactly matches `english_phrase`** (**CRITICAL**: this is not a valid translation!)
26
+ → Then translate `english_phrase` into the TARGET LANGUAGE.
27
+ → The translation must:
28
+ • Be natural and fluent
29
+ • Match Title Case
30
+ • Contain **no** extra punctuation, quotes, or added words
31
+ - Otherwise: leave the cell unchanged.
32
+ expected_output: >
33
+ A 2D Python `List[List[str]]` of identical shape where:
34
+ - All originally missing translation cells are now correctly filled
35
+ - Table structure is preserved exactly (no added columns, no reordering)
36
+ - Existing non-empty translations remain unchanged
37
+ - All derived English phrases are used strictly as translation bases
38
+ - All new translations follow capitalization and output rules strictly
39
+ agent: translator_researcher
languageexport/crew.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent, Crew, Process, Task,LLM
2
+ from crewai.project import CrewBase, agent, crew, task
3
+ import os
4
+ from languageexport.tools.custom_tool import SaveTranslationInput
5
+ import pandas as pd
6
+ os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
7
+ os.environ["OPENROUTER_API_KEY"] = os.getenv("OPENROUTER_API_KEY")
8
+ name_0="openrouter/tngtech/deepseek-r1t-chimera:free"
9
+ name_z="openrouter/meta-llama/llama-4-scout:free"
10
+ name="openai/gpt-4.1-mini-2025-04-14"
11
+ llm=LLM(
12
+ model=name_z,
13
+ temperature=0.0,
14
+ )
15
+ import yaml
16
+
17
+ @CrewBase
18
+ class LanguagesExport():
19
+ def __init__(self):
20
+ agents_config = yaml.safe_load(open(r'D:\CrewAI\crew\languageexport\src\languageexport\config\agents.yaml', encoding='utf-8'))
21
+ tasks_config = yaml.safe_load(open(r'D:\CrewAI\crew\languageexport\src\languageexport\config\tasks.yaml', encoding='utf-8'))
22
+ @agent
23
+ def translator_researcher(self) -> Agent:
24
+ return Agent(
25
+ config=self.agents_config['translator_researcher'],
26
+ llm=llm,
27
+ verbose=True
28
+ )
29
+
30
+ @task
31
+ def research_task(self) -> Task:
32
+ return Task(
33
+ config=self.tasks_config['research_task'],
34
+ output_pydantic=SaveTranslationInput,
35
+ )
36
+
37
+ @crew
38
+ def crew(self) -> Crew:
39
+ return Crew(
40
+ agents=[self.translator_researcher()],
41
+ tasks=[self.research_task()],
42
+ process=Process.sequential,
43
+ verbose=True
44
+ )
languageexport/flow.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai.flow.flow import Flow,listen,start
2
+ import json
3
+ import os
4
+ from typing import List, Dict,Any
5
+ from pydantic import BaseModel, Field
6
+ from crewai.flow.flow import Flow, listen, start
7
+ import pandas as pd
8
+ from languageexport.crew import LanguagesExport
9
+ class OutputFile(Flow):
10
+ @start()
11
+ def get_data(self):
12
+ path = input("Enter path to your Excel file (e.g., full_translations.xlsx): ").strip()
13
+ if not os.path.exists(path):
14
+ raise FileNotFoundError(f"File not found: {path}")
15
+ df = pd.read_excel(path)
16
+ print(f"Loaded {path} with shape {df.shape}")
17
+ table = [df.columns.tolist()] + df.values.tolist()
18
+ self.state['table'] = table
19
+ return table
20
+
21
+ @listen(get_data)
22
+ def ask_filename(self, table: List[List[Any]]):
23
+ filename = input("Enter desired output filename (with .xlsx extension): ").strip()
24
+ if not filename.lower().endswith('.xlsx'):
25
+ filename += '.xlsx'
26
+ self.state['filename'] = filename
27
+ return table
28
+
29
+ @listen(ask_filename)
30
+ def create_file(self, table: List[List[Any]]):
31
+ filename = self.state['filename']
32
+ result = LanguagesExport().crew().kickoff(inputs={'data': table, 'filename': filename})
33
+ self.state['result'] = result
34
+ print(f"Agent returned: {result}")
35
+ if os.path.exists(filename):
36
+ print(f"Output file created: {filename}")
37
+ else:
38
+ print(f"Expected output file not found: {filename}")
39
+ return filename
40
+
41
+ @listen(create_file)
42
+ def show_file(self, filename: str):
43
+ df = pd.read_excel(filename)
44
+ print("✅ Translated content:")
45
+ print(df)
46
+ return df
languageexport/main.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ import sys
3
+ import warnings
4
+
5
+ from datetime import datetime
6
+ from typing import List, Dict, Any
7
+
8
+ import os
9
+
10
+ import json
11
+ from pydantic import BaseModel, Field
12
+ from languageexport.flow import OutputFile
13
+ from languageexport.crew import LanguagesExport
14
+ import pandas as pd
15
+ import tkinter as Tk
16
+ from tkinter import Tk
17
+
18
+ from tkinter import filedialog
19
+ from tkinter import messagebox
20
+ from tkinter.filedialog import askopenfilename, asksaveasfilename
21
+ warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
22
+
23
+ def run():
24
+ """
25
+ Run the crew.
26
+ """
27
+ Tk().withdraw()
28
+
29
+ # Mở hộp thoại chọn file
30
+ print("Vui lòng chọn file Excel đầu vào")
31
+
32
+ file_path = askopenfilename(
33
+ title="Chọn file Excel đầu vào",
34
+ filetypes=[("Excel files", "*.xlsx *.xls")]
35
+ )
36
+ print(f"đường dẫn:{file_path}")
37
+ file_name=input("Enter the file name: ")
38
+ file_name_save=f"{file_name}.xlsx"
39
+ df= pd.read_excel(file_path)
40
+ table = [df.columns.tolist()] + df.values.tolist()
41
+ print(table)
42
+ rs=LanguagesExport().crew().kickoff(inputs={'data':table})
43
+ df = pd.DataFrame(data=rs["data"][1:], columns=rs["data"][0])
44
+ df.to_excel(file_name_save, index=False)
45
+
46
+ def train():
47
+ """
48
+ Train the crew for a given number of iterations.
49
+ """
50
+
51
+ inputs = {
52
+ 'data':'table'
53
+ }
54
+ try:
55
+ LanguagesExport().crew().train(n_iterations=int(sys.argv[1]), filename=sys.argv[2], inputs=inputs)
56
+
57
+ except Exception as e:
58
+ raise Exception(f"An error occurred while training the crew: {e}")
59
+
60
+ def replay():
61
+ """
62
+ Replay the crew execution from a specific task.
63
+ """
64
+ try:
65
+ LanguagesExport().crew().replay(task_id=sys.argv[1])
66
+
67
+ except Exception as e:
68
+ raise Exception(f"An error occurred while replaying the crew: {e}")
69
+
70
+ def test():
71
+ """
72
+ Test the crew execution and returns the results.
73
+ """
74
+ inputs = {
75
+ "topic": "AI LLMs",
76
+ "current_year": str(datetime.now().year)
77
+ }
78
+ try:
79
+ LanguagesExport().crew().test(n_iterations=int(sys.argv[1]), openai_model_name=sys.argv[2], inputs=inputs)
80
+
81
+ except Exception as e:
82
+ raise Exception(f"An error occurred while testing the crew: {e}")
languageexport/tools/__init__.py ADDED
File without changes
languageexport/tools/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (163 Bytes). View file
 
languageexport/tools/__pycache__/custom_tool.cpython-312.pyc ADDED
Binary file (820 Bytes). View file
 
languageexport/tools/custom_tool.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from crewai.tools import BaseTool
2
+ from typing import Type
3
+ from pydantic import BaseModel, Field
4
+ from typing import List, Any,Annotated
5
+ import pandas as pd
6
+ class SaveTranslationInput(BaseModel):
7
+ data: List[List[Any]] = Field(..., description="2D list representing the full translation table. The first row is the header.",strict=True)
pyproject.toml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "languageexport"
3
+ version = "0.1.0"
4
+ description = "LanguageExport using crewAI"
5
+ authors = [{ name = "Your Name", email = "you@example.com" }]
6
+ requires-python = ">=3.10,<3.13"
7
+ dependencies = [
8
+ "crewai[tools]>=0.114.0,<1.0.0",
9
+ "gradio>=5.25.2",
10
+ "pandas>=2.2.3",
11
+ "tk>=0.1.0",
12
+ ]
13
+
14
+ [project.scripts]
15
+ languageexport = "languageexport.main:run"
16
+ run_crew = "languageexport.main:run"
17
+ train = "languageexport.main:train"
18
+ replay = "languageexport.main:replay"
19
+ test = "languageexport.main:test"
20
+
21
+ [build-system]
22
+ requires = ["hatchling"]
23
+ build-backend = "hatchling.build"
24
+
25
+ [tool.crewai]
26
+ type = "crew"
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ crewai[tools]>=0.114.0,<1.0.0
2
+ gradio>=5.25.2
3
+ pandas>=2.2.3
4
+ tk
5
+ openpyxl
6
+ pyyaml
7
+ numpy
uv.lock ADDED
The diff for this file is too large to render. See raw diff