見出し画像

自然言語で知りたいコード実装をシュッと探る

OSS のソースコードって全部公開されてるからいいですよね。
頑張って読んでいけば知りたい実装とかわかるし勉強にもなる。

ただ、、、時間がかかるのですよねぇ、、、

ということで GitHub リポジトリのコードを全部読み込んで ChatGPT で欲しい情報がシュッと取り出せるか雑にやってみた。

import os
import multiprocessing
import itertools
from langchain.text_splitter import TokenTextSplitter
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.prompts.chat import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
)

os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

def get_repository_contents(repository_path):
    if os.path.isdir(repository_path):
        contents = []
        for entry in os.scandir(repository_path):
            if entry.is_file():
                if entry.name.endswith(("py")):
                    with open(entry.path, 'r', encoding='utf-8') as f:
                        contents.append(f.read())
            elif entry.is_dir():
                contents.extend(get_repository_contents(entry.path))
        return contents
    else:
        return []

def get_all_repository_contents(base_directory, batch_size=1000):
    with multiprocessing.Pool() as pool:
        paths = [os.path.join(base_directory, d) for d in os.listdir(base_directory)]
        contents = pool.imap_unordered(get_repository_contents, paths, chunksize=batch_size)
        yield from itertools.chain.from_iterable(contents)

def generate_serially(texts, prompt, history):
    chat = ChatOpenAI(temperature=0.5, model_name="gpt-3.5-turbo", request_timeout=500)
    chain = LLMChain(llm=chat, prompt=prompt)
    result = history
    for text in texts:
        resp = chain.run(text=text, current_result=result)
        result = resp
    return result

prompt_template = ("""
- Instructions
  YOUR_INSTRUCTION

  Finally, output Explain.md.

- Prerequisite
  Assume that the given Input is incomplete programming language code.
  Imagine that the entire application is composed from the given Input.

- input
------------
{text}
------------

- Current Result
------------
{current_result}
------------
""")
human_message_prompt = HumanMessagePromptTemplate(
        prompt=PromptTemplate(
            template=prompt_template,
            input_variables=["text", "current_result"],
        )
    )
chat_prompt_template = ChatPromptTemplate.from_messages([human_message_prompt])
output = ""
target_dir = '/base_directory'
for content in get_all_repository_contents(target_dir):
    text_splitter = TokenTextSplitter(chunk_size=500, allowed_special={''})
    texts = text_splitter.split_text(content)
    output = generate_serially(texts, chat_prompt_template, output)

with open("./output.md", mode="w") as f:
    f.write(readme)

こんな感じで雑なコード作る

  1. ローカルに適当なリポジトリをクローンする

  2. クローンしたリポジトリ配下の特定形式のファイル (.py とか) だけ読むようにする

  3. 質問プロンプトを書く

  4. グリグリコードを読んでいく

  5. 該当する情報があれば拾って要約する

  6. 要約は次のリクエストに渡す

  7. 最終的にファイルに書き出す

ってなわけでやってみた

今回は

で出力フォーマットをどうやって担保してるの?

という質問でやった。

結果

- How to control the output format of the LLM

LLM (Live Code Cell Markup Language) is used to describe programming code blocks in notebook documents. The following syntaxes can be used to control the output format of the LLM for a given input:

1. Syntax Highlighting: To highlight syntax, enclose the code block in triple backticks (```) and add the name of the programming language after the first set of backticks:

   ```
   ```python
   code here
   ```
   ```

2. Hiding the Code Block: To hide the code block, add `hide_input=true` to the first line of the code block:

   ```
   ```python 
   # hide the input code
   hide_input=true 
   code here
   ```
   ```

3. Hiding the Output: To hide the output of the code block, add `hide_output=true` to the first line of the code block:

   ```
   ```python 
   # hide the output
   hide_output=true 
   code here
   ```
   ```

4. Automatic Display of Output: To show the output of the code block automatically, add `run=true` to the first line of the code block:

   ```
   ```python 
   # display output automatically
   run=true 
   code here
   ```
   ```

5. Display Output on User Interaction: To show the output of the code block on user interaction, add `run=auto` to the first line of the code block:

   ```
   ```python 
   # display output on user interaction
   run=auto 
   code here
   ```
   ```

6. Adding a Title: To add a title to the code block, add `title=` followed by the desired title in quotes to the first line of the code block:

   ```
   ```python 
   # add a title
   title="My code block" 
   code here
   ```
   ```

7. Adding a Caption: To add a caption to the code block, add `caption=` followed by the desired caption in quotes to the first line of the code block:

   ```
   ```python 
   # add a caption
   caption="Figure 1. My code block" 
   code here
   ```
   ```

By using these syntaxes, the output format of the LLM for a given input can be easily controlled. For instance, the given input code block can be highlighted using the syntax highlighting feature by enclosing the code block in triple backticks and adding the language name. The output format can be further controlled by using the other LLM syntaxes mentioned above.

んー。

なんか欲しい情報と違う。

今回ステップごとの履歴もとっていたのでそれを見てみると
投げたコードチャンクによっては「わかりません」ってことで前回の要約すら消して回答してることがしばしば、、、

ので、過去のコンテキストを吹き飛ばして次に継承せずにリクエストに進んだのでよくわからん結果になっちゃった。

あと、今回直列でリクエスト回したので完了までものすごーく時間かかった。

結論

行けそうな感じだけどプロンプトのチューニングとかエラーハンドリングとかちゃんとしないとダメそう。
あと直列実行だと時間かかるからやり方変えた方がいい。

余談

README.md がないちっこいリポジトリに対して README の情報集めて書いてっていうプロンプトでやったらそれっぽいのはできた。

おしまい。

この記事が気に入ったらサポートをしてみませんか?