Tai Truong
fix readme
d202ada
{
"name": "Lonely Stonebraker",
"description": "Design Dialogues with Langflow.",
"data": {
"nodes": [
{
"width": 384,
"height": 461,
"id": "CustomComponent-MtJjl",
"type": "genericNode",
"position": {
"x": 534.3712097224906,
"y": -135.01908566635723
},
"data": {
"type": "CustomComponent",
"node": {
"template": {
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import Data\nfrom pathlib import Path\nfrom platformdirs import user_cache_dir\nimport os\n\nclass Component(CustomComponent):\n documentation: str = \"http://docs.langflow.org/components/custom\"\n\n def build_config(self):\n return {\"text_input\":{\"display_name\":\"Text Input\", \"input_types\":[\"str\"]},\"save_path\":{\"display_name\":\"Save Path\",\n \"info\":\"Put the full path with the file name and extension\",\"value\":Path(user_cache_dir(\"langflow\"))/\"text.t1.txt\"}}\n\n def build(self, text_input:str,save_path:str) -> str:\n try:\n # Create the directory if it doesn't exist\n os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n # Open the file in write mode and save the text\n with open(save_path, 'w') as file:\n file.write(text_input)\n except Exception as e:\n raise e\n self.status = text_input\n return text_input",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": false,
"dynamic": true,
"info": ""
},
"save_path": {
"type": "str",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"value": "/home/vazz/.cache/langflow/text.t1.txt",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "save_path",
"display_name": "Save Path",
"advanced": false,
"dynamic": false,
"info": "Put the full path with the file name and extension"
},
"text_input": {
"type": "str",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"fileTypes": [],
"file_path": "",
"password": false,
"name": "text_input",
"display_name": "Text Input",
"advanced": false,
"input_types": ["str"],
"dynamic": false,
"info": "",
"value": ""
},
"_type": "CustomComponent"
},
"base_classes": ["str"],
"display_name": "text checkpoint",
"documentation": "http://docs.langflow.org/components/custom",
"custom_fields": {
"save_path": null,
"text_input": null
},
"output_types": ["str"],
"field_formatters": {},
"beta": true
},
"id": "CustomComponent-MtJjl"
},
"selected": false,
"dragging": false,
"positionAbsolute": {
"x": 534.3712097224906,
"y": -135.01908566635723
}
},
{
"width": 384,
"height": 453,
"id": "CustomComponent-7NQoq",
"type": "genericNode",
"position": {
"x": 27.487979888011637,
"y": -414.43998171034826
},
"data": {
"type": "CustomComponent",
"node": {
"template": {
"audio": {
"type": "file",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"fileTypes": [],
"file_path": "/home/vazz/.cache/langflow/1b0814b7-2964-4e09-9b4b-f7413c4fb50b/b56b043d8940daecbdec03b97ad4346488c58d7cc62016560dd333aa7a6a12ce.m4a",
"password": false,
"name": "audio",
"display_name": "audio",
"advanced": false,
"dynamic": false,
"info": "",
"value": "Audio Recording 2023-12-13 at 16.35.22.m4a"
},
"OpenAIKey": {
"type": "str",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": false,
"fileTypes": [],
"file_path": "",
"password": true,
"name": "OpenAIKey",
"display_name": "OpenAIKey",
"advanced": false,
"dynamic": false,
"info": "",
"value": ""
},
"code": {
"type": "code",
"required": true,
"placeholder": "",
"list": false,
"show": true,
"multiline": true,
"value": "from langflow.custom import CustomComponent\nfrom typing import Optional, List, Dict, Union\nfrom langflow.field_typing import (\n AgentExecutor,\n BaseChatMemory,\n BaseLanguageModel,\n BaseLLM,\n BaseLoader,\n BaseMemory,\n BaseOutputParser,\n BasePromptTemplate,\n BaseRetriever,\n Callable,\n Chain,\n ChatPromptTemplate,\n Data,\n Document,\n Embeddings,\n NestedDict,\n Object,\n PromptTemplate,\n TextSplitter,\n Tool,\n VectorStore,\n)\n\nfrom openai import OpenAI\nimport os\nimport ffmpeg\n\nclass Component(CustomComponent):\n display_name: str = \"Whisper Transcriber\"\n description: str = \"Converts audio to text using OpenAI's Whisper.\"\n\n def build_config(self):\n return {\"audio\": {\"field_type\": \"file\", \"suffixes\": [\".mp3\", \".mp4\", \".m4a\"]}, \"OpenAIKey\": {\"field_type\": \"str\", \"password\": True}}\n\n def calculate_segment_duration(self, audio_path, target_chunk_size_mb=24):\n # Calculate the target chunk size in bytes\n target_chunk_size_bytes = target_chunk_size_mb * 1024 * 1024\n\n # Use ffprobe to get the audio file information\n ffprobe_output = ffmpeg.probe(audio_path)\n print(ffprobe_output)\n # Convert duration to float\n duration = float(ffprobe_output[\"format\"][\"duration\"])\n\n # Calculate the approximate bitrate\n bitrate = os.path.getsize(audio_path) / duration\n\n # Calculate the segment duration to achieve the target chunk size\n segment_duration = target_chunk_size_bytes / bitrate\n\n return segment_duration\n\n def split_audio_into_chunks(self, audio_path, target_chunk_size_mb=24):\n # Calculate the segment duration\n segment_duration = self.calculate_segment_duration(audio_path, target_chunk_size_mb)\n\n # Create a directory to store the chunks\n output_directory = f\"{os.path.splitext(audio_path)[0]}_chunks\"\n os.makedirs(output_directory, exist_ok=True)\n\n # Use ffmpeg-python to split the audio file into chunks\n (\n ffmpeg.input(audio_path)\n .output(f\"{output_directory}/%03d{os.path.splitext(audio_path)[1]}\", codec=\"copy\", f=\"segment\", segment_time=segment_duration)\n .run()\n )\n\n # Get the list of generated chunk files\n chunks = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]\n\n return chunks\n\n def build(self, audio: str, OpenAIKey: str) -> str:\n # Split audio into chunks\n audio_chunks = self.split_audio_into_chunks(audio)\n\n client = OpenAI(api_key=OpenAIKey)\n transcripts = []\n\n try:\n for chunk in audio_chunks:\n with open(chunk, \"rb\") as chunk_file:\n transcript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=chunk_file,\n response_format=\"text\"\n )\n transcripts.append(transcript)\n finally:\n # Clean up temporary chunk files\n for chunk in audio_chunks:\n os.remove(chunk)\n\n # Concatenate transcripts into the final response\n final_response = \"\\n\".join(transcripts)\n self.status = final_response\n return final_response\n",
"fileTypes": [],
"file_path": "",
"password": false,
"name": "code",
"advanced": false,
"dynamic": true,
"info": ""
},
"_type": "CustomComponent"
},
"description": "Converts audio to text using OpenAI's Whisper.",
"base_classes": ["str"],
"display_name": "Whisper Transcriber",
"documentation": "",
"custom_fields": {
"OpenAIKey": null,
"audio": null
},
"output_types": ["str"],
"field_formatters": {},
"beta": true
},
"id": "CustomComponent-7NQoq"
},
"selected": true,
"positionAbsolute": {
"x": 27.487979888011637,
"y": -414.43998171034826
},
"dragging": false
}
],
"edges": [
{
"source": "CustomComponent-7NQoq",
"sourceHandle": "{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-7NQoqœ}",
"target": "CustomComponent-MtJjl",
"targetHandle": "{œfieldNameœ:œtext_inputœ,œidœ:œCustomComponent-MtJjlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}",
"data": {
"targetHandle": {
"fieldName": "text_input",
"id": "CustomComponent-MtJjl",
"inputTypes": ["str"],
"type": "str"
},
"sourceHandle": {
"baseClasses": ["str"],
"dataType": "CustomComponent",
"id": "CustomComponent-7NQoq"
}
},
"style": {
"stroke": "#555"
},
"className": "stroke-gray-900 stroke-connection",
"animated": false,
"id": "reactflow__edge-CustomComponent-7NQoq{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-7NQoqœ}-CustomComponent-MtJjl{œfieldNameœ:œtext_inputœ,œidœ:œCustomComponent-MtJjlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}"
}
],
"viewport": {
"x": 119.37759169012509,
"y": 351.3082742479685,
"zoom": 1
}
},
"is_component": false,
"updated_at": "2023-12-13T23:51:56.874099",
"folder": null,
"id": "1b0814b7-2964-4e09-9b4b-f7413c4fb50b",
"user_id": "8b5cf798-f1b8-4108-88fd-d7274d08d471"
}