Sara Han commited on
Commit
0d14ea5
·
unverified ·
1 Parent(s): 3ba754d

Add RAG generation (#19)

Browse files

* feat: add pipelines for RAG

* feat: add the app for rag

* feat: update required dependencies

* feat: update add rag tab

* fix: correct unstructured dependency

* fix: fix layout, arg and input errors

* fix: rename generator

* feat: generate without ground data

* organize dependencies and add pydantic version

* update with feedback

* fix errors and update with latest changes

* remove temperature as value ini pipeline code

* fix pipeline errors

* update TODOs and review prompt generator

* Update READMES

* remove unneeded imports

* use llm.dump() instead of llm.model_dump()

* fix pipeline code

* apply feedback

* fix progress, messages and clear buttons

README.md CHANGED
@@ -34,6 +34,7 @@ Supported Tasks:
34
 
35
  - Text Classification
36
  - Chat Data for Supervised Fine-Tuning
 
37
 
38
  This tool simplifies the process of creating custom datasets, enabling you to:
39
 
 
34
 
35
  - Text Classification
36
  - Chat Data for Supervised Fine-Tuning
37
+ - Retrieval Augmented Generation
38
 
39
  This tool simplifies the process of creating custom datasets, enabling you to:
40
 
pyproject.toml CHANGED
@@ -18,13 +18,15 @@ readme = "README.md"
18
  license = {text = "Apache 2"}
19
 
20
  dependencies = [
 
21
  "distilabel[argilla,hf-inference-endpoints,hf-transformers,instructor,llama-cpp,ollama,openai,outlines,vllm] @ git+https://github.com/argilla-io/distilabel.git@develop",
22
  "gradio[oauth]>=5.4.0,<6.0.0",
23
- "transformers>=4.44.2,<5.0.0",
24
- "sentence-transformers>=3.2.0,<4.0.0",
25
- "model2vec>=0.2.4,<1.0.0",
26
  "gradio-huggingfacehub-search>=0.0.12,<1.0.0",
27
- "argilla>=2.4.0,<3.0.0",
 
 
 
 
28
  ]
29
 
30
  [build-system]
 
18
  license = {text = "Apache 2"}
19
 
20
  dependencies = [
21
+ "argilla>=2.4.0,<3.0.0",
22
  "distilabel[argilla,hf-inference-endpoints,hf-transformers,instructor,llama-cpp,ollama,openai,outlines,vllm] @ git+https://github.com/argilla-io/distilabel.git@develop",
23
  "gradio[oauth]>=5.4.0,<6.0.0",
 
 
 
24
  "gradio-huggingfacehub-search>=0.0.12,<1.0.0",
25
+ "model2vec>=0.2.4,<1.0.0",
26
+ "pydantic>=2.10.5,<3.0.0",
27
+ "sentence-transformers>=3.2.0,<4.0.0",
28
+ "transformers>=4.44.2,<5.0.0",
29
+ "unstructured[md,pdf,docx]>=0.16.0,<1.0.0",
30
  ]
31
 
32
  [build-system]
src/synthetic_dataset_generator/_distiset.py CHANGED
@@ -92,7 +92,22 @@ class CustomDistisetWithAdditionalTag(distilabel.distiset.Distiset):
92
  elif ("prompt" in columns and "completion" in columns) or (
93
  "messages" in columns
94
  ):
95
- task_categories: list[str] = ["text-generation", "text2text-generation"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  else:
97
  task_categories: list[str] = []
98
  gr.Info(
 
92
  elif ("prompt" in columns and "completion" in columns) or (
93
  "messages" in columns
94
  ):
95
+ task_categories: list[str] = [
96
+ "text-generation",
97
+ "text2text-generation",
98
+ "question-answering",
99
+ ]
100
+ elif "context" in columns and "question" in columns and "response" in columns:
101
+ task_categories: list[str] = [
102
+ "text-generation",
103
+ "text2text-generation",
104
+ "text-retrieval",
105
+ "question-answering"
106
+ ]
107
+ if (
108
+ "positive_retrieval" in columns and "negative_retrieval" in columns
109
+ ) or ("positive_reranking" in columns and "negative_reranking" in columns):
110
+ task_categories.append("sentence-similarity")
111
  else:
112
  task_categories: list[str] = []
113
  gr.Info(
src/synthetic_dataset_generator/app.py CHANGED
@@ -1,6 +1,7 @@
1
  from synthetic_dataset_generator._tabbedinterface import TabbedInterface
2
 
3
  # from synthetic_dataset_generator.apps.eval import app as eval_app
 
4
  from synthetic_dataset_generator.apps.about import app as about_app
5
  from synthetic_dataset_generator.apps.chat import app as chat_app
6
  from synthetic_dataset_generator.apps.textcat import app as textcat_app
@@ -22,8 +23,8 @@ button[role="tab"][aria-selected="true"]:hover {border-color: var(--button-prima
22
  image = """<br><img src="https://raw.githubusercontent.com/argilla-io/synthetic-data-generator/main/assets/logo.svg" alt="Synthetic Data Generator Logo" style="display: block; margin-left: auto; margin-right: auto; width: clamp(50%, 400px, 100%)"/>"""
23
 
24
  demo = TabbedInterface(
25
- [textcat_app, chat_app, about_app],
26
- ["Text Classification", "Chat Data", "About"],
27
  css=css,
28
  title=image,
29
  theme=theme,
 
1
  from synthetic_dataset_generator._tabbedinterface import TabbedInterface
2
 
3
  # from synthetic_dataset_generator.apps.eval import app as eval_app
4
+ from synthetic_dataset_generator.apps.rag import app as rag_app
5
  from synthetic_dataset_generator.apps.about import app as about_app
6
  from synthetic_dataset_generator.apps.chat import app as chat_app
7
  from synthetic_dataset_generator.apps.textcat import app as textcat_app
 
23
  image = """<br><img src="https://raw.githubusercontent.com/argilla-io/synthetic-data-generator/main/assets/logo.svg" alt="Synthetic Data Generator Logo" style="display: block; margin-left: auto; margin-right: auto; width: clamp(50%, 400px, 100%)"/>"""
24
 
25
  demo = TabbedInterface(
26
+ [textcat_app, chat_app, rag_app, about_app],
27
+ ["Text Classification", "Chat Data", "RAG", "About"],
28
  css=css,
29
  title=image,
30
  theme=theme,
src/synthetic_dataset_generator/apps/about.py CHANGED
@@ -7,7 +7,7 @@ with gr.Blocks() as app:
7
 
8
  Introducing the Synthetic Data Generator, a user-friendly application that takes a no-code approach to creating custom datasets with Large Language Models (LLMs). The best part: A simple step-by-step process, making dataset creation a non-technical breeze, allowing anyone to create datasets and models in minutes and without any code.
9
 
10
- The synthetic data generator takes your custom prompt and returns a dataset for your use case, using a synthetic data pipeline. In the background this is powered by [distilabel](https://distilabel.argilla.io/latest/) and the [free Hugging Face text-generation API](https://huggingface.co/docs/api-inference/en/index) but we dont need to worry about these complexities and we can focus on using the UI.
11
 
12
  - Read more in [our announcement blog post](https://huggingface.co/blog/synthetic-data-generator)
13
  - Find the library on [GitHub](https://github.com/argilla-io/synthetic-data-generator)
 
7
 
8
  Introducing the Synthetic Data Generator, a user-friendly application that takes a no-code approach to creating custom datasets with Large Language Models (LLMs). The best part: A simple step-by-step process, making dataset creation a non-technical breeze, allowing anyone to create datasets and models in minutes and without any code.
9
 
10
+ The synthetic data generator takes your custom prompt and returns a dataset for your use case, using a synthetic data pipeline. In the background this is powered by [distilabel](https://distilabel.argilla.io/latest/) and the [free Hugging Face text-generation API](https://huggingface.co/docs/api-inference/en/index) but we don't need to worry about these complexities and we can focus on using the UI.
11
 
12
  - Read more in [our announcement blog post](https://huggingface.co/blog/synthetic-data-generator)
13
  - Find the library on [GitHub](https://github.com/argilla-io/synthetic-data-generator)
src/synthetic_dataset_generator/apps/base.py CHANGED
@@ -6,7 +6,7 @@ import argilla as rg
6
  import gradio as gr
7
  from datasets import Dataset, concatenate_datasets, load_dataset
8
  from gradio import OAuthToken
9
- from huggingface_hub import HfApi, upload_file
10
 
11
  from synthetic_dataset_generator.constants import MAX_NUM_ROWS
12
  from synthetic_dataset_generator.utils import get_argilla_client
@@ -18,7 +18,7 @@ def validate_argilla_user_workspace_dataset(
18
  oauth_token: Union[OAuthToken, None] = None,
19
  progress=gr.Progress(),
20
  ) -> str:
21
- progress(0, desc="Validating dataset configuration")
22
  hf_user = HfApi().whoami(token=oauth_token.token)["name"]
23
  client = get_argilla_client()
24
  if dataset_name is None or dataset_name == "":
@@ -38,6 +38,7 @@ def validate_argilla_user_workspace_dataset(
38
  dataset = client.datasets(name=dataset_name, workspace=hf_user)
39
  if dataset and not add_to_existing_dataset:
40
  raise gr.Error(f"Dataset {dataset_name} already exists")
 
41
  return ""
42
 
43
 
@@ -159,3 +160,22 @@ def test_max_num_rows(num_rows: int) -> int:
159
  f"Number of rows is larger than the configured maximum. Setting number of rows to {MAX_NUM_ROWS}. Set environment variable `MAX_NUM_ROWS` to change this behavior."
160
  )
161
  return num_rows
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  import gradio as gr
7
  from datasets import Dataset, concatenate_datasets, load_dataset
8
  from gradio import OAuthToken
9
+ from huggingface_hub import HfApi, upload_file, repo_exists
10
 
11
  from synthetic_dataset_generator.constants import MAX_NUM_ROWS
12
  from synthetic_dataset_generator.utils import get_argilla_client
 
18
  oauth_token: Union[OAuthToken, None] = None,
19
  progress=gr.Progress(),
20
  ) -> str:
21
+ progress(0.1, desc="Validating dataset configuration")
22
  hf_user = HfApi().whoami(token=oauth_token.token)["name"]
23
  client = get_argilla_client()
24
  if dataset_name is None or dataset_name == "":
 
38
  dataset = client.datasets(name=dataset_name, workspace=hf_user)
39
  if dataset and not add_to_existing_dataset:
40
  raise gr.Error(f"Dataset {dataset_name} already exists")
41
+ progress(1.0, desc="Dataset configuration validated")
42
  return ""
43
 
44
 
 
160
  f"Number of rows is larger than the configured maximum. Setting number of rows to {MAX_NUM_ROWS}. Set environment variable `MAX_NUM_ROWS` to change this behavior."
161
  )
162
  return num_rows
163
+
164
+
165
+ def get_iframe(hub_repo_id: str) -> str:
166
+ if not hub_repo_id:
167
+ return ""
168
+
169
+ if not repo_exists(repo_id=hub_repo_id, repo_type="dataset"):
170
+ return ""
171
+
172
+ url = f"https://huggingface.co/datasets/{hub_repo_id}/embed/viewer"
173
+ iframe = f"""
174
+ <iframe
175
+ src="{url}"
176
+ frameborder="0"
177
+ width="100%"
178
+ height="600px"
179
+ ></iframe>
180
+ """
181
+ return iframe
src/synthetic_dataset_generator/apps/chat.py CHANGED
@@ -25,7 +25,7 @@ from synthetic_dataset_generator.constants import (
25
  MODEL,
26
  SFT_AVAILABLE,
27
  )
28
- from synthetic_dataset_generator.pipelines.base import get_rewriten_prompts
29
  from synthetic_dataset_generator.pipelines.chat import (
30
  DEFAULT_DATASET_DESCRIPTIONS,
31
  generate_pipeline_code,
@@ -61,10 +61,9 @@ def convert_dataframe_messages(dataframe: pd.DataFrame) -> pd.DataFrame:
61
 
62
 
63
  def generate_system_prompt(dataset_description, progress=gr.Progress()):
64
- progress(0.0, desc="Starting")
65
- progress(0.3, desc="Initializing")
66
  generate_description = get_prompt_generator()
67
- progress(0.7, desc="Generating")
68
  result = next(
69
  generate_description.process(
70
  [
@@ -79,6 +78,7 @@ def generate_system_prompt(dataset_description, progress=gr.Progress()):
79
 
80
 
81
  def generate_sample_dataset(system_prompt, num_turns, progress=gr.Progress()):
 
82
  dataframe = generate_dataset(
83
  system_prompt=system_prompt,
84
  num_turns=num_turns,
@@ -86,6 +86,7 @@ def generate_sample_dataset(system_prompt, num_turns, progress=gr.Progress()):
86
  progress=progress,
87
  is_sample=True,
88
  )
 
89
  return dataframe
90
 
91
 
@@ -117,7 +118,7 @@ def generate_dataset(
117
  batch_size = DEFAULT_BATCH_SIZE
118
 
119
  # create prompt rewrites
120
- prompt_rewrites = get_rewriten_prompts(system_prompt, num_rows)
121
 
122
  # create instructions
123
  n_processed = 0
@@ -274,6 +275,7 @@ def push_dataset(
274
  client = get_argilla_client()
275
  if client is None:
276
  return ""
 
277
  if "messages" in dataframe.columns:
278
  settings = rg.Settings(
279
  fields=[
@@ -370,7 +372,6 @@ def push_dataset(
370
  dataframe["completion_length"] = dataframe["completion"].apply(len)
371
  dataframe["prompt_embeddings"] = get_embeddings(dataframe["prompt"])
372
 
373
- progress(0.5, desc="Creating dataset")
374
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
375
  if rg_dataset is None:
376
  rg_dataset = rg.Dataset(
@@ -516,7 +517,6 @@ with gr.Blocks() as app:
516
  system_prompt=system_prompt.value,
517
  num_turns=num_turns.value,
518
  num_rows=num_rows.value,
519
- temperature=temperature.value,
520
  )
521
  pipeline_code = gr.Code(
522
  value=code,
@@ -582,7 +582,7 @@ with gr.Blocks() as app:
582
  outputs=[success_message],
583
  ).success(
584
  fn=generate_pipeline_code,
585
- inputs=[system_prompt, num_turns, num_rows, temperature],
586
  outputs=[pipeline_code],
587
  ).success(
588
  fn=show_pipeline_code_visibility,
@@ -593,7 +593,7 @@ with gr.Blocks() as app:
593
  triggers=[clear_btn_part.click, clear_btn_full.click],
594
  fn=lambda _: ("", "", 1, _get_dataframe()),
595
  inputs=[dataframe],
596
- outputs=[dataset_description, system_prompt, num_turns, dataframe],
597
  )
598
  app.load(fn=get_org_dropdown, outputs=[org_name])
599
  app.load(fn=get_random_repo_name, outputs=[repo_name])
 
25
  MODEL,
26
  SFT_AVAILABLE,
27
  )
28
+ from synthetic_dataset_generator.pipelines.base import get_rewritten_prompts
29
  from synthetic_dataset_generator.pipelines.chat import (
30
  DEFAULT_DATASET_DESCRIPTIONS,
31
  generate_pipeline_code,
 
61
 
62
 
63
  def generate_system_prompt(dataset_description, progress=gr.Progress()):
64
+ progress(0.1, desc="Initializing")
 
65
  generate_description = get_prompt_generator()
66
+ progress(0.5, desc="Generating")
67
  result = next(
68
  generate_description.process(
69
  [
 
78
 
79
 
80
  def generate_sample_dataset(system_prompt, num_turns, progress=gr.Progress()):
81
+ progress(0.1, desc="Generating sample dataset")
82
  dataframe = generate_dataset(
83
  system_prompt=system_prompt,
84
  num_turns=num_turns,
 
86
  progress=progress,
87
  is_sample=True,
88
  )
89
+ progress(1.0, desc="Sample dataset generated")
90
  return dataframe
91
 
92
 
 
118
  batch_size = DEFAULT_BATCH_SIZE
119
 
120
  # create prompt rewrites
121
+ prompt_rewrites = get_rewritten_prompts(system_prompt, num_rows)
122
 
123
  # create instructions
124
  n_processed = 0
 
275
  client = get_argilla_client()
276
  if client is None:
277
  return ""
278
+ progress(0.5, desc="Creating dataset in Argilla")
279
  if "messages" in dataframe.columns:
280
  settings = rg.Settings(
281
  fields=[
 
372
  dataframe["completion_length"] = dataframe["completion"].apply(len)
373
  dataframe["prompt_embeddings"] = get_embeddings(dataframe["prompt"])
374
 
 
375
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
376
  if rg_dataset is None:
377
  rg_dataset = rg.Dataset(
 
517
  system_prompt=system_prompt.value,
518
  num_turns=num_turns.value,
519
  num_rows=num_rows.value,
 
520
  )
521
  pipeline_code = gr.Code(
522
  value=code,
 
582
  outputs=[success_message],
583
  ).success(
584
  fn=generate_pipeline_code,
585
+ inputs=[system_prompt, num_turns, num_rows],
586
  outputs=[pipeline_code],
587
  ).success(
588
  fn=show_pipeline_code_visibility,
 
593
  triggers=[clear_btn_part.click, clear_btn_full.click],
594
  fn=lambda _: ("", "", 1, _get_dataframe()),
595
  inputs=[dataframe],
596
+ outputs=[system_prompt, num_turns, dataframe],
597
  )
598
  app.load(fn=get_org_dropdown, outputs=[org_name])
599
  app.load(fn=get_random_repo_name, outputs=[repo_name])
src/synthetic_dataset_generator/apps/eval.py CHANGED
@@ -19,6 +19,7 @@ from huggingface_hub import HfApi, repo_exists
19
 
20
  from synthetic_dataset_generator.apps.base import (
21
  combine_datasets,
 
22
  hide_success_message,
23
  push_pipeline_code_to_hub,
24
  show_success_message,
@@ -48,25 +49,6 @@ from synthetic_dataset_generator.utils import (
48
  )
49
 
50
 
51
- def get_iframe(hub_repo_id: str) -> str:
52
- if not hub_repo_id:
53
- return ""
54
-
55
- if not repo_exists(repo_id=hub_repo_id, repo_type="dataset"):
56
- return ""
57
-
58
- url = f"https://huggingface.co/datasets/{hub_repo_id}/embed/viewer"
59
- iframe = f"""
60
- <iframe
61
- src="{url}"
62
- frameborder="0"
63
- width="100%"
64
- height="600px"
65
- ></iframe>
66
- """
67
- return iframe
68
-
69
-
70
  def get_valid_columns(dataframe: pd.DataFrame):
71
  instruction_valid_columns = []
72
  response_valid_columns = []
@@ -357,11 +339,15 @@ def push_dataset_to_hub(
357
  oauth_token: Union[gr.OAuthToken, None],
358
  private: bool,
359
  pipeline_code: str,
 
360
  ):
 
361
  repo_id = validate_push_to_hub(org_name, repo_name)
 
362
  dataset = Dataset.from_pandas(dataframe)
363
  dataset = combine_datasets(repo_id, dataset, oauth_token)
364
  distiset = Distiset({"default": dataset})
 
365
  distiset.push_to_hub(
366
  repo_id=repo_id,
367
  private=private,
@@ -370,6 +356,8 @@ def push_dataset_to_hub(
370
  create_pr=False,
371
  )
372
  push_pipeline_code_to_hub(pipeline_code, org_name, repo_name, oauth_token)
 
 
373
 
374
 
375
  def push_dataset(
@@ -408,6 +396,7 @@ def push_dataset(
408
  client = get_argilla_client()
409
  if client is None:
410
  return ""
 
411
  if eval_type == "chat-eval":
412
  num_generations = len((dataframe["generations"][0]))
413
  fields = [
@@ -488,7 +477,6 @@ def push_dataset(
488
  dataframe["instruction"].to_list()
489
  )
490
 
491
- progress(0.5, desc="Creating dataset")
492
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
493
  if rg_dataset is None:
494
  rg_dataset = rg.Dataset(
@@ -628,7 +616,6 @@ def push_dataset(
628
  dataframe[f"{column}_length"] = dataframe[column].apply(len)
629
  dataframe[f"{column}_embeddings"] = get_embeddings(dataframe[column])
630
 
631
- progress(0.5, desc="Creating dataset")
632
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
633
  if rg_dataset is None:
634
  rg_dataset = rg.Dataset(
@@ -895,12 +882,11 @@ with gr.Blocks() as app:
895
  outputs=[pipeline_code_ui],
896
  )
897
 
898
- clear_btn_part.click(fn=lambda x: "", inputs=[], outputs=[search_in])
899
  clear_btn_full.click(
900
  fn=lambda df: ("", "", pd.DataFrame(columns=df.columns)),
901
  inputs=[dataframe],
902
  outputs=[
903
- search_in,
904
  instruction_instruction_response,
905
  response_instruction_response,
906
  ],
 
19
 
20
  from synthetic_dataset_generator.apps.base import (
21
  combine_datasets,
22
+ get_iframe,
23
  hide_success_message,
24
  push_pipeline_code_to_hub,
25
  show_success_message,
 
49
  )
50
 
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  def get_valid_columns(dataframe: pd.DataFrame):
53
  instruction_valid_columns = []
54
  response_valid_columns = []
 
339
  oauth_token: Union[gr.OAuthToken, None],
340
  private: bool,
341
  pipeline_code: str,
342
+ progress=gr.Progress(),
343
  ):
344
+ progress(0.0, desc="Validating")
345
  repo_id = validate_push_to_hub(org_name, repo_name)
346
+ progress(0.5, desc="Creating dataset")
347
  dataset = Dataset.from_pandas(dataframe)
348
  dataset = combine_datasets(repo_id, dataset, oauth_token)
349
  distiset = Distiset({"default": dataset})
350
+ progress(0.9, desc="Pushing dataset")
351
  distiset.push_to_hub(
352
  repo_id=repo_id,
353
  private=private,
 
356
  create_pr=False,
357
  )
358
  push_pipeline_code_to_hub(pipeline_code, org_name, repo_name, oauth_token)
359
+ progress(1.0, desc="Dataset pushed")
360
+ return dataframe
361
 
362
 
363
  def push_dataset(
 
396
  client = get_argilla_client()
397
  if client is None:
398
  return ""
399
+ progress(0.5, desc="Creating dataset in Argilla")
400
  if eval_type == "chat-eval":
401
  num_generations = len((dataframe["generations"][0]))
402
  fields = [
 
477
  dataframe["instruction"].to_list()
478
  )
479
 
 
480
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
481
  if rg_dataset is None:
482
  rg_dataset = rg.Dataset(
 
616
  dataframe[f"{column}_length"] = dataframe[column].apply(len)
617
  dataframe[f"{column}_embeddings"] = get_embeddings(dataframe[column])
618
 
 
619
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
620
  if rg_dataset is None:
621
  rg_dataset = rg.Dataset(
 
882
  outputs=[pipeline_code_ui],
883
  )
884
 
885
+ clear_btn_part.click(fn=lambda : "", inputs=[], outputs=[search_in])
886
  clear_btn_full.click(
887
  fn=lambda df: ("", "", pd.DataFrame(columns=df.columns)),
888
  inputs=[dataframe],
889
  outputs=[
 
890
  instruction_instruction_response,
891
  response_instruction_response,
892
  ],
src/synthetic_dataset_generator/apps/rag.py ADDED
@@ -0,0 +1,896 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import uuid
3
+ from tqdm import tqdm
4
+ from typing import Union
5
+
6
+ import argilla as rg
7
+ import gradio as gr
8
+ import pandas as pd
9
+ from datasets import (
10
+ Dataset,
11
+ get_dataset_config_names,
12
+ get_dataset_split_names,
13
+ load_dataset,
14
+ )
15
+ from distilabel.distiset import Distiset
16
+ from gradio.oauth import OAuthToken
17
+ from gradio_huggingfacehub_search import HuggingfaceHubSearch
18
+ from huggingface_hub import HfApi
19
+ from unstructured.chunking.title import chunk_by_title
20
+ from unstructured.partition.auto import partition
21
+
22
+ from synthetic_dataset_generator.apps.base import (
23
+ combine_datasets,
24
+ get_iframe,
25
+ hide_success_message,
26
+ push_pipeline_code_to_hub,
27
+ show_success_message,
28
+ test_max_num_rows,
29
+ validate_argilla_user_workspace_dataset,
30
+ validate_push_to_hub,
31
+ )
32
+ from synthetic_dataset_generator.constants import DEFAULT_BATCH_SIZE
33
+ from synthetic_dataset_generator.pipelines.base import get_rewritten_prompts
34
+ from synthetic_dataset_generator.pipelines.embeddings import (
35
+ get_embeddings,
36
+ get_sentence_embedding_dimensions,
37
+ )
38
+ from synthetic_dataset_generator.pipelines.rag import (
39
+ DEFAULT_DATASET_DESCRIPTIONS,
40
+ get_chunks_generator,
41
+ get_prompt_generator,
42
+ generate_pipeline_code,
43
+ get_sentence_pair_generator,
44
+ get_response_generator,
45
+ )
46
+ from synthetic_dataset_generator.utils import (
47
+ column_to_list,
48
+ get_argilla_client,
49
+ get_org_dropdown,
50
+ get_random_repo_name,
51
+ swap_visibility,
52
+ )
53
+
54
+
55
+ def _get_valid_columns(dataframe: pd.DataFrame):
56
+ doc_valid_columns = []
57
+
58
+ for col in dataframe.columns:
59
+ sample_val = dataframe[col].iloc[0]
60
+ if isinstance(sample_val, str):
61
+ doc_valid_columns.append(col)
62
+
63
+ return doc_valid_columns
64
+
65
+
66
+ def _load_dataset_from_hub(
67
+ repo_id: str,
68
+ num_rows: int = 10,
69
+ token: Union[OAuthToken, None] = None,
70
+ progress=gr.Progress(track_tqdm=True),
71
+ ):
72
+ if not repo_id:
73
+ raise gr.Error("Hub repo id is required")
74
+ subsets = get_dataset_config_names(repo_id, token=token)
75
+ splits = get_dataset_split_names(repo_id, subsets[0], token=token)
76
+ ds = load_dataset(repo_id, subsets[0], split=splits[0], token=token, streaming=True)
77
+ rows = []
78
+ for idx, row in enumerate(tqdm(ds, desc="Loading the dataset", total=num_rows)):
79
+ rows.append(row)
80
+ if idx == num_rows:
81
+ break
82
+ ds = Dataset.from_list(rows)
83
+ dataframe = ds.to_pandas()
84
+ doc_valid_columns = _get_valid_columns(dataframe)
85
+ col_doc = doc_valid_columns[0] if doc_valid_columns else ""
86
+ return (
87
+ dataframe,
88
+ gr.Dropdown(
89
+ choices=doc_valid_columns,
90
+ label="Documents column",
91
+ value=col_doc,
92
+ interactive=(False if col_doc == "" else True),
93
+ multiselect=False,
94
+ ),
95
+ )
96
+
97
+
98
+ def _preprocess_input_data(file_paths, num_rows, progress=gr.Progress(track_tqdm=True)):
99
+ data = {}
100
+ total_chunks = 0
101
+
102
+ for file_path in tqdm(file_paths, desc="Processing files", total=len(file_paths)):
103
+ partitioned_file = partition(filename=file_path)
104
+ chunks = [str(chunk) for chunk in chunk_by_title(partitioned_file)]
105
+ data[file_path] = chunks
106
+ total_chunks += len(chunks)
107
+ if total_chunks >= num_rows:
108
+ break
109
+
110
+ dataframe = pd.DataFrame.from_records(
111
+ [(k, v) for k, values in data.items() for v in values],
112
+ columns=["filename", "chunks"],
113
+ )
114
+ col_doc = "chunks"
115
+
116
+ return (
117
+ dataframe,
118
+ gr.Dropdown(
119
+ choices=["chucks"],
120
+ label="Documents column",
121
+ value=col_doc,
122
+ interactive=(False if col_doc == "" else True),
123
+ multiselect=False,
124
+ ),
125
+ )
126
+
127
+
128
+ def generate_system_prompt(dataset_description, progress=gr.Progress()):
129
+ progress(0.1, desc="Initializing")
130
+ generate_description = get_prompt_generator()
131
+ progress(0.5, desc="Generating")
132
+ result = next(
133
+ generate_description.process(
134
+ [
135
+ {
136
+ "instruction": dataset_description,
137
+ }
138
+ ]
139
+ )
140
+ )[0]["generation"]
141
+ progress(1.0, desc="Prompt generated")
142
+ return result
143
+
144
+
145
+ def load_dataset_file(
146
+ repo_id: str,
147
+ file_paths: list[str],
148
+ input_type: str,
149
+ num_rows: int = 10,
150
+ token: Union[OAuthToken, None] = None,
151
+ progress=gr.Progress(),
152
+ ):
153
+ progress(0.1, desc="Loading the source data")
154
+ if input_type == "dataset-input":
155
+ return _load_dataset_from_hub(repo_id, num_rows, token)
156
+ else:
157
+ return _preprocess_input_data(file_paths, num_rows)
158
+
159
+
160
+ def generate_dataset(
161
+ input_type: str,
162
+ dataframe: pd.DataFrame,
163
+ system_prompt: str,
164
+ document_column: str,
165
+ retrieval: bool = False,
166
+ reranking: bool = False,
167
+ num_rows: int = 10,
168
+ temperature: float = 0.7,
169
+ is_sample: bool = False,
170
+ progress=gr.Progress(),
171
+ ):
172
+ num_rows = test_max_num_rows(num_rows)
173
+ progress(0.0, desc="Generating questions")
174
+ if input_type == "prompt-input":
175
+ chunk_generator = get_chunks_generator(
176
+ temperature=temperature, is_sample=is_sample
177
+ )
178
+ else:
179
+ document_data = column_to_list(dataframe, document_column)
180
+ if len(document_data) < num_rows:
181
+ document_data += random.choices(
182
+ document_data, k=num_rows - len(document_data)
183
+ )
184
+
185
+ retrieval_generator = get_sentence_pair_generator(
186
+ action="query",
187
+ triplet=True if retrieval else False,
188
+ temperature=temperature,
189
+ is_sample=is_sample,
190
+ )
191
+ response_generator = get_response_generator(
192
+ temperature=temperature, is_sample=is_sample
193
+ )
194
+ if reranking:
195
+ reranking_generator = get_sentence_pair_generator(
196
+ action="semantically-similar",
197
+ triplet=True,
198
+ temperature=temperature,
199
+ is_sample=is_sample,
200
+ )
201
+ steps = 2 + sum([1 if reranking else 0, 1 if input_type == "prompt-type" else 0])
202
+ total_steps: int = num_rows * steps
203
+ step_progress = round(1 / steps, 2)
204
+ batch_size = DEFAULT_BATCH_SIZE
205
+
206
+ # generate chunks
207
+ if input_type == "prompt-input":
208
+ n_processed = 0
209
+ chunk_results = []
210
+ rewritten_system_prompts = get_rewritten_prompts(system_prompt, num_rows)
211
+ while n_processed < num_rows:
212
+ progress(
213
+ step_progress * n_processed / num_rows,
214
+ total=total_steps,
215
+ desc="Generating chunks",
216
+ )
217
+ remaining_rows = num_rows - n_processed
218
+ batch_size = min(batch_size, remaining_rows)
219
+ inputs = [
220
+ {"task": random.choice(rewritten_system_prompts)}
221
+ for _ in range(batch_size)
222
+ ]
223
+ chunks = list(chunk_generator.process(inputs=inputs))
224
+ chunk_results.extend(chunks[0])
225
+ n_processed += batch_size
226
+ random.seed(a=random.randint(0, 2**32 - 1))
227
+ document_data = [chunk["generation"] for chunk in chunk_results]
228
+ progress(step_progress, desc="Generating chunks")
229
+
230
+ # generate questions
231
+ n_processed = 0
232
+ retrieval_results = []
233
+ while n_processed < num_rows:
234
+ progress(
235
+ step_progress * n_processed / num_rows,
236
+ total=total_steps,
237
+ desc="Generating questions",
238
+ )
239
+ remaining_rows = num_rows - n_processed
240
+ batch_size = min(batch_size, remaining_rows)
241
+ inputs = [
242
+ {"anchor": document}
243
+ for document in document_data[n_processed : n_processed + batch_size]
244
+ ]
245
+ questions = list(retrieval_generator.process(inputs=inputs))
246
+ retrieval_results.extend(questions[0])
247
+ n_processed += batch_size
248
+ for result in retrieval_results:
249
+ result["context"] = result["anchor"]
250
+ if retrieval:
251
+ result["question"] = result["positive"]
252
+ result["positive_retrieval"] = result.pop("positive")
253
+ result["negative_retrieval"] = result.pop("negative")
254
+ else:
255
+ result["question"] = result.pop("positive")
256
+
257
+ progress(step_progress, desc="Generating questions")
258
+
259
+ # generate responses
260
+ n_processed = 0
261
+ response_results = []
262
+ while n_processed < num_rows:
263
+ progress(
264
+ step_progress + step_progress * n_processed / num_rows,
265
+ total=total_steps,
266
+ desc="Generating responses",
267
+ )
268
+ batch = retrieval_results[n_processed : n_processed + batch_size]
269
+ responses = list(response_generator.process(inputs=batch))
270
+ response_results.extend(responses[0])
271
+ n_processed += batch_size
272
+ for result in response_results:
273
+ result["response"] = result["generation"]
274
+ progress(step_progress, desc="Generating responses")
275
+
276
+ # generate reranking
277
+ if reranking:
278
+ n_processed = 0
279
+ reranking_results = []
280
+ while n_processed < num_rows:
281
+ progress(
282
+ step_progress * n_processed / num_rows,
283
+ total=total_steps,
284
+ desc="Generating reranking data",
285
+ )
286
+ batch = response_results[n_processed : n_processed + batch_size]
287
+ batch = list(reranking_generator.process(inputs=batch))
288
+ reranking_results.extend(batch[0])
289
+ n_processed += batch_size
290
+ for result in reranking_results:
291
+ result["positive_reranking"] = result.pop("positive")
292
+ result["negative_reranking"] = result.pop("negative")
293
+ progress(
294
+ 1,
295
+ total=total_steps,
296
+ desc="Creating dataset",
297
+ )
298
+
299
+ # create distiset
300
+ distiset_results = []
301
+ source_results = reranking_results if reranking else response_results
302
+ base_keys = ["context", "question", "response"]
303
+ retrieval_keys = ["positive_retrieval", "negative_retrieval"] if retrieval else []
304
+ reranking_keys = ["positive_reranking", "negative_reranking"] if reranking else []
305
+ relevant_keys = base_keys + retrieval_keys + reranking_keys
306
+
307
+ for result in source_results:
308
+ record = {key: result.get(key) for key in relevant_keys if key in result}
309
+ distiset_results.append(record)
310
+
311
+ dataframe = pd.DataFrame(distiset_results)
312
+
313
+ progress(1.0, desc="Dataset generation completed")
314
+ return dataframe
315
+
316
+
317
+ def generate_sample_dataset(
318
+ repo_id: str,
319
+ file_paths: list[str],
320
+ input_type: str,
321
+ system_prompt: str,
322
+ document_column: str,
323
+ retrieval_reranking: list[str],
324
+ num_rows: str,
325
+ oauth_token: Union[OAuthToken, None],
326
+ progress=gr.Progress(),
327
+ ):
328
+ retrieval = "Retrieval" in retrieval_reranking
329
+ reranking = "Reranking" in retrieval_reranking
330
+
331
+ if input_type == "prompt-input":
332
+ dataframe = pd.DataFrame(columns=["context", "question", "response"])
333
+ else:
334
+ dataframe, _ = load_dataset_file(
335
+ repo_id=repo_id,
336
+ file_paths=file_paths,
337
+ input_type=input_type,
338
+ num_rows=num_rows,
339
+ token=oauth_token,
340
+ )
341
+ progress(0.5, desc="Generating dataset")
342
+ dataframe = generate_dataset(
343
+ input_type=input_type,
344
+ dataframe=dataframe,
345
+ system_prompt=system_prompt,
346
+ document_column=document_column,
347
+ retrieval=retrieval,
348
+ reranking=reranking,
349
+ num_rows=10,
350
+ is_sample=True,
351
+ )
352
+ return dataframe
353
+
354
+
355
+ def push_dataset_to_hub(
356
+ dataframe: pd.DataFrame,
357
+ org_name: str,
358
+ repo_name: str,
359
+ oauth_token: Union[gr.OAuthToken, None],
360
+ private: bool,
361
+ pipeline_code: str,
362
+ progress=gr.Progress(),
363
+ ):
364
+ progress(0.0, desc="Validating")
365
+ repo_id = validate_push_to_hub(org_name, repo_name)
366
+ progress(0.5, desc="Creating dataset")
367
+ dataset = Dataset.from_pandas(dataframe)
368
+ dataset = combine_datasets(repo_id, dataset, oauth_token)
369
+ distiset = Distiset({"default": dataset})
370
+ progress(0.9, desc="Pushing dataset")
371
+ distiset.push_to_hub(
372
+ repo_id=repo_id,
373
+ private=private,
374
+ include_script=False,
375
+ token=oauth_token.token,
376
+ create_pr=False,
377
+ )
378
+ push_pipeline_code_to_hub(pipeline_code, org_name, repo_name, oauth_token)
379
+ progress(1.0, desc="Dataset pushed")
380
+ return dataframe
381
+
382
+
383
+ def push_dataset(
384
+ org_name: str,
385
+ repo_name: str,
386
+ private: bool,
387
+ original_repo_id: str,
388
+ file_paths: list[str],
389
+ input_type: str,
390
+ system_prompt: str,
391
+ document_column: str,
392
+ retrieval_reranking: list[str],
393
+ num_rows: int,
394
+ temperature: float,
395
+ pipeline_code: str,
396
+ oauth_token: Union[gr.OAuthToken, None] = None,
397
+ progress=gr.Progress(),
398
+ ) -> pd.DataFrame:
399
+ retrieval = "Retrieval" in retrieval_reranking
400
+ reranking = "Reranking" in retrieval_reranking
401
+
402
+ if input_type != "prompt-input":
403
+ dataframe, _ = load_dataset_file(
404
+ repo_id=original_repo_id,
405
+ file_paths=file_paths,
406
+ input_type=input_type,
407
+ num_rows=num_rows,
408
+ token=oauth_token,
409
+ )
410
+ progress(0.5, desc="Generating dataset")
411
+ dataframe = generate_dataset(
412
+ input_type=input_type,
413
+ dataframe=dataframe,
414
+ system_prompt=system_prompt,
415
+ document_column=document_column,
416
+ retrieval=retrieval,
417
+ reranking=reranking,
418
+ num_rows=num_rows,
419
+ temperature=temperature,
420
+ is_sample=True,
421
+ )
422
+ push_dataset_to_hub(
423
+ dataframe, org_name, repo_name, oauth_token, private, pipeline_code
424
+ )
425
+ try:
426
+ progress(0.1, desc="Setting up user and workspace")
427
+ hf_user = HfApi().whoami(token=oauth_token.token)["name"]
428
+ client = get_argilla_client()
429
+ if client is None:
430
+ return ""
431
+
432
+ progress(0.5, desc="Creating dataset in Argilla")
433
+ fields = [
434
+ rg.TextField(
435
+ name="context",
436
+ title="Context",
437
+ description="Context for the generation",
438
+ ),
439
+ rg.ChatField(
440
+ name="chat",
441
+ title="Chat",
442
+ description="User and assistant conversation based on the context",
443
+ ),
444
+ ]
445
+ for item in ["positive", "negative"]:
446
+ if retrieval:
447
+ fields.append(
448
+ rg.TextField(
449
+ name=f"{item}_retrieval",
450
+ title=f"{item.capitalize()} retrieval",
451
+ description=f"The {item} query for retrieval",
452
+ )
453
+ )
454
+ if reranking:
455
+ fields.append(
456
+ rg.TextField(
457
+ name=f"{item}_reranking",
458
+ title=f"{item.capitalize()} reranking",
459
+ description=f"The {item} query for reranking",
460
+ )
461
+ )
462
+
463
+ questions = [
464
+ rg.LabelQuestion(
465
+ name="relevant",
466
+ title="Are the question and response relevant to the given context?",
467
+ labels=["yes", "no"],
468
+ ),
469
+ rg.LabelQuestion(
470
+ name="is_response_correct",
471
+ title="Is the response correct?",
472
+ labels=["yes", "no"],
473
+ ),
474
+ ]
475
+ for item in ["positive", "negative"]:
476
+ if retrieval:
477
+ questions.append(
478
+ rg.LabelQuestion(
479
+ name=f"is_{item}_retrieval_relevant",
480
+ title=f"Is the {item} retrieval relevant?",
481
+ labels=["yes", "no"],
482
+ required=False,
483
+ )
484
+ )
485
+ if reranking:
486
+ questions.append(
487
+ rg.LabelQuestion(
488
+ name=f"is_{item}_reranking_relevant",
489
+ title=f"Is the {item} reranking relevant?",
490
+ labels=["yes", "no"],
491
+ required=False,
492
+ )
493
+ )
494
+ metadata = [
495
+ rg.IntegerMetadataProperty(
496
+ name=f"{item}_length", title=f"{item.capitalize()} length"
497
+ )
498
+ for item in ["context", "question", "response"]
499
+ ]
500
+
501
+ vectors = [
502
+ rg.VectorField(
503
+ name=f"{item}_embeddings",
504
+ dimensions=get_sentence_embedding_dimensions(),
505
+ )
506
+ for item in ["context", "question", "response"]
507
+ ]
508
+ settings = rg.Settings(
509
+ fields=fields,
510
+ questions=questions,
511
+ metadata=metadata,
512
+ vectors=vectors,
513
+ guidelines="Please review the conversation and provide an evaluation.",
514
+ )
515
+
516
+ dataframe["chat"] = dataframe.apply(
517
+ lambda row: [
518
+ {"role": "user", "content": row["question"]},
519
+ {"role": "assistant", "content": row["response"]},
520
+ ],
521
+ axis=1,
522
+ )
523
+
524
+ for item in ["context", "question", "response"]:
525
+ dataframe[f"{item}_length"] = dataframe[item].apply(len)
526
+ dataframe[f"{item}_embeddings"] = get_embeddings(dataframe[item].to_list())
527
+
528
+ rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
529
+ if rg_dataset is None:
530
+ rg_dataset = rg.Dataset(
531
+ name=repo_name,
532
+ workspace=hf_user,
533
+ settings=settings,
534
+ client=client,
535
+ )
536
+ rg_dataset = rg_dataset.create()
537
+
538
+ progress(0.7, desc="Pushing dataset to Argilla")
539
+ hf_dataset = Dataset.from_pandas(dataframe)
540
+ rg_dataset.records.log(records=hf_dataset)
541
+ progress(1.0, desc="Dataset pushed to Argilla")
542
+ except Exception as e:
543
+ raise gr.Error(f"Error pushing dataset to Argilla: {e}")
544
+ return ""
545
+
546
+
547
+ def show_system_prompt_visibility():
548
+ return {system_prompt: gr.Textbox(visible=True)}
549
+
550
+
551
+ def hide_system_prompt_visibility():
552
+ return {system_prompt: gr.Textbox(visible=False)}
553
+
554
+
555
+ def show_document_column_visibility():
556
+ return {document_column: gr.Dropdown(visible=True)}
557
+
558
+
559
+ def hide_document_column_visibility():
560
+ return {document_column: gr.Dropdown(visible=False)}
561
+
562
+
563
+ def show_pipeline_code_visibility():
564
+ return {pipeline_code_ui: gr.Accordion(visible=True)}
565
+
566
+
567
+ def hide_pipeline_code_visibility():
568
+ return {pipeline_code_ui: gr.Accordion(visible=False)}
569
+
570
+
571
+ ######################
572
+ # Gradio UI
573
+ ######################
574
+
575
+
576
+ with gr.Blocks() as app:
577
+ with gr.Column() as main_ui:
578
+ gr.Markdown("## 1. Select your input")
579
+ with gr.Row(equal_height=False):
580
+ with gr.Column(scale=2):
581
+ input_type = gr.Dropdown(
582
+ label="Input type",
583
+ choices=["dataset-input", "file-input", "prompt-input"],
584
+ value="dataset-input",
585
+ multiselect=False,
586
+ visible=False,
587
+ )
588
+ with gr.Tab("Load from Hub") as tab_dataset_input:
589
+ with gr.Row(equal_height=False):
590
+ with gr.Column(scale=2):
591
+ search_in = HuggingfaceHubSearch(
592
+ label="Search",
593
+ placeholder="Search for a dataset",
594
+ search_type="dataset",
595
+ sumbit_on_select=True,
596
+ )
597
+ with gr.Row():
598
+ clear_dataset_btn_part = gr.Button(
599
+ "Clear", variant="secondary"
600
+ )
601
+ load_dataset_btn = gr.Button("Load", variant="primary")
602
+ with gr.Column(scale=3):
603
+ examples = gr.Examples(
604
+ examples=[
605
+ "charris/wikipedia_sample",
606
+ "plaguss/argilla_sdk_docs_raw_unstructured",
607
+ "BeIR/hotpotqa-generated-queries",
608
+ ],
609
+ label="Example datasets",
610
+ fn=lambda x: x,
611
+ inputs=[search_in],
612
+ run_on_click=True,
613
+ )
614
+ search_out = gr.HTML(label="Dataset preview", visible=False)
615
+ with gr.Tab("Load your file") as tab_file_input:
616
+ with gr.Row(equal_height=False):
617
+ with gr.Column(scale=2):
618
+ file_in = gr.File(
619
+ label="Upload your file. Supported formats: .md, .txt, .docx, .pdf",
620
+ file_count="multiple",
621
+ file_types=[".md", ".txt", ".docx", ".pdf"],
622
+ )
623
+ with gr.Row():
624
+ clear_file_btn_part = gr.Button(
625
+ "Clear", variant="secondary"
626
+ )
627
+ load_file_btn = gr.Button("Load", variant="primary")
628
+ with gr.Column(scale=3):
629
+ file_out = gr.HTML(label="Dataset preview", visible=False)
630
+ with gr.Tab("Generate from prompt") as tab_prompt_input:
631
+ with gr.Row(equal_height=False):
632
+ with gr.Column(scale=2):
633
+ dataset_description = gr.Textbox(
634
+ label="Dataset description",
635
+ placeholder="Give a precise description of your desired dataset.",
636
+ )
637
+ with gr.Row():
638
+ clear_prompt_btn_part = gr.Button(
639
+ "Clear", variant="secondary"
640
+ )
641
+ load_prompt_btn = gr.Button("Create", variant="primary")
642
+ with gr.Column(scale=3):
643
+ examples = gr.Examples(
644
+ examples=DEFAULT_DATASET_DESCRIPTIONS,
645
+ inputs=[dataset_description],
646
+ cache_examples=False,
647
+ label="Examples",
648
+ )
649
+
650
+ gr.HTML(value="<hr>")
651
+ gr.Markdown(value="## 2. Configure your task")
652
+ with gr.Row(equal_height=True):
653
+ with gr.Row(equal_height=False):
654
+ with gr.Column(scale=2):
655
+ system_prompt = gr.Textbox(
656
+ label="System prompt",
657
+ placeholder="You are a helpful assistant.",
658
+ visible=False,
659
+ )
660
+ document_column = gr.Dropdown(
661
+ label="Document Column",
662
+ info="Select the document column to generate the RAG dataset",
663
+ choices=["Load your data first in step 1."],
664
+ value="Load your data first in step 1.",
665
+ interactive=False,
666
+ multiselect=False,
667
+ allow_custom_value=False,
668
+ )
669
+ retrieval_reranking = gr.CheckboxGroup(
670
+ choices=[("Retrieval", "Retrieval"), ("Reranking", "Reranking")],
671
+ type="value",
672
+ label="Data for RAG",
673
+ info="Indicate the additional data you want to generate for RAG.",
674
+ )
675
+ with gr.Row():
676
+ clear_btn_full = gr.Button("Clear", variant="secondary")
677
+ btn_apply_to_sample_dataset = gr.Button(
678
+ "Save", variant="primary"
679
+ )
680
+ with gr.Column(scale=3):
681
+ dataframe = gr.Dataframe(
682
+ headers=["context", "question", "response"],
683
+ wrap=True,
684
+ interactive=False,
685
+ )
686
+
687
+ gr.HTML(value="<hr>")
688
+ gr.Markdown(value="## 3. Generate your dataset")
689
+ with gr.Row(equal_height=False):
690
+ with gr.Column(scale=2):
691
+ org_name = get_org_dropdown()
692
+ repo_name = gr.Textbox(
693
+ label="Repo name",
694
+ placeholder="dataset_name",
695
+ value=f"my-distiset-{str(uuid.uuid4())[:8]}",
696
+ interactive=True,
697
+ )
698
+ num_rows = gr.Number(
699
+ label="Number of rows",
700
+ value=10,
701
+ interactive=True,
702
+ scale=1,
703
+ )
704
+ temperature = gr.Slider(
705
+ label="Temperature",
706
+ minimum=0.1,
707
+ maximum=1,
708
+ value=0.7,
709
+ step=0.1,
710
+ interactive=True,
711
+ )
712
+ private = gr.Checkbox(
713
+ label="Private dataset",
714
+ value=False,
715
+ interactive=True,
716
+ scale=1,
717
+ )
718
+ btn_push_to_hub = gr.Button("Push to Hub", variant="primary", scale=2)
719
+ with gr.Column(scale=3):
720
+ success_message = gr.Markdown(
721
+ visible=True,
722
+ min_height=100, # don't remove this otherwise progress is not visible
723
+ )
724
+ with gr.Accordion(
725
+ "Customize your pipeline with distilabel",
726
+ open=False,
727
+ visible=False,
728
+ ) as pipeline_code_ui:
729
+ code = generate_pipeline_code(
730
+ repo_id=search_in.value,
731
+ file_paths=file_in.value,
732
+ input_type=input_type.value,
733
+ system_prompt=system_prompt.value,
734
+ document_column=document_column.value,
735
+ retrieval_reranking=retrieval_reranking.value,
736
+ num_rows=num_rows.value,
737
+ )
738
+ pipeline_code = gr.Code(
739
+ value=code,
740
+ language="python",
741
+ label="Distilabel Pipeline Code",
742
+ )
743
+
744
+ tab_dataset_input.select(
745
+ fn=lambda: "dataset-input",
746
+ inputs=[],
747
+ outputs=[input_type],
748
+ ).then(fn=hide_system_prompt_visibility, inputs=[], outputs=[system_prompt]).then(
749
+ fn=show_document_column_visibility, inputs=[], outputs=[document_column]
750
+ )
751
+
752
+ tab_file_input.select(
753
+ fn=lambda: "file-input",
754
+ inputs=[],
755
+ outputs=[input_type],
756
+ ).then(fn=hide_system_prompt_visibility, inputs=[], outputs=[system_prompt]).then(
757
+ fn=show_document_column_visibility, inputs=[], outputs=[document_column]
758
+ )
759
+
760
+ tab_prompt_input.select(
761
+ fn=lambda: "prompt-input",
762
+ inputs=[],
763
+ outputs=[input_type],
764
+ ).then(fn=show_system_prompt_visibility, inputs=[], outputs=[system_prompt]).then(
765
+ fn=hide_document_column_visibility, inputs=[], outputs=[document_column]
766
+ )
767
+
768
+ search_in.submit(fn=get_iframe, inputs=search_in, outputs=search_out).then(
769
+ fn=lambda df: pd.DataFrame(columns=df.columns),
770
+ inputs=[dataframe],
771
+ outputs=[dataframe],
772
+ )
773
+
774
+ load_dataset_btn.click(
775
+ fn=load_dataset_file,
776
+ inputs=[search_in, file_in, input_type],
777
+ outputs=[
778
+ dataframe,
779
+ document_column,
780
+ ],
781
+ )
782
+
783
+ load_file_btn.click(
784
+ fn=load_dataset_file,
785
+ inputs=[search_in, file_in, input_type],
786
+ outputs=[
787
+ dataframe,
788
+ document_column,
789
+ ],
790
+ )
791
+
792
+ load_prompt_btn.click(
793
+ fn=generate_system_prompt,
794
+ inputs=[dataset_description],
795
+ outputs=[system_prompt],
796
+ show_progress=True,
797
+ ).success(
798
+ fn=generate_sample_dataset,
799
+ inputs=[
800
+ search_in,
801
+ file_in,
802
+ input_type,
803
+ system_prompt,
804
+ document_column,
805
+ retrieval_reranking,
806
+ num_rows,
807
+ ],
808
+ outputs=dataframe,
809
+ )
810
+
811
+ btn_apply_to_sample_dataset.click(
812
+ fn=generate_sample_dataset,
813
+ inputs=[
814
+ search_in,
815
+ file_in,
816
+ input_type,
817
+ system_prompt,
818
+ document_column,
819
+ retrieval_reranking,
820
+ num_rows,
821
+ ],
822
+ outputs=dataframe,
823
+ )
824
+
825
+ btn_push_to_hub.click(
826
+ fn=validate_argilla_user_workspace_dataset,
827
+ inputs=[repo_name],
828
+ outputs=[success_message],
829
+ show_progress=True,
830
+ ).then(
831
+ fn=validate_push_to_hub,
832
+ inputs=[org_name, repo_name],
833
+ outputs=[success_message],
834
+ show_progress=True,
835
+ ).success(
836
+ fn=hide_success_message,
837
+ outputs=[success_message],
838
+ show_progress=True,
839
+ ).success(
840
+ fn=hide_pipeline_code_visibility,
841
+ inputs=[],
842
+ outputs=[pipeline_code_ui],
843
+ ).success(
844
+ fn=push_dataset,
845
+ inputs=[
846
+ org_name,
847
+ repo_name,
848
+ private,
849
+ search_in,
850
+ file_in,
851
+ input_type,
852
+ system_prompt,
853
+ document_column,
854
+ retrieval_reranking,
855
+ num_rows,
856
+ temperature,
857
+ pipeline_code,
858
+ ],
859
+ outputs=[success_message],
860
+ show_progress=True,
861
+ ).success(
862
+ fn=show_success_message,
863
+ inputs=[org_name, repo_name],
864
+ outputs=[success_message],
865
+ ).success(
866
+ fn=generate_pipeline_code,
867
+ inputs=[
868
+ search_in,
869
+ file_in,
870
+ input_type,
871
+ system_prompt,
872
+ document_column,
873
+ retrieval_reranking,
874
+ num_rows,
875
+ ],
876
+ outputs=[pipeline_code],
877
+ ).success(
878
+ fn=show_pipeline_code_visibility,
879
+ inputs=[],
880
+ outputs=[pipeline_code_ui],
881
+ )
882
+
883
+ clear_dataset_btn_part.click(fn=lambda : "", inputs=[], outputs=[search_in])
884
+ clear_file_btn_part.click(fn=lambda: None, inputs=[], outputs=[file_in])
885
+ clear_prompt_btn_part.click(
886
+ fn=lambda : "", inputs=[], outputs=[dataset_description]
887
+ )
888
+ clear_btn_full.click(
889
+ fn=lambda df: ("", [], pd.DataFrame(columns=df.columns)),
890
+ inputs=[dataframe],
891
+ outputs=[document_column, retrieval_reranking, dataframe],
892
+ )
893
+
894
+ app.load(fn=swap_visibility, outputs=main_ui)
895
+ app.load(fn=get_org_dropdown, outputs=[org_name])
896
+ app.load(fn=get_random_repo_name, outputs=[repo_name])
src/synthetic_dataset_generator/apps/textcat.py CHANGED
@@ -20,7 +20,7 @@ from synthetic_dataset_generator.apps.base import (
20
  validate_push_to_hub,
21
  )
22
  from synthetic_dataset_generator.constants import DEFAULT_BATCH_SIZE
23
- from synthetic_dataset_generator.pipelines.base import get_rewriten_prompts
24
  from synthetic_dataset_generator.pipelines.embeddings import (
25
  get_embeddings,
26
  get_sentence_embedding_dimensions,
@@ -120,7 +120,7 @@ def generate_dataset(
120
  # create text classification data
121
  n_processed = 0
122
  textcat_results = []
123
- rewritten_system_prompts = get_rewriten_prompts(system_prompt, num_rows)
124
  while n_processed < num_rows:
125
  progress(
126
  2 * 0.5 * n_processed / num_rows,
@@ -314,6 +314,7 @@ def push_dataset(
314
  if client is None:
315
  return ""
316
  labels = get_preprocess_labels(labels)
 
317
  settings = rg.Settings(
318
  fields=[
319
  rg.TextField(
@@ -354,7 +355,6 @@ def push_dataset(
354
  dataframe["text_length"] = dataframe["text"].apply(len)
355
  dataframe["text_embeddings"] = get_embeddings(dataframe["text"].to_list())
356
 
357
- progress(0.5, desc="Creating dataset")
358
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
359
  if rg_dataset is None:
360
  rg_dataset = rg.Dataset(
@@ -559,7 +559,6 @@ with gr.Blocks() as app:
559
  labels=labels.value,
560
  num_labels=len(labels.value) if multi_label.value else 1,
561
  num_rows=num_rows.value,
562
- temperature=temperature.value,
563
  )
564
  pipeline_code = gr.Code(
565
  value=code,
@@ -644,7 +643,6 @@ with gr.Blocks() as app:
644
  labels,
645
  multi_label,
646
  num_rows,
647
- temperature,
648
  ],
649
  outputs=[pipeline_code],
650
  ).success(
@@ -662,7 +660,7 @@ with gr.Blocks() as app:
662
  _get_dataframe(),
663
  ),
664
  inputs=[dataframe],
665
- outputs=[dataset_description, system_prompt, labels, dataframe],
666
  )
667
 
668
  app.load(fn=swap_visibility, outputs=main_ui)
 
20
  validate_push_to_hub,
21
  )
22
  from synthetic_dataset_generator.constants import DEFAULT_BATCH_SIZE
23
+ from synthetic_dataset_generator.pipelines.base import get_rewritten_prompts
24
  from synthetic_dataset_generator.pipelines.embeddings import (
25
  get_embeddings,
26
  get_sentence_embedding_dimensions,
 
120
  # create text classification data
121
  n_processed = 0
122
  textcat_results = []
123
+ rewritten_system_prompts = get_rewritten_prompts(system_prompt, num_rows)
124
  while n_processed < num_rows:
125
  progress(
126
  2 * 0.5 * n_processed / num_rows,
 
314
  if client is None:
315
  return ""
316
  labels = get_preprocess_labels(labels)
317
+ progress(0.5, desc="Creating dataset in Argilla")
318
  settings = rg.Settings(
319
  fields=[
320
  rg.TextField(
 
355
  dataframe["text_length"] = dataframe["text"].apply(len)
356
  dataframe["text_embeddings"] = get_embeddings(dataframe["text"].to_list())
357
 
 
358
  rg_dataset = client.datasets(name=repo_name, workspace=hf_user)
359
  if rg_dataset is None:
360
  rg_dataset = rg.Dataset(
 
559
  labels=labels.value,
560
  num_labels=len(labels.value) if multi_label.value else 1,
561
  num_rows=num_rows.value,
 
562
  )
563
  pipeline_code = gr.Code(
564
  value=code,
 
643
  labels,
644
  multi_label,
645
  num_rows,
 
646
  ],
647
  outputs=[pipeline_code],
648
  ).success(
 
660
  _get_dataframe(),
661
  ),
662
  inputs=[dataframe],
663
+ outputs=[dataset_description, system_prompt, labels, multi_label, dataframe],
664
  )
665
 
666
  app.load(fn=swap_visibility, outputs=main_ui)
src/synthetic_dataset_generator/pipelines/base.py CHANGED
@@ -39,7 +39,7 @@ def _get_prompt_rewriter():
39
  return prompt_rewriter
40
 
41
 
42
- def get_rewriten_prompts(prompt: str, num_rows: int):
43
  prompt_rewriter = _get_prompt_rewriter()
44
  # create prompt rewrites
45
  inputs = [
 
39
  return prompt_rewriter
40
 
41
 
42
+ def get_rewritten_prompts(prompt: str, num_rows: int):
43
  prompt_rewriter = _get_prompt_rewriter()
44
  # create prompt rewrites
45
  inputs = [
src/synthetic_dataset_generator/pipelines/chat.py CHANGED
@@ -227,7 +227,7 @@ def get_response_generator(system_prompt, num_turns, temperature, is_sample):
227
  return response_generator
228
 
229
 
230
- def generate_pipeline_code(system_prompt, num_turns, num_rows, temperature):
231
  input_mappings = _get_output_mappings(num_turns)
232
 
233
  code = f"""
@@ -242,7 +242,9 @@ SYSTEM_PROMPT = "{system_prompt}"
242
 
243
  with Pipeline(name="sft") as pipeline:
244
  magpie = MagpieGenerator(
245
- llm={_get_llm_class()}.from_dict({_get_llm().model_dump()}),
 
 
246
  n_turns={num_turns},
247
  num_rows={num_rows},
248
  batch_size=1,
 
227
  return response_generator
228
 
229
 
230
+ def generate_pipeline_code(system_prompt, num_turns, num_rows):
231
  input_mappings = _get_output_mappings(num_turns)
232
 
233
  code = f"""
 
242
 
243
  with Pipeline(name="sft") as pipeline:
244
  magpie = MagpieGenerator(
245
+ llm={_get_llm_class()}.from_dict(
246
+ {_get_llm().dump()}
247
+ ),
248
  n_turns={num_turns},
249
  num_rows={num_rows},
250
  batch_size=1,
src/synthetic_dataset_generator/pipelines/rag.py ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from typing import List
4
+
5
+ from datasets import get_dataset_config_names, get_dataset_split_names
6
+ from distilabel.steps.tasks import (
7
+ GenerateSentencePair,
8
+ TextGeneration,
9
+ )
10
+
11
+ from synthetic_dataset_generator.constants import MAX_NUM_TOKENS
12
+ from synthetic_dataset_generator.pipelines.base import _get_llm, _get_llm_class
13
+
14
+ DEFAULT_DATASET_DESCRIPTIONS = [
15
+ "A dataset to retrieve information from legal documents.",
16
+ "A dataset to search for economical techniques.",
17
+ ]
18
+
19
+ PROMPT_CREATION_PROMPT = """
20
+
21
+ You are an AI assistant specialized in designing retrieval-augmented generation (RAG) tasks for dataset creation.
22
+
23
+ Your task is to generate a well-structured and descriptive prompt based on the provided dataset description and company context. Respond with only the generated prompt and nothing else.
24
+
25
+ The prompt should closely follow the style and structure of the example prompts below. Ensure that you include all relevant details from the dataset description and reflect the company context accurately.
26
+
27
+ Description: A dataset to retrieve information from legal documents.
28
+ Output: A dataset to retrieve information from a collection of legal documents related to the US law system and the status of contracts.
29
+
30
+ Description: A dataset to search for economical techniques.
31
+ Output: A dataset to search for economical techniques and strategies for the European market and the financial sector.
32
+
33
+ Description: A dataset covering FAQ questions for a tech company called Argilla that sells technology datasets within the open-source Natural Language Processing space.
34
+ Output: A dataset covering FAQ questions for a tech company called Argilla that sells technology datasets within the open-source Natural Language Processing space.
35
+
36
+ Description:
37
+ """
38
+
39
+ SYSTEM_PROMPT_CHUCKS = """
40
+ You are a helpful and knowledgeable AI assistant. Your task is to generate concise and informative text chunks relevant to the given retrieval task.
41
+
42
+ Ensure the text chunks are:
43
+ - Focused and directly related to the retrieval task.
44
+ - Clear, truthful, and based on your general knowledge.
45
+
46
+ Do not include or reference the retrieval task itself in the generated chunks.
47
+ """
48
+
49
+ CHUNKS_TEMPLATE = """You have been assigned to generate text chunks based on the following retrieval task: {{ task }}.
50
+
51
+ Provide only the text chunks without explaining your process or reasoning.
52
+
53
+ Ensure the chunks are clear, accurate, and directly relevant to the task.
54
+
55
+ Use your general knowledge to create informative and precise outputs.
56
+ """
57
+
58
+ SYSTEM_PROMPT_RAG = """
59
+ You are a helpful AI assistant. Your task is to answer the following question based on the provided document.
60
+
61
+ If the answer is not explicitly stated in the document, use your knowledge to provide the most relevant and accurate answer possible.
62
+
63
+ If you cannot answer the question based on the given information, state that clearly.
64
+ """
65
+
66
+ RAG_TEMPLATE = """Document:
67
+ {{ context }}
68
+
69
+ Question: {{ question }}
70
+
71
+ Please provide a clear and concise answer to the question based on the information in the document:
72
+ """.rstrip()
73
+
74
+
75
+ def get_prompt_generator():
76
+ generation_kwargs = {
77
+ "temperature": 0.8,
78
+ "max_new_tokens": MAX_NUM_TOKENS,
79
+ }
80
+ text_generator = TextGeneration(
81
+ llm=_get_llm(generation_kwargs=generation_kwargs),
82
+ system_prompt=PROMPT_CREATION_PROMPT,
83
+ use_system_prompt=True,
84
+ )
85
+
86
+ text_generator.load()
87
+ return text_generator
88
+
89
+
90
+ def get_chunks_generator(temperature, is_sample):
91
+ generation_kwargs = {
92
+ "temperature": temperature,
93
+ "max_new_tokens": MAX_NUM_TOKENS if is_sample else 256,
94
+ }
95
+ text_generator = TextGeneration(
96
+ llm=_get_llm(generation_kwargs=generation_kwargs),
97
+ system_prompt=SYSTEM_PROMPT_CHUCKS,
98
+ template=CHUNKS_TEMPLATE,
99
+ columns=["task"],
100
+ use_system_prompt=True,
101
+ )
102
+
103
+ text_generator.load()
104
+ return text_generator
105
+
106
+
107
+ def get_sentence_pair_generator(action, triplet, temperature, is_sample):
108
+ generation_kwargs = {
109
+ "temperature": temperature,
110
+ "max_new_tokens": 256 if is_sample else MAX_NUM_TOKENS,
111
+ }
112
+ sentence_pair_generator = GenerateSentencePair(
113
+ llm=_get_llm(generation_kwargs=generation_kwargs),
114
+ triplet=triplet,
115
+ action=action,
116
+ hard_negative=True,
117
+ )
118
+ sentence_pair_generator.load()
119
+ return sentence_pair_generator
120
+
121
+
122
+ def get_response_generator(temperature, is_sample):
123
+ generation_kwargs = {
124
+ "temperature": temperature,
125
+ "max_new_tokens": MAX_NUM_TOKENS if is_sample else 256,
126
+ }
127
+ text_generator = TextGeneration(
128
+ llm=_get_llm(generation_kwargs=generation_kwargs),
129
+ system_prompt=SYSTEM_PROMPT_RAG,
130
+ template=RAG_TEMPLATE,
131
+ columns=["context", "question"],
132
+ use_system_prompt=True,
133
+ )
134
+
135
+ text_generator.load()
136
+ return text_generator
137
+
138
+
139
+ def generate_pipeline_code(
140
+ repo_id: str,
141
+ file_paths: List[str],
142
+ input_type: str,
143
+ system_prompt: str,
144
+ document_column: str,
145
+ retrieval_reranking: list[str],
146
+ num_rows: int = 10,
147
+ ) -> str:
148
+ if repo_id is None:
149
+ subset = "default"
150
+ split = "train"
151
+ else:
152
+ subset = get_dataset_config_names(repo_id)[0]
153
+ split = get_dataset_split_names(repo_id, subset)[0]
154
+ retrieval = "Retrieval" in retrieval_reranking
155
+ reranking = "Reranking" in retrieval_reranking
156
+ base_code = f"""
157
+ # Requirements: `pip install distilabel[hf-inference-endpoints]`
158
+ {"import random" if input_type == "prompt-input" else ""}
159
+ from distilabel.models import {_get_llm_class()}
160
+ from distilabel.pipeline import Pipeline
161
+ from distilabel.steps import KeepColumns{", LoadDataFromDicts" if input_type != "dataset-input" else ""}{", LoadDataFromHub" if input_type == "dataset-input" else ""}{", CombineOutputs" if retrieval and reranking else ""}
162
+ from distilabel.steps.tasks import GenerateSentencePair, TextGeneration {", GenerateTextRetrievalData" if input_type == "prompt-input" else ""}
163
+
164
+ SYSTEM_PROMPT_RAG = '''
165
+ You are a helpful AI assistant. Your task is to answer the following question based on the provided document.
166
+
167
+ If the answer is not explicitly stated in the document, use your knowledge to provide the most relevant and accurate answer possible.
168
+
169
+ If you cannot answer the question based on the given information, state that clearly.
170
+ '''
171
+
172
+ RAG_TEMPLATE = '''Document:
173
+ {{{{ filename }}}}
174
+
175
+ Question: {{{{ question }}}}
176
+
177
+ Please provide a clear and concise answer to the question based on the information in the document:
178
+ '''.rstrip()
179
+ """
180
+
181
+ if input_type == "file-input":
182
+ base_code += """
183
+ data = process_and_chunk_files(files=[files])
184
+ """
185
+
186
+ if input_type == "prompt-input":
187
+ pipeline = f"""
188
+ TASK_SYSTEM_PROMPT = '''
189
+
190
+ {system_prompt}
191
+ '''
192
+
193
+ with Pipeline(name="rag") as pipeline:
194
+
195
+ task_generator = LoadDataFromDicts(data=[{{"task": TASK_SYSTEM_PROMPT}}])
196
+
197
+ sentence_similarity_generation = GenerateTextRetrievalData(
198
+ llm={_get_llm_class()}.from_dict(
199
+ {_get_llm().dump()}
200
+ ),
201
+ seed=random.randint(0, 2**32 - 1),
202
+ query_type="common",
203
+ difficulty="high school",
204
+ clarity="clear",
205
+ num_generations={num_rows},
206
+ output_mappings={{"positive_document": "anchor"}},
207
+ )
208
+
209
+ keep_columns_prompt = KeepColumns(
210
+ columns=["anchor"],
211
+ )
212
+ """
213
+ else:
214
+ pipeline = """
215
+ with Pipeline(name="rag") as pipeline:
216
+ """
217
+ if input_type == "file-input":
218
+ pipeline += """
219
+ load_the_dataset = LoadDataFromDicts(
220
+ data = data,
221
+ )
222
+ """
223
+ else:
224
+ pipeline += f"""
225
+ load_the_dataset = LoadDataFromHub(
226
+ repo_id="{repo_id}",
227
+ config="{subset}",
228
+ split="{split}",
229
+ num_examples={num_rows},
230
+ batch_size=2,
231
+ output_mappings={{'{document_column}': 'anchor'}}
232
+ )
233
+ """
234
+
235
+ pipeline += f"""
236
+ generate_retrieval_pairs = GenerateSentencePair(
237
+ triplet={str(retrieval)},
238
+ hard_negative=True,
239
+ action="query",
240
+ llm={_get_llm_class()}.from_dict(
241
+ {_get_llm().dump()}
242
+ ),
243
+ output_mappings={{"positive": "positive_retrieval"{', "negative": "negative_retrieval"' if retrieval else ""}}},
244
+ input_batch_size=10,
245
+ )
246
+ """
247
+
248
+ if reranking:
249
+ pipeline += f"""
250
+ generate_reranking_pairs = GenerateSentencePair(
251
+ triplet=True,
252
+ hard_negative=True,
253
+ action="semantically-similar",
254
+ llm={_get_llm_class()}.from_dict(
255
+ {_get_llm().dump()}
256
+ ),
257
+ input_batch_size=10,
258
+ output_mappings={{"positive": "positive_reranking", "negative": "negative_reranking"}},
259
+ )
260
+
261
+ combine_outputs = CombineOutputs()
262
+ """
263
+
264
+ pipeline += f"""
265
+ generate_response = TextGeneration(
266
+ llm={_get_llm_class()}.from_dict(
267
+ {_get_llm().dump()}
268
+ ),
269
+ system_prompt=SYSTEM_PROMPT_RAG,
270
+ template=RAG_TEMPLATE,
271
+ columns=["filename", "question"],
272
+ use_system_prompt=True,
273
+ input_mappings={{"filename": "anchor", "question": "positive_retrieval"}},
274
+ output_mappings={{"generation": "response"}},
275
+ )
276
+
277
+ keep_columns = KeepColumns(
278
+ columns=["anchor", "positive_retrieval", "response"{', "negative_retrieval"' if retrieval else ""}{', "positive_reranking", "negative_reranking"' if reranking else ""}],
279
+ )
280
+ """
281
+
282
+ pipeline_steps = (
283
+ "[generate_retrieval_pairs, generate_reranking_pairs] >> combine_outputs >> generate_response >> keep_columns"
284
+ if reranking
285
+ else "generate_retrieval_pairs >> generate_response >> keep_columns"
286
+ )
287
+
288
+ pipeline += """
289
+ task_generator >> sentence_similarity_generation >> keep_columns_prompt >> {pipeline_steps}
290
+ """.format(pipeline_steps=pipeline_steps) if input_type == "prompt-input" else """
291
+ load_the_dataset >> {pipeline_steps}
292
+ """.format(pipeline_steps=pipeline_steps)
293
+
294
+ pipeline += """
295
+ if __name__ == "__main__":
296
+ distiset = pipeline.run(use_cache=False)
297
+ print(distiset)
298
+ if distiset:
299
+ print(distiset["default"]["train"][0])
300
+ """
301
+
302
+ return base_code + pipeline
src/synthetic_dataset_generator/pipelines/textcat.py CHANGED
@@ -126,7 +126,6 @@ def generate_pipeline_code(
126
  labels: List[str] = None,
127
  num_labels: int = 1,
128
  num_rows: int = 10,
129
- temperature: float = 0.9,
130
  ) -> str:
131
  labels = get_preprocess_labels(labels)
132
  base_code = f"""
@@ -142,10 +141,12 @@ SYSTEM_PROMPT = "{system_prompt}"
142
 
143
  with Pipeline(name="textcat") as pipeline:
144
 
145
- task_generator = LoadDataFromDicts(data=[{{"task": TEXT_CLASSIFICATION_TASK}}])
146
 
147
  textcat_generation = GenerateTextClassificationData(
148
- llm={_get_llm_class()}.from_dict({_get_llm().model_dump()}),
 
 
149
  seed=random.randint(0, 2**32 - 1),
150
  difficulty={None if difficulty == "mixed" else repr(difficulty)},
151
  clarity={None if clarity == "mixed" else repr(clarity)},
@@ -178,10 +179,12 @@ with Pipeline(name="textcat") as pipeline:
178
  )
179
 
180
  textcat_labeller = TextClassification(
181
- llm={_get_llm_class()}.from_dict({_get_llm().model_dump()}),
 
 
182
  n={num_labels},
183
  available_labels={labels},
184
- context=TEXT_CLASSIFICATION_TASK,
185
  default_label="unknown"
186
  )
187
 
 
126
  labels: List[str] = None,
127
  num_labels: int = 1,
128
  num_rows: int = 10,
 
129
  ) -> str:
130
  labels = get_preprocess_labels(labels)
131
  base_code = f"""
 
141
 
142
  with Pipeline(name="textcat") as pipeline:
143
 
144
+ task_generator = LoadDataFromDicts(data=[{{"task": SYSTEM_PROMPT}}])
145
 
146
  textcat_generation = GenerateTextClassificationData(
147
+ llm={_get_llm_class()}.from_dict(
148
+ {_get_llm().dump()}
149
+ ),
150
  seed=random.randint(0, 2**32 - 1),
151
  difficulty={None if difficulty == "mixed" else repr(difficulty)},
152
  clarity={None if clarity == "mixed" else repr(clarity)},
 
179
  )
180
 
181
  textcat_labeller = TextClassification(
182
+ llm={_get_llm_class()}.from_dict(
183
+ {_get_llm().dump()}
184
+ ),
185
  n={num_labels},
186
  available_labels={labels},
187
+ context=SYSTEM_PROMPT,
188
  default_label="unknown"
189
  )
190