ã¯ããã«
ã¿ããªãç®é»ã·ããã¸è¡ããã ãç¹å¥ä¸æ çãããã¿ã®å¤åãã観ããããï¼ nikkieã§ãã
ããæ°æ¥Pythonã®éåæã¸ã§ãã¬ã¼ã¿ãé ã«å¼ã£ããã£ã¦ãã¾ãã
é£ããããªæ¦å¿µã§ããããã¤ãã«ãã®æãæ¥ãããã¨è
¹ã決ãã¦ç´ æ¯ããã¾ããã
â»èãéãããã¦ããã@ftnextã¾ã§ãææããã ããã¨å¤§å¤ãããããã§ãã
ç®æ¬¡
- ã¯ããã«
- ç®æ¬¡
- ã¸ã§ãã¬ã¼ã¿
- éåæã¸ã§ãã¬ã¼ã¿ãæ°ã«ãªãã ãããã£ãã
- ã¯ããã¦éåæã¸ã§ãã¬ã¼ã¿
- OpenAIã®APIã«ä¸¦è¡å¦çã§ãªã¯ã¨ã¹ã with éåæã¸ã§ãã¬ã¼ã¿
- çµããã«
- ã½ã¼ã¹ã³ã¼ãï¼OpenAIã®APIã«ä¸¦è¡å¦çã§ãªã¯ã¨ã¹ã with éåæã¸ã§ãã¬ã¼ã¿ï¼
ã¸ã§ãã¬ã¼ã¿
ã¸ã§ãã¬ã¼ã¿ã¨ã¯ãyieldãæã¤é¢æ°ã§ãã
def awesome_generator(): yield "ãããªã¼ð" yield "ã¡ãããªãã¼ð"
ã¸ã§ãã¬ã¼ã¿ã¯ãªã¹ãã¨æ¯ã¹ãã¨ã¡ã¢ãªå¹çããããç§ãPythonãæ¸ãä¸ã§ã¯ããå¿
éåã§ãã
ãªã¹ããè¿ã颿°ã®ä»£ããã«ã¸ã§ãã¬ã¼ã¿ã§å®è£
ãããã¨ãæ¤è¨ãã¾ãã
ããå°ã詳ãã説æã以ä¸ã«ããã¾ãã
éå»ã®LTãã
éåæã¸ã§ãã¬ã¼ã¿ãæ°ã«ãªãã ãããã£ãã
ãéåæã¸ã§ãã¬ã¼ã¿ããæ°ã«ãªãå§ãããã£ããã¯ãOpenAIã®APIã«3000ä»¶ã®ãªã¯ã¨ã¹ãã並è¡å¦çã§éãå®è£ ããããã¨ã
ãã®å®è£
ãããä¸ã§ãAPIãå¼ã³åºã颿°ã¯ã¬ã¹ãã³ã¹1ä»¶ãã¤yieldãããã£ãã®ã§ããã
async def call_api(...): # ãã®å®è£ ã¯ã¤ã¡ã¼ã¸ã§ã for chunk in chunked(propmts, chunk_size): coroutines = [ openai.ChatCompletion.acreate(...) for prompt in chunk ] results = await asyncio.gather(*coroutines, return_exceptions=True) for result in results: # resultãå ã«responseãçµã¿ç«ã¦ yield response
æ
£ãã¦ããªãasync/awaitã¨yieldã®çµåãæ¹ãåãããæå¿µï¼çµé¨å¤ä¸è¶³ã§ãã¨ã©ã¼ãã¡ãã£ã¨ä½è¨ã£ã¦ããããããªãç¶æ
ï¼ã
ãã®ã¨ãã¯å®è£
ãããäºé
ãå±±ç©ã¿ã ã£ãã®ã§ãyieldã使ãã®ã諦ãããªã¹ãã«3000ä»¶å
¨é¨ãéãã¦è¿ãå®è£
ã¨ãã¾ããã
async def call_api(...) -> list[OpenAIResponse]: # ãã®å®è£ ã¯ã¤ã¡ã¼ã¸ã§ã responses: list[OpenAIResponse] = [] for chunk in chunked(propmts, chunk_size): coroutines = [ openai.ChatCompletion.acreate(...) for prompt in chunk ] results = await asyncio.gather(*coroutines, return_exceptions=True) for result in results: # resultãå ã«responseãçµã¿ç«ã¦ responses.append(response) return responses
ä¸éãå®è£
ãçµããå¾ããasyncã®ä»ãã颿°ã§yieldã£ã¦éåæã¸ã§ãã¬ã¼ã¿ã£ã¦ãã¤ã ããªãã¨å¼ã£ãããå§ãã¾ãã
ã¯ããã¦éåæã¸ã§ãã¬ã¼ã¿
ç³æ¬ããããã°ã®ä¾
ãéåæã¸ã§ãã¬ã¼ã¿ãã§æ¤ç´¢ããã¨ããã£ããã1ã®ããã°ãçºè¦ã
ç§ãåãã¦è§¦ã£ãPythonã¯3.6ãªã®ã§ãããããã§éåæã¸ã§ãã¬ã¼ã¿ããµãã¼ãããã¦ããã®ãï¼
åçµãã¦åããã¾ãï¼Python 3.10.9ï¼ã
import asyncio async def spam_generator(): await asyncio.sleep(1) yield "spam1" await asyncio.sleep(2) yield "spam2" async def spam(): async for s in spam_generator(): print(s) if __name__ == "__main__": asyncio.run(spam())
% time python aish_example.py spam1 spam2 python aish_example.py 0.05s user 0.04s system 3% cpu 3.118 total
ãã®ä¾ã観å¯ããã¨
- éåæã¸ã§ãã¬ã¼ã¿
spam_generatorã¯async defã§yieldãã¦ãã - éåæã¸ã§ãã¬ã¼ã¿ã使ã
spamã¯async defã§async forãã¦ãã
ããããããéåæã¸ã§ãã¬ã¼ã¿ã使ãå´ã¯async forã使ãã°ããã®ã§ã¯ãã¨ãã仮説ãçã¾ãã¾ãã
What's New In Python 3.6ã®ä¾
ããä¸ä¾ããPython 3.6ã§å ãã£ãã®ãªããã¨å
¬å¼ããã¥ã¡ã³ãã®What's Newãè¦ã¾ãã
https://docs.python.org/ja/3/whatsnew/3.6.html#pep-525-asynchronous-generators
import asyncio async def ticker(delay, to): for i in range(to): yield i await asyncio.sleep(delay) async def print_ticker(delay, to): async for t in ticker(delay, to): print(t) if __name__ == "__main__": asyncio.run(print_ticker(0.5, 5))
% time python whats_new_example.py 0 1 2 3 4 python whats_new_example.py 0.06s user 0.05s system 4% cpu 2.660 total
éåæã¸ã§ãã¬ã¼ã¿tickerã使ãå´ã¯async forã§ä½¿ããã¨ã«ãªãã¾ããï¼â»ä½¿ãå´ã®ä¾ã¾ã§ã¯ããã¥ã¡ã³ãã«ã¯ããã¾ããï¼ã
éåæã¸ã§ãã¬ã¼ã¿ã®å®è£
ã¯ãµã¤ãã®forã§ãasync forã¯ä¸è¦ããã§ãã
OpenAIã®APIã«ä¸¦è¡å¦çã§ãªã¯ã¨ã¹ã with éåæã¸ã§ãã¬ã¼ã¿
call_apiãéåæã¸ã§ãã¬ã¼ã¿ã¨ãã使ã颿°ã«async forãå°å
¥ãã¾ãã
使ãå´ã¯ããæ¸ãããåããã¾ããð
async def main(input_path: Path, output_path: Path, chunk_size: int): examples = load_examples(input_path) responses = call_api(tqdm(prompts_generator(examples)), chunk_size) # éåæã¸ã§ãã¬ã¼ã¿ examples_generator = (e for e in examples) with jsonlines.open(output_path, "w") as writer: async for response in responses: example = next(examples_generator) # zipã®ä»£ãã writer.write(example | response)
zip颿°ã§éåæã®ã¤ãã©ãã«ã¯æ±ããªãããã ã£ãã®ã§ãããããªããã¼ãªå®è£
ã«ãªã£ã¦ãã¾ãã
ã³ã¼ãå
¨ä½ã¯è¨äºã®æå¾ã«ç¤ºãã¾ãã
ä¸è¨å®è£
ã¯ãã¡ã¤ã«IOï¼ç¹ã«ããã§ã¯æ¸ãè¾¼ã¿ï¼ãããããã³ã°ã§ãããNode.jsãæãåºãã¨ãã¡ã¤ã«IOãéåæã§ããã
ä¸è¨ã®ã³ã¼ãã¯ãéåæãªãã¡ã¤ã«IOã®ã©ã¤ãã©ãª2ãå°å
¥ãããã¨ã§ã並è¡å¦çã®æ©æµããã享åã§ããã®ã§ã¯ãªããã¨æããã¾ãã
çµããã«
Pythonã®éåæã¸ã§ãã¬ã¼ã¿ãç´ æ¯ããã¾ããã
async defã¨yieldã§éåæã¸ã§ãã¬ã¼ã¿async forã§ã¯ãªããforã§ãã
- éåæã¸ã§ãã¬ã¼ã¿ã使ãå´ã¯
async forasync defãå¿ è¦
éåæã¸ã§ãã¬ã¼ã¿ããã¡ããã¡ãããã¤ãèªæã§ãããã¸ã§ãã¬ã¼ã¿ã¸ã®ç¿çãã¤ãã³ãã«ã¼ãã使ã£ã並è¡å¦çï¼asyncioï¼ã®çè§£ã«ãã£ã¦å·®åã¯å°ãããªã£ã¦ãã¦ãå°ãè伸ã³ãããæãå±ããæè¦ã§ãã
éåæã¸ã§ãã¬ã¼ã¿ã®ããããä½¿ãæ¹ï¼ãã¹ããã©ã¯ãã£ã¹ï¼ã¯å¼ãç¶ãç´ æ¯ããã¦æ¢ãã¦ãããã¨æãã¾ãã
ç¾æç¹ã§ã¯ãæ¦å¿µã¯å®å
¨ã«çè§£ããæ°ãããï¼