You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

GPTtrace.py 5.8 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #! /bin/env python3
  2. import os
  3. import argparse
  4. from revChatGPT.V1 import Chatbot
  5. from typing import List, Optional, Tuple
  6. from marko.parser import Parser
  7. from marko.block import FencedCode
  8. from marko.inline import RawText
  9. from pathlib import Path
  10. ENV_UUID = "GPTTRACE_CONV_UUID"
  11. ENV_ACCESS_TOKEN = "GPTTRACE_ACCESS_TOKEN"
  12. PROMPTS_DIR = Path("./prompts")
  13. def main():
  14. parser = argparse.ArgumentParser(
  15. prog='GPTtrace',
  16. description='Use ChatGPT to write eBPF programs (bpftrace, etc.)')
  17. group = parser.add_mutually_exclusive_group()
  18. group.add_argument(
  19. "-i", "--info", help="Let ChatGPT explain what's eBPF", action="store_true")
  20. group.add_argument(
  21. "-e", "--execute", help="Generate commands using your input with ChatGPT, and run it", action="store", metavar="TEXT")
  22. group.add_argument(
  23. "-g", "--generate", help="Generate eBPF programs using your input with ChatGPT", action="store", metavar="TEXT")
  24. group.add_argument(
  25. "--train", help="Train ChatGPT with conversions we provided", action="store_true")
  26. parser.add_argument(
  27. "-v", "--verbose", help="Print the prompt and receive message", action="store_true")
  28. parser.add_argument(
  29. "-u", "--uuid", help=f"Conversion UUID to use, or passed through environment variable `{ENV_UUID}`")
  30. parser.add_argument("-t", "--access-token",
  31. help=f"ChatGPT access token, see `https://chat.openai.com/api/auth/session` or passed through `{ENV_ACCESS_TOKEN}`")
  32. args = parser.parse_args()
  33. access_token = args.access_token or os.environ.get(ENV_ACCESS_TOKEN, None)
  34. conv_uuid = args.uuid or os.environ.get(ENV_UUID, None)
  35. if access_token is None:
  36. print(
  37. f"Either provide your access token through `-t` or through environment variable {ENV_ACCESS_TOKEN}")
  38. return
  39. chatbot = Chatbot(config={"access_token": access_token})
  40. if args.info:
  41. generate_result(chatbot, "Explain what's eBPF", conv_uuid, True)
  42. elif args.execute is not None:
  43. desc: str = args.execute
  44. print("Sending query to ChatGPT: " + desc)
  45. ret_val, _ = generate_result(
  46. chatbot, construct_running_prompt(desc), conv_uuid, args.verbose)
  47. # print(ret_val)
  48. parsed = make_executable_command(ret_val)
  49. # print(f"Command to run: {parsed}")
  50. print("Press Ctrl+C to stop the program....")
  51. os.system("sudo " + parsed)
  52. elif args.generate is not None:
  53. desc: str = args.generate
  54. print("Sending query to ChatGPT: " + desc)
  55. ret_val, _ = generate_result(
  56. chatbot, construct_generate_prompt(desc), conv_uuid, True)
  57. # print(ret_val)
  58. parsed = extract_code_blocks(ret_val)
  59. # print(f"Command to run: {parsed}")
  60. with open("generated.bpf.c", "w") as f:
  61. for code in parsed:
  62. f.write(code)
  63. elif args.train:
  64. prompts = os.listdir(PROMPTS_DIR)
  65. prompts.sort()
  66. # conv_uuid could be None, in which we will create a new session and use it in the next steps
  67. session = conv_uuid
  68. for file in prompts:
  69. info = f"Training ChatGPT with `{file}`"
  70. print("-"*len(info))
  71. print(info)
  72. print("-"*len(info))
  73. with open(PROMPTS_DIR/file, "r") as f:
  74. input_data = f.read()
  75. if args.verbose:
  76. print(input_data)
  77. print("-"*len(info))
  78. _, session = generate_result(
  79. chatbot, input_data, conv_uuid, args.verbose)
  80. print(f"Trained session: {session}")
  81. else:
  82. parser.print_help()
  83. def construct_generate_prompt(text: str) -> str:
  84. return f'''You are now a translater from human language to {os.uname()[0]} eBPF programs.
  85. Please write eBPF programs for me.
  86. No explanation required, no instruction required, don't tell me how to compile and run.
  87. What I want is a eBPF program for: {text}.'''
  88. def construct_running_prompt(text: str) -> str:
  89. return f'''You are now a translater from human language to {os.uname()[0]} shell bpftrace command.
  90. No explanation required.
  91. respond with only the raw shell bpftrace command.
  92. It should be start with `bpftrace`.
  93. Your response should be able to put into a shell and run directly.
  94. Just output in one line, without any description, or any other text that cannot be run in shell.
  95. What should I type to shell to trace using bpftrace for: {text}, in one line.'''
  96. def make_executable_command(command: str) -> str:
  97. if command.startswith('\n'):
  98. command = command[1:]
  99. if command.endswith('\n'):
  100. command = command[:-1]
  101. if command.startswith('`'):
  102. command = command[1:]
  103. if command.endswith('`'):
  104. command = command[:-1]
  105. command = command.strip()
  106. command = command.split('User: ')[0]
  107. return command
  108. def generate_result(bot: Chatbot, text: str, session: Optional[str] = None, print_out: bool = False) -> Tuple[str, str]:
  109. from io import StringIO
  110. prev_text = ""
  111. buf = StringIO()
  112. received_session = ""
  113. for data in bot.ask(
  114. text, conversation_id=session
  115. ):
  116. received_session = data["conversation_id"]
  117. message = data["message"][len(prev_text):]
  118. if print_out:
  119. print(message, end="", flush=True)
  120. buf.write(message)
  121. prev_text = data["message"]
  122. if print_out:
  123. print()
  124. return buf.getvalue(), received_session
  125. def extract_code_blocks(text: str) -> List[str]:
  126. result = []
  127. parser = Parser()
  128. for block in parser.parse(text).children:
  129. if type(block) is FencedCode:
  130. block: FencedCode
  131. blk: RawText = block.children[0]
  132. result.append(blk.children)
  133. return result
  134. if __name__ == "__main__":
  135. main()

Generate eBPF programs and tracing with ChatGPT and natural language