import aiohttp
import asyncio
from typing import List, Optional
import json
from chidori import Chidori, GraphBuilder
class Story:
def __init__(self, title: str, url: Optional[str], score: Optional[float]):
self.title = title
self.url = url
self.score = score
HN_URL_TOP_STORIES = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty"
async def fetch_story(session, id):
async with session.get(f"https://hacker-news.firebaseio.com/v0/item/{id}.json?print=pretty") as response:
return await response.json()
async def fetch_hn() -> List[Story]:
async with aiohttp.ClientSession() as session:
async with session.get(HN_URL_TOP_STORIES) as response:
story_ids = await response.json()
tasks = []
for id in story_ids[:30]:
tasks.append(fetch_story(session, id))
stories = await asyncio.gather(*tasks)
stories_out = []
for story in stories:
story_dict = {k: story.get(k, None) for k in ('title', 'url', 'score')}
stories_out.append(Story(**story_dict))
return stories_out
class ChidoriWorker:
def __init__(self):
self.c = Chidori("0", "http://localhost:9800")
async def build_graph(self):
g = GraphBuilder()
h = await g.custom_node(
name="FetchTopHN",
node_type_name="FetchTopHN",
output="{ output: String }"
)
h_interpret = await g.prompt_node(
name="InterpretTheGroup",
template="""
Based on the following list of HackerNews threads,
filter this list to only launches of new AI projects: {{FetchTopHN.output}}
"""
)
await h_interpret.run_when(g, h)
h_format_and_rank = await g.prompt_node(
name="FormatAndRank",
template="""
Format this list of new AI projects in markdown, ranking the most
interesting projects from most interesting to least.
{{InterpretTheGroup.promptResult}}
"""
)
await h_format_and_rank.run_when(g, h_interpret)
await g.commit(self.c, 0)
async def run(self):
await self.build_graph()
await self.c.play(0, 0)
await self.c.run_custom_node_loop()
async def handle_fetch_hn(node_will_exec):
stories = await fetch_hn()
result = {"output": json.dumps([story.__dict__ for story in stories])}
return result
async def main():
w = ChidoriWorker()
await w.c.start_server(":memory:")
await w.c.register_custom_node_handle("FetchTopHN", handle_fetch_hn)
await w.run()
if __name__ == "__main__":
asyncio.run(main())