Spaces:
Sleeping
Sleeping
| import math # For access to infinity | |
| import gradio # For building the interface | |
| import pandas # For working with tables | |
| from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline # For LLMS | |
| # Instantiate the model that we'll be calling. This is a tiny one! | |
| MODEL_ID = "HuggingFaceTB/SmolLM2-135M-Instruct" | |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) | |
| pipe = pipeline( | |
| task="text-generation", | |
| model=AutoModelForCausalLM.from_pretrained( | |
| MODEL_ID, | |
| ), | |
| tokenizer=tokenizer | |
| ) | |
| # Create a function to calculate the Drake Equation | |
| def drake_equation(R: float, fp: float, ne: float, fl: float, fi: float, fc: float, L: float) -> float: | |
| """ | |
| Calculate the Drake Equation | |
| R is the rate at which stars are born | |
| fp is the fraction of stars that host planets | |
| ne is the number of habitable planets per planetary system | |
| fl is the fraction of those planets where life occurs | |
| fi is the fraction of life that evolves intelligence | |
| fc is the fraction of intelligent life that develops communication capabilities | |
| L is the average length of time civilizations are detectable | |
| Return N - the number of civilizations in our galaxy with which communication might be possible | |
| """ | |
| N = R * fp * ne * fl * fi * fc * L | |
| return dict( | |
| results={ | |
| "N" : N, | |
| }, | |
| verdict={ | |
| "Based on your input, the number of alien civilizations that communication may be possible with is": N, | |
| } | |
| ) | |
| # This helper function applies a chat format to help the LLM understand what is going on | |
| def _format_chat(system_prompt: str, user_prompt: str) -> str: | |
| messages = [ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt}, | |
| ] | |
| template = getattr(tokenizer, "chat_template", None) | |
| return tokenizer.apply_chat_template( | |
| messages, | |
| tokenize=False, | |
| add_generation_prompt=True | |
| ) | |
| # This functoin uses the LLM to generate a response. | |
| def _llm_generate(prompt: str, max_tokens: int) -> str: | |
| out = pipe( | |
| prompt, | |
| max_new_tokens=max_tokens, | |
| do_sample=True, | |
| temperature=0.5, | |
| return_full_text=False, | |
| ) | |
| return out[0]["generated_text"] | |
| # This function generates an explanation of the results | |
| def llm_explain(results: dict, inputs: list) -> str: | |
| R, fp, ne, fl, fi, fc, L = inputs | |
| r = results["results"] | |
| v = results["verdict"] | |
| system_prompt = ( | |
| "You explain the implications of Drake Equation calculation to a smart college student." | |
| "You comment on the implication of their results and how many or few extraterrestrial civilizations are identified." | |
| "You always return CONCISE responses, only one sentence." | |
| ) | |
| user_prompt = ( | |
| f"The rate at which stars are born is {R}.\n" | |
| f"The fraction of stars that host planets is {fp}.\n" | |
| f"The number of habitable planets per planetary system is {ne}.\n " | |
| f"The fraction of those planets where life occurs is {fl}.\n" | |
| f"The fraction of life that evolves intelligence is {fi}.\n" | |
| f"The fraction of intelligent life that develops communication capabilities is {fc}.\n" | |
| f"The average length of time civilizations are detectable is {L}.\n" | |
| f"The number of civilizations in our galaxy with which communication may be possible is {r['N']}.\n" | |
| "Explain the results of this Drake Equation calculation in ONE friendly sentence for a non-expert" | |
| "" | |
| ) | |
| formatted = _format_chat(system_prompt, user_prompt) | |
| return _llm_generate(formatted, max_tokens=128) | |
| # This function ties everythign together (evaluation, LLM explanaation, output) | |
| # And will be out main entry point for teh GUI | |
| def run_once(R, fp, ne, fl, fi, fc, L): | |
| inputs = [R, fp, ne, fl, fi, fc, L] | |
| d = drake_equation( | |
| R=float(R), | |
| fp=float(fp), | |
| ne=float(ne), | |
| fl=float(fl), | |
| fi=float(fi), | |
| fc=float(fc), | |
| L=float(L), | |
| ) | |
| df = pandas.DataFrame([{ | |
| "The number of civilizations in our galaxy with which communication may be possible": round(d["results"]["N"], 3), | |
| }]) | |
| narrative = llm_explain(d, inputs).split("\n")[0] | |
| return df, narrative | |
| # Last but not least, here's the UI! | |
| with gradio.Blocks() as demo: | |
| # Let's start by adding a title and introduction | |
| gradio.Markdown( | |
| "# Run and Explain the Drake Equation" | |
| ) | |
| gradio.Markdown( | |
| "This app runs the Drake Equation calculation for estimating extraterrestrial life and returns a natural language description of the results" | |
| ) | |
| # This row contains all of the physical parameters | |
| with gradio.Row(): | |
| R = gradio.Number(value=0.0, label="Rate at which stars are born [stars per year]") | |
| fp = gradio.Number(value=0.0, label="Fraction of stars that host planets") | |
| ne = gradio.Number(value=0.0, label="Number of habitable planets per planetary system") | |
| fl = gradio.Number(value=0.0, label="Fraction of those planets where life occurs") | |
| fi = gradio.Number(value=0.0, label="Fraction of life that evolves intelligence") | |
| fc = gradio.Number(value=0.0, label="Fraction of intelligent life that develops communication capabilities") | |
| L = gradio.Number(value=0.0, label="Average length of time civilizations are detectable [years]") | |
| # Add a button to click to run the interface | |
| run_btn = gradio.Button("Compute") | |
| # These are the outputs. We use both a dataframe (for tabular info) and a markdown box | |
| # for info from teh LLM | |
| results_df = gradio.Dataframe(label="Numerical results (deterministic)", interactive=False) | |
| explain_md = gradio.Markdown(label="Explanation") | |
| # Run the calculations when the button is clicked | |
| run_btn.click(fn=run_once, inputs=[R, fp, ne, fl, fi, fc, L], outputs=[results_df, explain_md]) | |
| # Finally, add a few examples | |
| gradio.Examples( | |
| examples=[ | |
| [3.0, 0.95, 5.0, 0.01, 0.01, 0.5, 100000.0], | |
| [1.5, 0.75, 3.0, 0.0001, 0.001, 0.01, 10000.0], | |
| [4.0, 0.9, 6.5, 0.000005, 0.05, 0.2, 5000000.0], | |
| ], | |
| inputs=[R, fp, ne, fl, fi, fc, L], | |
| label="Representative cases", | |
| examples_per_page=3, | |
| cache_examples=False, | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |