From 56c182364643f0466748d92ae8f94ea2b66901ff Mon Sep 17 00:00:00 2001 From: Kevin Burnett <18027+burnettk@users.noreply.github.com> Date: Thu, 24 Aug 2023 11:49:17 -0700 Subject: [PATCH] script to update a doc page with chatgpt (#451) Co-authored-by: burnettk --- .../sub-processes_and_call_activities.md | 44 ++++----- docs/bin/edit | 12 +++ docs/bin/gpt-proofread.py | 97 +++++++++++++++++++ 3 files changed, 131 insertions(+), 22 deletions(-) create mode 100755 docs/bin/edit create mode 100644 docs/bin/gpt-proofread.py diff --git a/docs/Building_Diagrams/sub-processes_and_call_activities.md b/docs/Building_Diagrams/sub-processes_and_call_activities.md index 6526f316..84d5ef58 100644 --- a/docs/Building_Diagrams/sub-processes_and_call_activities.md +++ b/docs/Building_Diagrams/sub-processes_and_call_activities.md @@ -1,41 +1,41 @@ # Sub-Processes and Call Activities -Both sub-processes and call activities are useful for simplifying and organizing complex workflows by organizing workflows within a larger process. +Sub-processes and call activities are both useful for simplifying and organizing complex workflows within larger processes. They have distinct purposes and are used in different scenarios. -**Reasons to use a Sub-Processes or Call Activities:** +**Reasons to use a Sub-Process or Call Activity:** -- Consolidate tasks that have either common features or collaboratively form a distinct functionality. For instance, a Notification Gateway, which includes script tasks and a service task, works together to construct and send a notification like an email. - -- Group tasks where a boundary event can be efficiently applied to the entire group. For instance, instead of individually assigning a condition or timer to each task, all tasks can be included within a sub-process or call activity, where the condition or timer inherently applies to all contained tasks. +- Consolidating tasks with common features or forming a distinct functionality, such as a Notification Gateway that constructs and sends notifications like emails. + +- Grouping tasks where a boundary event can efficiently be applied to the entire group, avoiding the need to assign conditions or timers individually to each task. ## Call Process ![active_call_process](images/active_call_process.png) -A call process is similar to a sub-process in that it encapsulates part of a workflow, but it is designed to be reused across multiple different processes. It's essentially a stand-alone process that can be "called" into action as required by other processes. Using a call process can help to eliminate redundancy and ensure consistent execution of the process steps. +A call process encapsulates part of a workflow and can be reused across multiple processes. It functions as a stand-alone process that can be called into action by other processes. Using a call process eliminates redundancy and ensures consistent execution of process steps. **When to use a Call Process:** -- **Reusability** a certain set of activities is being reused in multiple main processes, it's a good idea to define it as a call process and reuse it whenever needed by calling the process. - -- **Reduce Complexity:** If your main process is becoming too complex, breaking it down into smaller, more manageable call processes can make it easier to understand and maintain. - -- **Version Control**: If a certain process may undergo changes over time but is used in multiple places, defining it as a call process allows you to make changes in one place and have those changes propagate to all instances where the process is used. +- **Reusability:** When a set of activities is reused in multiple main processes, defining it as a call process allows for easy reuse by calling the process. -- **Delegation**: When different people or teams need to be responsible for the execution of tasks within a process, a call activity can be useful and can be assigned to the most appropriate person or team. +- **Reducing Complexity:** Breaking down a complex main process into smaller, manageable call processes can make it easier to understand and maintain. -- **Access Control**: If a specific segment of a process isn't meant to be available to every user, converting it into a call process can aid in establishing access control over that particular process. Additional information about this can be found in the [Admin and Permission](../DevOps_installation_integration/admin_and_permissions.md) section. +- **Version Control:** If a process may undergo changes over time but is used in multiple places, defining it as a call process allows changes to be made in one place and propagated to all instances where the process is used. -## Sub-processes +- **Delegation:** When different individuals or teams are responsible for executing tasks within a process, a call activity can be assigned to the most appropriate person or team. -![active_subtask](images/active_subprocess.png) +- **Access Control:** If a specific segment of a process should not be available to every user, converting it into a call process helps establish access control. More information about this can be found in the [Admin and Permission](../DevOps_installation_integration/admin_and_permissions.md) section. -Sub-processes are generally employed within a single process, whereas a call activity has the advantage of being reusable across multiple processes. If the conditions that warrant the use of a call activity, such as reusability, aren't necessary, a sub-process is usually the preferred option. +## Sub-Processes -**When to use a sub process:** +![active_subtask](images/active_subprocess.png) -- **Consolidate similar functionalities:** When you have a group of tasks that are closely related and work well together, but don't need to be used or replicated elsewhere in other processes. - -- **Call activity is not required:** When these tasks don't meet the conditions needed for a call activity a sub-process can achieve the same goal. - -- **Conditions or events needs to be applied:** When specific conditions or events, such as a timer event, need to be applied to a set of tasks, but these tasks do not collectively form a reusable workflow that can be called as a separate process. +Sub-processes are typically used within a single process and are not reusable across multiple processes like call activities. When the conditions for reusability are not necessary, a sub-process is usually the preferred option. + +**When to use a Sub-Process:** + +- **Consolidating Similar Functionalities:** When a group of tasks are closely related and work well together, but do not need to be used or replicated elsewhere in other processes. + +- **Not Requiring a Call Activity:** When tasks do not meet the conditions required for a call activity, a sub-process can achieve the same goal. + +- **Applying Conditions or Events:** When specific conditions or events, such as a timer event, need to be applied to a set of tasks that do not collectively form a reusable workflow that can be called as a separate process. diff --git a/docs/bin/edit b/docs/bin/edit new file mode 100755 index 00000000..c8aeaf72 --- /dev/null +++ b/docs/bin/edit @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function error_handler() { + >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." + exit "$2" +} +trap 'error_handler ${LINENO} $?' ERR +set -o errtrace -o errexit -o nounset -o pipefail + +gitc Building_Diagrams/sub-processes_and_call_activities.md +python bin/gpt-proofread.py Building_Diagrams/sub-processes_and_call_activities.md +mv Building_Diagrams/sub-processes_and_call_activities.qmd Building_Diagrams/sub-processes_and_call_activities.md diff --git a/docs/bin/gpt-proofread.py b/docs/bin/gpt-proofread.py new file mode 100644 index 00000000..fb4fff0f --- /dev/null +++ b/docs/bin/gpt-proofread.py @@ -0,0 +1,97 @@ +# originally from https://mindfulmodeler.substack.com/p/proofreading-an-entire-book-with +# and then modified for our use case. +import sys +import os +from langchain.prompts import PromptTemplate +from langchain.chat_models import ChatOpenAI +from langchain.text_splitter import MarkdownTextSplitter +from langchain.text_splitter import CharacterTextSplitter +from langchain.prompts.chat import ( + ChatPromptTemplate, + SystemMessagePromptTemplate, + HumanMessagePromptTemplate, +) +from langchain.schema import ( + AIMessage, + HumanMessage, + SystemMessage +) + +human_template = """ +{text} +""" +human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) + +# system_text = """You are an expert technical editor specializing in business process management documentation written for enterprise software users. You are especially good at cutting clutter. +# +# - Improve grammar and language +# - fix errors +# - cut clutter +# - keep tone and voice +# - don't change markdown syntax, e.g. keep [@reference] +# - never cut jokes +# - output 1 line per sentence (same as input) +# """ + +# style ideas from 24 aug 2023: +# - short and focused +# - clear over fun +# - brief over verbose + +system_text = """You are an expert technical editor specializing in business process management documentation written for enterprise software users. + +- Improve grammar and language +- fix errors +- keep tone and voice +- don't change markdown syntax, e.g. keep [@reference] +- do not remove entire sentences +- never cut jokes +- output 1 line per sentence (same as input) +""" + +system_prompt = SystemMessage(content=system_text) + +openai_api_key = os.environ.get("OPENAI_API_KEY") +if openai_api_key is None: + keyfile = "oai.key" + with open(keyfile, 'r') as f: + openai_api_key = f.read().strip() + +# model = "gpt-4" +model = "gpt-3.5-turbo" + +# If you get timeouts, you might have to increase timeout parameter +llm = ChatOpenAI(openai_api_key=openai_api_key, model=model, request_timeout=240) + +def process_file(input_file): + output_file = os.path.splitext(input_file)[0] + ".qmd" + + with open(input_file, 'r') as f: + content = f.read() + + # Markdown splitter didn't work so well + # splitter = MarkdownTextSplitter(chunk_size=1000, chunk_overlap=0) + + # FIXME: actually split + # splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, chunk_overlap=0) + # docs = splitter.split_text(content) + docs = [content] + + print("Split into {} docs".format(len(docs))) + chat_prompt = ChatPromptTemplate.from_messages([system_prompt, human_message_prompt]) + + with open(output_file, 'w') as f: + for doc in docs: + print(f"doc: {doc}") + result = llm(chat_prompt.format_prompt(text=doc).to_messages()) + print(result.content) + f.write(result.content + '\n') + + print(f"Edited file saved as {output_file}") + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python script.py input_file") + else: + input_file = sys.argv[1] + process_file(input_file)