diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..cbb0d520fd356fe1c07654796e8c9dda34785d09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +#Ignore env containing secrets +.env +#Ignore Virtual Env +env/ +#Ignore generated outputs +outputs/ +#Ignore pycache +**/__pycache__/ + +test*.py +./test/ +./flagged/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..10bce1b598383a95588346b8457995b2773345a4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ze Jin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 5515048e7177a717adcfb0d017e74fdc1285e35a..78493e24c1b404edd78827750ff17c0c85b58e51 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,74 @@ --- -title: AI Research Assistant -emoji: ⚡ -colorFrom: blue -colorTo: green -sdk: gradio -sdk_version: 3.39.0 +title: AI-Research-Assistant app_file: app.py -pinned: false +sdk: gradio +sdk_version: 3.38.0 +--- +
+ +
+ English | + 中文 +
+
+ +Inspired by [gpt-researcher](https://github.com/assafelovic/gpt-researcher). This project endeavors to develop an AI research assistant capable of **generating research reports** effortlessly for researchers. For instance, researchers can request the AI research assistant to compose a report on *the latest advancements in the field of superconductors as of 2023*, which is currently a trending topic. The AI research assistant will subsequently compile a report based on the relevant information obtained from the internet. Now, AIRA also offers support for **academic English polishing**. + + +| Image1 | Image2 | +| :----: | :----: | +| | | + +The currently supported agents encompass a wide range of fields, including *finance, business analysis, clinical medicine, basic medicine, travel, academic research and sociology*. + +In addition to official api, this project offers an alternative approach to generating research reports by utilizing a third-party API. For access to this third-party API, please refer to [chimeragpt](https://chimeragpt.adventblocks.cc/) or [GPT-API-free](https://github.com/chatanywhere/GPT_API_free). Before running the project, kindly ensure that you set the environment variables `OPENAI_API_KEY` and `OPENAI_API_BASE`. + +```shell +$ export OPENAI_API_KEY = your_api_key +$ export OPENAI_API_BASE = your_api_base +``` + +or you can set the api key and base in `.env` file. + + +## Installation + +1. Clone the repository + + ```shell + $ git clone git@github.com:paradoxtown/ai_research_assistant.git + $ cd ai_research_assistant + ``` + +2. Install the dependencies + + ```shell + $ pip install -r requirements.txt + ``` + +3. Export evnironment variables + + ```shell + $ export OPENAI_API_KEY = your_api_key + $ export OPENAI_API_BASE = your_api_base + ``` + or modify the `.env` file. + +4. Run the project + + ```shell + $ python app.py + ``` + +## TODO + +- [x] Switch Google Search to DuckDuckGo +- [ ] Literature review +- [x] Third-party API +- [ ] Prettify report +- [x] Add medical agent and social agent +- [ ] Add option for users to customize the number of words and temperature + --- -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference +
Happy researching! 🚀
\ No newline at end of file diff --git a/__pycache__/aira.cpython-311.pyc b/__pycache__/aira.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8dfeb3420566bb1b85073745e2fddbc552df775f Binary files /dev/null and b/__pycache__/aira.cpython-311.pyc differ diff --git a/__pycache__/aira.cpython-39.pyc b/__pycache__/aira.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5857f99c4a3ca1af55e086b7c33ec5b1f33ff339 Binary files /dev/null and b/__pycache__/aira.cpython-39.pyc differ diff --git a/__pycache__/app.cpython-311.pyc b/__pycache__/app.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..991495f5c26b944b72fa28d3266bcf3ff0d026fb Binary files /dev/null and b/__pycache__/app.cpython-311.pyc differ diff --git a/__pycache__/app.cpython-39.pyc b/__pycache__/app.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d4af20f00b7764c374cd7d0e5d6c77f874b156a Binary files /dev/null and b/__pycache__/app.cpython-39.pyc differ diff --git a/__pycache__/components.cpython-311.pyc b/__pycache__/components.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2140931b916fd14652ab6f995345b3680b95678f Binary files /dev/null and b/__pycache__/components.cpython-311.pyc differ diff --git a/__pycache__/home.cpython-311.pyc b/__pycache__/home.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c542dc6c1d5a9e41f75ecb75c8a39b9bc2fac10 Binary files /dev/null and b/__pycache__/home.cpython-311.pyc differ diff --git a/__pycache__/main.cpython-311.pyc b/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e934e595dce91d6e099663c6db4e9718eece240 Binary files /dev/null and b/__pycache__/main.cpython-311.pyc differ diff --git a/__pycache__/main.cpython-39.pyc b/__pycache__/main.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17174c0576b116123047ab963e18dfd65676f0ca Binary files /dev/null and b/__pycache__/main.cpython-39.pyc differ diff --git a/__pycache__/style.cpython-311.pyc b/__pycache__/style.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04c61a745b9d0d991511b1c61917ad08e732596f Binary files /dev/null and b/__pycache__/style.cpython-311.pyc differ diff --git a/__pycache__/test.cpython-311.pyc b/__pycache__/test.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b73da4c44ffcee4ca069aab4ab3e0cd492de4103 Binary files /dev/null and b/__pycache__/test.cpython-311.pyc differ diff --git a/__pycache__/test2.cpython-311.pyc b/__pycache__/test2.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c561ecfe51696a213bdcddb698f14b798c1403ea Binary files /dev/null and b/__pycache__/test2.cpython-311.pyc differ diff --git a/__pycache__/test3.cpython-311.pyc b/__pycache__/test3.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec44db7bc64e51fd3481571aa3858597ae2d3493 Binary files /dev/null and b/__pycache__/test3.cpython-311.pyc differ diff --git a/actions/__pycache__/duck_search.cpython-311.pyc b/actions/__pycache__/duck_search.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d1fd69e8b8fd9eae47cb25977b13198fdae0079 Binary files /dev/null and b/actions/__pycache__/duck_search.cpython-311.pyc differ diff --git a/actions/__pycache__/google_search.cpython-311.pyc b/actions/__pycache__/google_search.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..191e723601337cc78a6786a1396dad3d6826045c Binary files /dev/null and b/actions/__pycache__/google_search.cpython-311.pyc differ diff --git a/actions/__pycache__/web_scrape.cpython-311.pyc b/actions/__pycache__/web_scrape.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..abd45c694d68a910754ca5a5502d0d0b22134b36 Binary files /dev/null and b/actions/__pycache__/web_scrape.cpython-311.pyc differ diff --git a/actions/__pycache__/web_scrape.cpython-39.pyc b/actions/__pycache__/web_scrape.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6146659a15f4fde0ebb2bb10144bd022dccc8d05 Binary files /dev/null and b/actions/__pycache__/web_scrape.cpython-39.pyc differ diff --git a/actions/__pycache__/web_search.cpython-311.pyc b/actions/__pycache__/web_search.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d18bcade699ffaae51a79177cee60d3f1258687 Binary files /dev/null and b/actions/__pycache__/web_search.cpython-311.pyc differ diff --git a/actions/__pycache__/web_search.cpython-39.pyc b/actions/__pycache__/web_search.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5035276602742b421ce68a1bc179b7d782f373fc Binary files /dev/null and b/actions/__pycache__/web_search.cpython-39.pyc differ diff --git a/actions/duck_search.py b/actions/duck_search.py new file mode 100644 index 0000000000000000000000000000000000000000..2e8b7aaba3349a1b23413d7b73c8d6a752327592 --- /dev/null +++ b/actions/duck_search.py @@ -0,0 +1,11 @@ +from duckduckgo_search import DDGS + + +def duckduckgo_search(query, max_search_result=3): + with DDGS() as ddgs: + responses = list() + for i, r in enumerate(ddgs.text(query, region='wt-wt', safesearch='Off', timelimit='y')): + if i == max_search_result: + break + responses.append(r) + return responses \ No newline at end of file diff --git a/actions/google_search.py b/actions/google_search.py new file mode 100644 index 0000000000000000000000000000000000000000..1943a37ff3d2a9ba5c8fab7be99e2898f34c3d49 --- /dev/null +++ b/actions/google_search.py @@ -0,0 +1,63 @@ +import requests +from bs4 import BeautifulSoup + + +def get_urls(query, proxies=None): + query = query + url = f"https://www.google.com/search?q={query}" + headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'} + response = requests.get(url, headers=headers, proxies=proxies) + soup = BeautifulSoup(response.content, 'html.parser') + results = [] + for g in soup.find_all('div', class_='g'): + anchors = g.find_all('a') + if anchors: + link = anchors[0]['href'] + if link.startswith('/url?q='): + link = link[7:] + if not link.startswith('http'): + continue + title = g.find('h3').text + item = {'title': title, 'link': link} + results.append(item) + + return results + +def scrape_text(url, proxies=None) -> str: + """Scrape text from a webpage + + Args: + url (str): The URL to scrape text from + + Returns: + str: The scraped text + """ + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36', + 'Content-Type': 'text/plain', + } + try: + response = requests.get(url, headers=headers, proxies=proxies, timeout=8) + if response.encoding == "ISO-8859-1": response.encoding = response.apparent_encoding + except: + return "Unable to connect to the server" + soup = BeautifulSoup(response.text, "html.parser") + for script in soup(["script", "style"]): + script.extract() + text = soup.get_text() + lines = (line.strip() for line in text.splitlines()) + chunks = (phrase.strip() for line in lines for phrase in line.split(" ")) + text = "\n".join(chunk for chunk in chunks if chunk) + return text + + +if __name__ == '__main__': + txt = "What is LSTM?" + proxies = None + urls = get_urls(txt, proxies) + max_search_result = 10 + + for url in urls[:max_search_result]: + print(url) + print(scrape_text(url['link'], proxies)) + print("\n\n") diff --git a/agent/__init__.py b/agent/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/agent/__pycache__/__init__.cpython-311.pyc b/agent/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9bf3fad6991fd9749799648103bd772f2ead98c Binary files /dev/null and b/agent/__pycache__/__init__.cpython-311.pyc differ diff --git a/agent/__pycache__/llm_utils.cpython-311.pyc b/agent/__pycache__/llm_utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab7dc5619acb35d06bd49c90f3c7f57996a8b07e Binary files /dev/null and b/agent/__pycache__/llm_utils.cpython-311.pyc differ diff --git a/agent/__pycache__/llm_utils.cpython-39.pyc b/agent/__pycache__/llm_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b98f13b47cb5cd1fec0bb5bc3eb70ed16e0df4c3 Binary files /dev/null and b/agent/__pycache__/llm_utils.cpython-39.pyc differ diff --git a/agent/__pycache__/prompts.cpython-311.pyc b/agent/__pycache__/prompts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de2a3038e9170104ed71736e7b96cf7b8a071b14 Binary files /dev/null and b/agent/__pycache__/prompts.cpython-311.pyc differ diff --git a/agent/__pycache__/prompts.cpython-39.pyc b/agent/__pycache__/prompts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6970af3ca63f554bdd017b09d839efd44e68c70 Binary files /dev/null and b/agent/__pycache__/prompts.cpython-39.pyc differ diff --git a/agent/__pycache__/research_agent.cpython-311.pyc b/agent/__pycache__/research_agent.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f1f58152babd0f00be037a3d9dec70144df0247 Binary files /dev/null and b/agent/__pycache__/research_agent.cpython-311.pyc differ diff --git a/agent/__pycache__/research_agent.cpython-39.pyc b/agent/__pycache__/research_agent.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c87ab085cca74877c63d36ede550686c8c84e7db Binary files /dev/null and b/agent/__pycache__/research_agent.cpython-39.pyc differ diff --git a/agent/__pycache__/run.cpython-311.pyc b/agent/__pycache__/run.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68ab3334c61558e3499edbe0f2c9eabf5e563d25 Binary files /dev/null and b/agent/__pycache__/run.cpython-311.pyc differ diff --git a/agent/__pycache__/run.cpython-39.pyc b/agent/__pycache__/run.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..136989cb7b504f9c915ceb028d59d0f80a27369a Binary files /dev/null and b/agent/__pycache__/run.cpython-39.pyc differ diff --git a/agent/__pycache__/toolkits.cpython-311.pyc b/agent/__pycache__/toolkits.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61b3bd35446535119d0012371645dadb33bb6494 Binary files /dev/null and b/agent/__pycache__/toolkits.cpython-311.pyc differ diff --git a/agent/llm_utils.py b/agent/llm_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0810a66ba41d76e48c4afe3d123b266f902b2e10 --- /dev/null +++ b/agent/llm_utils.py @@ -0,0 +1,39 @@ +from __future__ import annotations +from config import Config +import openai + +CFG = Config() + +openai.api_key = CFG.openai_api_key +openai.api_base = CFG.openai_api_base + +from typing import Optional + +def llm_response(model, + messages, + temperature: float = CFG.temperature, + max_tokens: Optional[int] = None): + return openai.ChatCompletion.create( + model=model, + messages=messages, + temperature=temperature, + max_tokens=max_tokens, + ).choices[0].message["content"] + + +def llm_stream_response(model, + messages, + temperature: float = CFG.temperature, + max_tokens: Optional[int] = None): + response = "" + for chunk in openai.ChatCompletion.create( + model=model, + messages=messages, + temperature=temperature, + max_tokens=max_tokens, + stream=True, + ): + content = chunk["choices"][0].get("delta", {}).get("content") + if content is not None: + response += content + yield response diff --git a/agent/prompts.py b/agent/prompts.py new file mode 100644 index 0000000000000000000000000000000000000000..607b56de35eb90de70b86d752717558c8c083faa --- /dev/null +++ b/agent/prompts.py @@ -0,0 +1,132 @@ +def generate_agent_role_prompt(agent): + """ Generates the agent role prompt. + Args: agent (str): The type of the agent. + Returns: str: The agent role prompt. + """ + prompts = { + "Finance Agent": "You are a seasoned finance analyst AI assistant. Your primary goal is to compose comprehensive, astute, impartial, and methodically arranged financial reports based on provided data and trends.", + + "Travel Agent": "You are a world-travelled AI tour guide assistant. Your main purpose is to draft engaging, insightful, unbiased, and well-structured travel reports on given locations, including history, attractions, and cultural insights.", + + "Academic Research Agent": "You are an AI academic research assistant. Your primary responsibility is to create thorough, academically rigorous, unbiased, and systematically organized reports on a given research topic, following the standards of scholarly work.", + + "Business Analyst Agent": "You are an experienced AI business analyst assistant. Your main objective is to produce comprehensive, insightful, impartial, and systematically structured business reports based on provided business data, market trends, and strategic analysis.", + "Computer Security Analyst Agent": "You are an AI specializing in computer security analysis. Your principal duty is to generate comprehensive, meticulously detailed, impartial, and systematically structured reports on computer security topics. This includes Exploits, Techniques, Threat Actors, and Advanced Persistent Threat (APT) Groups. All produced reports should adhere to the highest standards of scholarly work and provide in-depth insights into the complexities of computer security.", + + "Clinical Medicine Agent": "You are an AI specializing in clinical medicine analysis. Your primary role is to compose comprehensive, well-researched, impartial, and methodically organized reports on various aspects of clinical medicine. This includes in-depth studies on medical conditions, treatments, medical advancements, patient care, and healthcare practices. Your reports should follow the highest standards of medical research and provide critical insights into the complexities of the clinical medicine field. Whether it's analyzing medical data, conducting literature reviews, or evaluating the efficacy of medical interventions, your goal is to deliver insightful and evidence-based reports to assist medical professionals and researchers in making informed decisions.", + + "Basic Medicine Agent": "You are an AI specializing in basic medicine. Your goal is to provide comprehensive, unbiased reports on essential healthcare topics. Deliver clear insights into general health practices, common medical conditions, preventive measures, first aid procedures, and healthy lifestyle choices. Aim to be accessible to non-medical professionals and offer evidence-based recommendations for overall well-being.", + + "Social Science Research Agent": "You are an AI social science research assistant with a focus on providing comprehensive, well-researched, and unbiased reports on various topics within the social sciences. Your primary goal is to delve into the complexities of human behavior, society, and culture to produce insightful and methodically organized reports. Whether it's sociology, psychology, anthropology, economics, or any other social science discipline, you excel in critically analyzing data, academic literature, and historical trends to offer valuable insights into the subject matter. Your reports are crafted to meet the highest standards of scholarly work, adhering to objectivity and academic rigor while presenting information in a clear and engaging manner. With your expertise, you can delve into societal issues, cultural dynamics, economic trends, and other relevant areas within the realm of social sciences.", + + "Default Agent": "You are an AI critical thinker research assistant. Your sole purpose is to write well written, critically acclaimed, objective and structured reports on given text." + } + + return prompts.get(agent, "No such agent") + + +def generate_report_prompt(question, research_summary): + """ Generates the report prompt for the given question and research summary. + Args: question (str): The question to generate the report prompt for + research_summary (str): The research summary to generate the report prompt for + Returns: str: The report prompt for the given question and research summary + """ + + return f'"""{research_summary}""" Using the above information, answer the following'\ + f' question or topic: "{question}" in a detailed report --'\ + " The report should focus on the answer to the question, should be well structured, informative, detailed" \ + " in depth, with facts and numbers if available, a minimum of 2,400 words and with markdown syntax and apa format. "\ + "Write all source urls at the end of the report in apa format." + +def generate_search_queries_prompt(question): + """ Generates the search queries prompt for the given question. + Args: question (str): The question to generate the search queries prompt for + Returns: str: The search queries prompt for the given question + """ + + return f'Write 5 google search queries to search online that form an objective opinion from the following: "{question}"\n'\ + 'You must respond with a list of strings in the following json format: {"Q1": query1, "Q2": query2, "Q3": query3, "Q4": query4, "Q5": query5}' + + +def generate_resource_report_prompt(question, research_summary): + """Generates the resource report prompt for the given question and research summary. + + Args: + question (str): The question to generate the resource report prompt for. + research_summary (str): The research summary to generate the resource report prompt for. + + Returns: + str: The resource report prompt for the given question and research summary. + """ + return f'"""{research_summary}""" Based on the above information, generate a bibliography recommendation report for the following' \ + f' question or topic: "{question}". The report should provide a detailed analysis of each recommended resource,' \ + ' explaining how each source can contribute to finding answers to the research question.' \ + ' Focus on the relevance, reliability, and significance of each source.' \ + ' Ensure that the report is well-structured, informative, in-depth, and follows Markdown syntax.' \ + ' Include relevant facts, figures, and numbers whenever available.' \ + ' The report should have a minimum length of 1,200 words.' + + +def generate_outline_report_prompt(question, research_summary): + """ Generates the outline report prompt for the given question and research summary. + Args: question (str): The question to generate the outline report prompt for + research_summary (str): The research summary to generate the outline report prompt for + Returns: str: The outline report prompt for the given question and research summary + """ + + return f'"""{research_summary}""" Using the above information, generate an outline for a research report in Markdown syntax'\ + f' for the following question or topic: "{question}". The outline should provide a well-structured framework'\ + ' for the research report, including the main sections, subsections, and key points to be covered.' \ + ' The research report should be detailed, informative, in-depth, and a minimum of 1,200 words.' \ + ' Use appropriate Markdown syntax to format the outline and ensure readability.' + +def generate_concepts_prompt(question, research_summary): + """ Generates the concepts prompt for the given question. + Args: question (str): The question to generate the concepts prompt for + research_summary (str): The research summary to generate the concepts prompt for + Returns: str: The concepts prompt for the given question + """ + + return f'"""{research_summary}""" Using the above information, generate a list of 5 main concepts to learn for a research report'\ + f' on the following question or topic: "{question}". The outline should provide a well-structured framework'\ + 'You must respond with a list of strings in the following format: ["concepts 1", "concepts 2", "concepts 3", "concepts 4, concepts 5"]' + + +def generate_lesson_prompt(concept): + """ + Generates the lesson prompt for the given question. + Args: + concept (str): The concept to generate the lesson prompt for. + Returns: + str: The lesson prompt for the given concept. + """ + + prompt = f'generate a comprehensive lesson about {concept} in Markdown syntax. This should include the definition'\ + f'of {concept}, its historical background and development, its applications or uses in different'\ + f'fields, and notable events or facts related to {concept}.' + + return prompt + +def get_report_by_type(report_type): + report_type_mapping = { + 'Research Report': generate_report_prompt, + 'Resource Report': generate_resource_report_prompt, + 'Outline Report': generate_outline_report_prompt + } + return report_type_mapping[report_type] + +def generate_english_polishing_prompt(content): + """ Generates the english polishing prompt for the given content. + Inspired by project gpt_academic + Args: question (str): + Returns: str: The english polishing prompt for the given content + """ + return f'Below is a paragraph from an academic paper. Polish the writing to meet the academic style and improve the spelling, grammar, clarity, concision, and overall readability. When necessary, rewrite the whole sentence. Furthermore, list all modifications and explain the reasons for doing so in the markdown table. \n {content}' + +def generate_summarize_prompt(content): + """ Generates the summarize prompt for the given content. + Inspired by project gpt_academic + Args: question (str): + Returns: str: The summarize prompt for the given content + """ + return f'The following information is crawled from the Internet and will be used in writing the research report. Please clear the junk information and summarize the useful information in depth. Include all factual information, numbers, stats etc if available. \n {content}' \ No newline at end of file diff --git a/agent/research_agent.py b/agent/research_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..3bfc4c8e5c1468455dfeb834ada5b4dbf728944d --- /dev/null +++ b/agent/research_agent.py @@ -0,0 +1,109 @@ +import json +from actions.duck_search import duckduckgo_search +from processing.text import read_txt_files +from agent.llm_utils import llm_response, llm_stream_response +from config import Config +from agent import prompts +import os +import string + +CFG = Config() + + +class ResearchAgent: + def __init__(self, question, agent): + """ Initializes the research assistant with the given question. + Args: question (str): The question to research + Returns: None + """ + + self.question = question + self.agent = agent + self.visited_urls = set() + self.search_summary = "" + self.directory_name = ''.join(c for c in question if c.isascii() and c not in string.punctuation)[:100] + self.dir_path = os.path.dirname(f"./outputs/{self.directory_name}/") + + def call_agent(self, action): + messages = [{ + "role": "system", + "content": prompts.generate_agent_role_prompt(self.agent), + }, { + "role": "user", + "content": action, + }] + return llm_response( + model=CFG.fast_llm_model, + messages=messages, + ) + + def call_agent_stream(self, action): + messages = [{ + "role": "system", + "content": prompts.generate_agent_role_prompt(self.agent), + }, { + "role": "user", + "content": action, + }] + yield from llm_stream_response( + model=CFG.fast_llm_model, + messages=messages + ) + + def create_search_queries(self): + """ Creates the search queries for the given question. + Args: None + Returns: list[str]: The search queries for the given question + """ + result = self.call_agent(prompts.generate_search_queries_prompt(self.question)) + return json.loads(result) + + def search_single_query(self, query): + """ Runs the async search for the given query. + Args: query (str): The query to run the async search for + Returns: list[str]: The async search for the given query + """ + return duckduckgo_search(query, max_search_result=3) + + def run_search_summary(self, query): + """ Runs the search summary for the given query. + Args: query (str): The query to run the search summary for + Returns: str: The search summary for the given query + """ + responses = self.search_single_query(query) + + print(f"Searching for {query}") + query = hash(query) + file_path = f"./outputs/{self.directory_name}/research-{query}.txt" + os.makedirs(os.path.dirname(file_path), exist_ok=True) + with open(file_path, "w") as f: + json.dump(responses, f) + print(f"Saved {query} to {file_path}") + return responses + + def search_online(self): + """ Conducts the search for the given question. + Args: None + Returns: str: The search results for the given question + """ + + self.search_summary = read_txt_files(self.dir_path) if os.path.isdir(self.dir_path) else "" + + if not self.search_summary: + search_queries = self.create_search_queries() + for _, query in search_queries.items(): + search_result = self.run_search_summary(query) + self.search_summary += f"=Query=:\n{query}\n=Search Result=:\n{search_result}\n================\n" + + return self.search_summary + + def write_report(self, report_type): + """ Writes the report for the given question. + Args: None + Returns: str: The report for the given question + """ + yield "Searching online..." + + report_type_func = prompts.get_report_by_type(report_type) + + yield from self.call_agent_stream(report_type_func(self.question, self.search_online())) diff --git a/agent/toolkits.py b/agent/toolkits.py new file mode 100644 index 0000000000000000000000000000000000000000..29e7ee8ad5d83e2b5a6ca1aba9c689eb8f319641 --- /dev/null +++ b/agent/toolkits.py @@ -0,0 +1,15 @@ +from agent import prompts, llm_utils +from config import Config + +CFG = Config() + +def english_polishing(content): + prompt = prompts.generate_english_polishing_prompt(content) + messages = [{ + "role": "user", + "content": prompt, + }] + + yield from llm_utils.llm_stream_response( + model=CFG.fast_llm_model, + messages=messages) diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..8ca73e651d9eb7a700f93fe8e4b5965d61159605 --- /dev/null +++ b/app.py @@ -0,0 +1,81 @@ +import gradio as gr + +from config import check_openai_api_key +from agent.research_agent import ResearchAgent +from agent.toolkits import english_polishing +from statics.style import * + +theme = gr.themes.Soft( + primary_hue=gr.themes.Color(c100="#e0e7ff", c200="#c7d2fe", c300="#a5b4fc", c400="#818cf8", c50="#eef2ff", c500="#6366f1", c600="#5e5aaa", c700="#4338ca", c800="#3730a3", c900="#312e81", c950="#2b2c5e"), + font_mono=[gr.themes.GoogleFont('Fira Code'), 'ui-monospace', 'Consolas', 'monospace'] +) + +check_openai_api_key() + +def run_agent(task, agent, report_type): + assistant = ResearchAgent(task, agent) + yield from assistant.write_report(report_type) + +with gr.Blocks(theme=gr.themes.Base(), + title="AI Research Assistant", + css=css) as demo: + gr.HTML(top_bar) + with gr.Tab(label="Report"): + with gr.Column(): + gr.HTML(research_report_html) + research_report = gr.Markdown(value="  **Research report will appear here...**", + elem_classes="output") + with gr.Row(): + agent_type = gr.Dropdown(label="# Agent Type", + value="Default Agent", + interactive=True, + allow_custom_value=False, + choices=["Default Agent", + "Business Analyst Agent", + "Finance Agent", + "Travel Agent", + "Academic Research Agent", + "Computer Security Analyst Agent", + "Clinical Medicine Agent", + "Basic Medicine Agent", + "Social Science Research Agent"]) + report_type = gr.Dropdown(label="# Report Type", + value="Research Report", + interactive=True, + allow_custom_value=False, + choices=["Research Report", + "Resource Report", + "Outline Report"]) + input_box = gr.Textbox(label="# What would you like to research next?", placeholder="Enter your question here") + submit_btn = gr.Button("Generate Report") + submit_btn.click(run_agent, inputs=[input_box, agent_type, report_type], + outputs=research_report) + gr.Examples(["Should I invest in the Large Language Model industry in 2023?", + "Is it advisable to make investments in the electric car industry during the year 2023?", + "What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023?", + "What are the most recent advancements in the domain of superconductors as of 2023?"], + inputs=input_box) + + with gr.Tab("English Polishing"): + gr.HTML(english_polishing_html) + polished_result = gr.Markdown("  **Polished result will appear here...**", elem_classes="output") + sentences = gr.Textbox(label="# What would you like to polish?", placeholder="Enter your sentence here") + + with gr.Row(): + polish_btn = gr.Button("Polish") + save_btn = gr.Button("Save") + + polish_btn.click(english_polishing, inputs=[sentences], outputs=polished_result) + + def save_result(history, origin, result): + history += f"\n**Origin** : {origin}\n\n**Polished Result** : {result}" + return history + + gr.HTML(history_result_html) + history_result = gr.Markdown("  **History result will appear here...**") + save_btn.click(save_result, inputs=[history_result, sentences, polished_result], outputs=history_result) + + with gr.Tab("Literature Review"): + pass + +demo.queue().launch() \ No newline at end of file diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..704ba0f8fd18eac290da02e5b1d22d4be54b235f --- /dev/null +++ b/config/__init__.py @@ -0,0 +1,9 @@ +from config.config import Config, check_openai_api_key +from config.singleton import AbstractSingleton, Singleton + +__all__ = [ + "check_openai_api_key", + "AbstractSingleton", + "Config", + "Singleton", +] diff --git a/config/__pycache__/__init__.cpython-311.pyc b/config/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..165bd58174e76663b605c5ee5f8d229e24bb8273 Binary files /dev/null and b/config/__pycache__/__init__.cpython-311.pyc differ diff --git a/config/__pycache__/__init__.cpython-39.pyc b/config/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0ca3cf70d859246d918c1055084039a03772852 Binary files /dev/null and b/config/__pycache__/__init__.cpython-39.pyc differ diff --git a/config/__pycache__/config.cpython-311.pyc b/config/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adfce64030d3315a253b67f0a21334383ba2c5ee Binary files /dev/null and b/config/__pycache__/config.cpython-311.pyc differ diff --git a/config/__pycache__/config.cpython-39.pyc b/config/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0db29a71f9cd1ca796514dcd13bbaa5ddbf4b26e Binary files /dev/null and b/config/__pycache__/config.cpython-39.pyc differ diff --git a/config/__pycache__/singleton.cpython-311.pyc b/config/__pycache__/singleton.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..562f78dad1cf29f462cf745c966d908b8c08f1bb Binary files /dev/null and b/config/__pycache__/singleton.cpython-311.pyc differ diff --git a/config/__pycache__/singleton.cpython-39.pyc b/config/__pycache__/singleton.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4ee71f050a9ff565e0fb759f32f3569de319664 Binary files /dev/null and b/config/__pycache__/singleton.cpython-39.pyc differ diff --git a/config/config.py b/config/config.py new file mode 100644 index 0000000000000000000000000000000000000000..97f1d2190585b966e70d5280d968330cd5aec932 --- /dev/null +++ b/config/config.py @@ -0,0 +1,82 @@ +"""Configuration class to store the state of bools for different scripts access.""" +import os + +import openai +from colorama import Fore +from dotenv import load_dotenv + +from config.singleton import Singleton + +load_dotenv(verbose=True) + + +class Config(metaclass=Singleton): + """ + Configuration class to store the state of bools for different scripts access. + """ + + def __init__(self) -> None: + """Initialize the Config class""" + self.debug_mode = False + self.allow_downloads = False + + self.selenium_web_browser = os.getenv("USE_WEB_BROWSER", "chrome") + self.fast_llm_model = os.getenv("FAST_LLM_MODEL", "gpt-3.5-turbo") + self.smart_llm_model = os.getenv("SMART_LLM_MODEL", "gpt-4") + self.fast_token_limit = int(os.getenv("FAST_TOKEN_LIMIT", 8000)) + self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000)) + self.browse_chunk_max_length = int(os.getenv("BROWSE_CHUNK_MAX_LENGTH", 8192)) + + self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.openai_api_base = os.getenv("OPENAI_API_BASE", openai.api_base) + self.temperature = float(os.getenv("TEMPERATURE", "1")) + + self.user_agent = os.getenv( + "USER_AGENT", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36" + " (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", + ) + + self.memory_backend = os.getenv("MEMORY_BACKEND", "local") + # Initialize the OpenAI API client + openai.api_key = self.openai_api_key + + def set_fast_llm_model(self, value: str) -> None: + """Set the fast LLM model value.""" + self.fast_llm_model = value + + def set_smart_llm_model(self, value: str) -> None: + """Set the smart LLM model value.""" + self.smart_llm_model = value + + def set_fast_token_limit(self, value: int) -> None: + """Set the fast token limit value.""" + self.fast_token_limit = value + + def set_smart_token_limit(self, value: int) -> None: + """Set the smart token limit value.""" + self.smart_token_limit = value + + def set_browse_chunk_max_length(self, value: int) -> None: + """Set the browse_website command chunk max length value.""" + self.browse_chunk_max_length = value + + def set_openai_api_key(self, value: str) -> None: + """Set the OpenAI API key value.""" + self.openai_api_key = value + + def set_debug_mode(self, value: bool) -> None: + """Set the debug mode value.""" + self.debug_mode = value + + +def check_openai_api_key() -> None: + """Check if the OpenAI API key is set in config.py or as an environment variable.""" + cfg = Config() + if not cfg.openai_api_key: + print( + Fore.RED + + "Please set your OpenAI API key in .env or as an environment variable." + ) + print("You can get your key from https://platform.openai.com/account/api-keys") + exit(1) diff --git a/config/singleton.py b/config/singleton.py new file mode 100644 index 0000000000000000000000000000000000000000..55b2aeea120bbe51ca837265fcb7fbff467e55f2 --- /dev/null +++ b/config/singleton.py @@ -0,0 +1,24 @@ +"""The singleton metaclass for ensuring only one instance of a class.""" +import abc + + +class Singleton(abc.ABCMeta, type): + """ + Singleton metaclass for ensuring only one instance of a class. + """ + + _instances = {} + + def __call__(cls, *args, **kwargs): + """Call method for the singleton metaclass.""" + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] + + +class AbstractSingleton(abc.ABC, metaclass=Singleton): + """ + Abstract singleton class for ensuring only one instance of a class. + """ + + pass diff --git a/outputs/Should I invest in the Large Language Model industry in 2023/research--2012672616352147449.txt b/outputs/Should I invest in the Large Language Model industry in 2023/research--2012672616352147449.txt new file mode 100644 index 0000000000000000000000000000000000000000..fe91b31cee0a902133c777d9f70f680fe0d70901 --- /dev/null +++ b/outputs/Should I invest in the Large Language Model industry in 2023/research--2012672616352147449.txt @@ -0,0 +1 @@ +[{"title": "Top Investing Trends For 2023 - Forbes Advisor", "href": "https://www.forbes.com/advisor/investing/top-investing-trends-2023/", "body": "With 2022 drawing to a close, the S&P 500 has clawed its way out of bear market territory but remains down 17% as of this writing. As we look ahead to 2023, here are nine investing trends that can ..."}, {"title": "Global Risks Report 2023: the biggest risks facing the world", "href": "https://www.weforum.org/agenda/2023/01/these-are-the-biggest-risks-facing-the-world-global-risks-2023/", "body": "Davos 2023. The World Economic Forum's latest Global Risks Report identifies the key risks facing the world over the next decade. In the next two years, the cost-of-living crisis is seen as the biggest risk, while over the next 10 years environmental risks dominate. The interconnectedness of global risks and crises is giving rise to the threat ..."}, {"title": "Global Risks Report 2023: We know what the risks are - here's what ...", "href": "https://www.weforum.org/agenda/2023/01/global-risks-report-2023-experts-davos2023/", "body": "The urgency of a cost of living crisis dominates 2023's Global Risks Report, which is in danger of deprioritizing other risks. Experts at the World Economic Forum give their insights into how their sectors are seeking to manage risks, build resilience and use new opportunities to shore up defences in 2023."}] \ No newline at end of file diff --git a/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--2821165325009188188.txt b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--2821165325009188188.txt new file mode 100644 index 0000000000000000000000000000000000000000..129501663dfdee57d662cb0835d6786b73d81a09 --- /dev/null +++ b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--2821165325009188188.txt @@ -0,0 +1 @@ +[{"title": "Physicists discover a new switch for superconductivity - ScienceDaily", "href": "https://www.sciencedaily.com/releases/2023/06/230622120822.htm", "body": "June 22, 2023 Source: Massachusetts Institute of Technology Summary: A study sheds surprising light on how certain superconductors undergo a 'nematic transition' -- unlocking new,..."}, {"title": "Physicists discover a new switch for superconductivity", "href": "https://news.mit.edu/2023/physicists-discover-new-switch-superconductivity-0622", "body": "June 22, 2023 Press Inquiries Caption When some ultrathin materials undergo a \"nematic transition,\" their atomic lattice structure stretches in ways that unlock superconductivity (as this conceptual image shows). MIT physicists have identified how this essential nematic switch occurs in one class of superconductors. Credits Image: iStock"}, {"title": "New Room-Temperature Superconductor Discovered by Scientists - The New ...", "href": "https://www.nytimes.com/2023/03/08/science/room-temperature-superconductor-ranga-dias.html", "body": "New Room-Temperature Superconductor Discovered by Scientists - The New York Times New Room-Temperature Superconductor Offers Tantalizing Possibilities The breakthrough could one day..."}] \ No newline at end of file diff --git a/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--5111118754196914265.txt b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--5111118754196914265.txt new file mode 100644 index 0000000000000000000000000000000000000000..ffcab6950339ab7537b85e4f7947beea9ac3f4b6 --- /dev/null +++ b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--5111118754196914265.txt @@ -0,0 +1 @@ +[{"title": "LK-99 superconductor breakthrough could mark 'new era' - New York Post", "href": "https://nypost.com/2023/08/02/lk-99-superconductor-breakthrough-could-mark-new-era/", "body": "LK-99 superconductor research breakthrough could mark 'new era for humankind'. Imagine riding a levitating train at speeds of 14,000 miles per hour \u2014 cutting the trip from New York to Los ..."}, {"title": "Superconductor Breakthrough Findings Replicated, Twice, in Preliminary ...", "href": "https://www.tomshardware.com/news/superconductor-breakthrough-replicated-twice", "body": "August 1, 2023 See more But in what's perhaps the most definite sign of a verification, Chinese researchers with the Huazhong University of Science and Technology have claimed to have successfully..."}, {"title": "Research breakthrough could be significant for quantum ... - ScienceDaily", "href": "https://www.sciencedaily.com/releases/2023/06/230628130347.htm", "body": "Summary: Scientists using one of the world's most powerful quantum microscopes have made a discovery that could have significant consequences for the future of computing. Researchers have..."}] \ No newline at end of file diff --git a/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--7173058848746146304.txt b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--7173058848746146304.txt new file mode 100644 index 0000000000000000000000000000000000000000..31804312c3ade9be4247501e54ede09691864bc9 --- /dev/null +++ b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research--7173058848746146304.txt @@ -0,0 +1 @@ +[{"title": "LK-99 superconductor breakthrough could mark 'new era' - New York Post", "href": "https://nypost.com/2023/08/02/lk-99-superconductor-breakthrough-could-mark-new-era/", "body": "Updated Imagine riding a levitating train at speeds of 14,000 miles per hour \u2014 cutting the trip from New York to Los Angeles to just 20 minutes. A team of South Korean researchers say the science..."}, {"title": "Physicists discover a new switch for superconductivity", "href": "https://news.mit.edu/2023/physicists-discover-new-switch-superconductivity-0622", "body": "Publication Date June 22, 2023 Press Inquiries Caption When some ultrathin materials undergo a \"nematic transition,\" their atomic lattice structure stretches in ways that unlock superconductivity (as this conceptual image shows). MIT physicists have identified how this essential nematic switch occurs in one class of superconductors. Credits"}, {"title": "New Room-Temperature Superconductor Discovered by Scientists - The New ...", "href": "https://www.nytimes.com/2023/03/08/science/room-temperature-superconductor-ranga-dias.html", "body": "This week's announcement is the latest attempt in that effort, but it comes from a team that faces wide skepticism because a 2020 paper that described a promising but less practical superconducting..."}] \ No newline at end of file diff --git a/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-1874061891885786097.txt b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-1874061891885786097.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b0567a0b2766ac32a223072387353a54eb93ae3 --- /dev/null +++ b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-1874061891885786097.txt @@ -0,0 +1 @@ +[{"title": "New Room-Temperature Superconductor Discovered by Scientists - The New ...", "href": "https://www.nytimes.com/2023/03/08/science/room-temperature-superconductor-ranga-dias.html", "body": "Scientists announced this week a tantalizing advance toward the dream of a material that could effortlessly convey electricity in everyday conditions. Such a breakthrough could transform almost any..."}, {"title": "Physicists discover a new switch for superconductivity", "href": "https://phys.org/news/2023-06-physicists-superconductivity.html", "body": "Editors' notes Physicists discover a new switch for superconductivity by Jennifer Chu, Massachusetts Institute of Technology Credit: CC0 Public Domain Under certain conditions\u2014usually..."}, {"title": "Physicists discover a new switch for superconductivity", "href": "https://news.mit.edu/2023/physicists-discover-new-switch-superconductivity-0622", "body": "June 22, 2023 Press Inquiries Caption When some ultrathin materials undergo a \"nematic transition,\" their atomic lattice structure stretches in ways that unlock superconductivity (as this conceptual image shows). MIT physicists have identified how this essential nematic switch occurs in one class of superconductors. Credits Image: iStock"}] \ No newline at end of file diff --git a/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-6554312988458864116.txt b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-6554312988458864116.txt new file mode 100644 index 0000000000000000000000000000000000000000..57c998327d072c312a137a961573ff2869b0b60d --- /dev/null +++ b/outputs/What are the most recent advancements in the domain of superconductors as of 2023/research-6554312988458864116.txt @@ -0,0 +1 @@ +[{"title": "Korea Superconductor Experts Seek to Test Breakthrough Claims", "href": "https://www.bloomberg.com/news/articles/2023-08-03/korea-superconductor-experts-seek-to-test-breakthrough-claims", "body": "August 3, 2023 at 4:23 AM EDT. South Korean experts created a committee to verify claims about a potential breakthrough in superconductor technology that have been driving both excitement and ..."}, {"title": "Viral New Superconductivity Claims Leave Many Scientists Skeptical ...", "href": "https://www.scientificamerican.com/article/viral-new-superconductivity-claims-leave-many-scientists-skeptical/", "body": "By Dan Garisto on July 27, 2023. Demonstration of superconductivity, special material cooled with liquid nitrogen. Credit: Forance/Alamy Stock Photo. If rumor has wings, extraordinary..."}, {"title": "What's an Ambient Superconductor and Why the Buzz About LK-99?", "href": "https://www.washingtonpost.com/business/energy/2023/08/03/room-temperature-superconductor-and-lk-99-what-to-know/ec47ab44-31ce-11ee-85dd-5c3c97d6acda_story.html", "body": "Superconductivity is having a moment. The concept of developing techniques for transporting electricity with no resistance is tantalizing because it has the potential to revolutionize the energy ..."}] \ No newline at end of file diff --git a/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--1921511018874273162.txt b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--1921511018874273162.txt new file mode 100644 index 0000000000000000000000000000000000000000..b61ad44a313d2bdaf871117691e6f19459838660 --- /dev/null +++ b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--1921511018874273162.txt @@ -0,0 +1 @@ +[{"title": "Is Bitcoin Legal? - Investopedia", "href": "https://www.investopedia.com/ask/answers/121515/bitcoin-legal-us.asp", "body": "As of June 2021, bitcoin was legal in the U.S., Japan, the U.K., and most other developed countries. In general, it is necessary to look at bitcoin laws in specific countries. In the U.S., the IRS ..."}, {"title": "Can Government Regulation Affect Bitcoin Prices? - Investopedia", "href": "https://www.investopedia.com/news/can-government-regulation-affect-bitcoin-prices/", "body": "Government regulation might be one of them. In a June note, analysts at Morgan Stanley suggested that government regulation might be a factor influencing bitcoin prices. According to them ..."}, {"title": "How legal is Bitcoin and Crypto Currencies? - CryptoCompare", "href": "https://www.cryptocompare.com/coins/guides/how-legal-is-bitcoin-and-crypto-currencies", "body": "The use, trading and mining of Bitcoins is considered legal and the Australian Taxation office has announced its intention to incorporate guidelines on capital gains tax and VAT taxes. New Zealand - The Kiwi stance to Bitcoin can be gleamed from the Governor of the Central Banks belief that digital currencies have the potential to supplant cash."}] \ No newline at end of file diff --git a/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--7815519697487258378.txt b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--7815519697487258378.txt new file mode 100644 index 0000000000000000000000000000000000000000..32ee79578862dc126e7963d1161ed11a451edc35 --- /dev/null +++ b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research--7815519697487258378.txt @@ -0,0 +1 @@ +[{"title": "Bitcoin Is In For A Wild Ride In 2023: Here Are The Predictions - Forbes", "href": "https://www.forbes.com/sites/qai/2023/01/05/bitcoin-is-in-for-a-wild-ride-in-2023-here-are-the-predictions/", "body": "Getty Images Key takeaways Bitcoin price predictions range from $250,000 all the way down to $5,000. Inflation is a key factor in Bitcoin's price in 2023. Some believe that this year could..."}, {"title": "Bitcoin (BTC) mid-year update: Market experts predict prices for 2023", "href": "https://www.cnbc.com/2023/07/18/bitcoin-btc-mid-year-update-market-experts-predict-prices-for-2023.html", "body": "After an 80% rally for bitcoin, market experts predict where it's going next in 2023. Published Mon, Jul 17 20238:04 PM EDT Updated Wed, Jul 26 20232:06 PM EDT. Ryan Browne @Ryan_Browne_. Share ..."}, {"title": "Bitcoin Prediction: Will Bitcoin Rise Even More in 2023? - U.S. News", "href": "https://money.usnews.com/investing/cryptocurrency/articles/bitcoin-prediction-will-bitcoin-rise-even-more-in-2023", "body": "As usual, with a closer look at any period of market asset volatility, some context is required. \"Yes, Bitcoin is up 41% between Jan. 1, 2023, and Feb. 28, 2023,\" says Jordan Taylor, an ..."}] \ No newline at end of file diff --git a/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-3771585635681793337.txt b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-3771585635681793337.txt new file mode 100644 index 0000000000000000000000000000000000000000..fda1955932bcfc6d3a3c58077a57ec46f49eef1f --- /dev/null +++ b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-3771585635681793337.txt @@ -0,0 +1 @@ +[{"title": "The Biggest Risks Of Investing In Bitcoin - Forbes", "href": "https://www.forbes.com/sites/forbesbusinesscouncil/2021/06/17/the-biggest-risks-of-investing-in-bitcoin/", "body": "Bitcoin isn't money. Another reason that Bitcoin is so risky is that it is a tradeable asset but it is not backed by anything. Bitcoin has value only because the people who are trading it say it ..."}, {"title": "The Top 10 Risks Of Bitcoin Investing (And How To Avoid Them) - Forbes", "href": "https://www.forbes.com/sites/forbesfinancecouncil/2018/12/05/the-top-10-risks-of-bitcoin-investing-and-how-to-avoid-them/", "body": "With a currency that is 100% technology-based, bitcoin owners are more vulnerable to cyberthreats, online fraud and a system that can be shut down. 5. Block Withholding. New bitcoins are created ..."}, {"title": "Here Are Bitcoin's 3 Biggest Risks | The Motley Fool", "href": "https://www.fool.com/investing/2022/05/11/here-are-bitcoins-3-biggest-risks/", "body": "The threat of regulation. Unsurprisingly, perhaps the single largest risk facing Bitcoin, and cryptocurrencies more generally, is the threat of tighter regulation. In 2021, China, the world's ..."}] \ No newline at end of file diff --git a/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-6414966712890420499.txt b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-6414966712890420499.txt new file mode 100644 index 0000000000000000000000000000000000000000..eee0adba5ec1f067be5abcaf50593ccd4a940db9 --- /dev/null +++ b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-6414966712890420499.txt @@ -0,0 +1 @@ +[{"title": "Key Considerations for Corporate Investment in Bitcoin - MicroStrategy", "href": "https://www.microstrategy.com/en/bitcoin/documents/key-considerations-for-corporate-investment-in-bitcoin", "body": "Download this playbook for a summary of key considerations corporations should keep in mind when investing in bitcoin.---MicroStrategy Bitcoin Initiative - Open Source Documents These documents are being provided to serve as a resource to help as you navigate a corporate bitcoin strategy."}, {"title": "Factors to Consider While Investing in Crypto - The Top Coins", "href": "https://thetopcoins.com/blog/factors-consider-while-investing-crypto", "body": "This blog can be used as a guideline better to assess the current market and potential risks and opportunities. Generally, when you are looking for the best cryptocurrencies to invest in, two main factors that should lure you in: 1) Market capitalisation: 153,000,000 (BTC's Market Cap) 2) Liquidity level: High/Good."}, {"title": "How To Invest In Bitcoin For Beginners", "href": "https://www.forbes.com/sites/qai/2023/02/14/how-to-invest-in-bitcoin-for-beginners/", "body": "getty Key takeaways As cryptocurrency's popularity grows, more and more retail investors have considered adding bitcoin to their portfolios Cryptocurrencies offer unique diversification and..."}] \ No newline at end of file diff --git a/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-7910004084663060634.txt b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-7910004084663060634.txt new file mode 100644 index 0000000000000000000000000000000000000000..c89646e73f282b868409cc86cc067e7dc2f5a708 --- /dev/null +++ b/outputs/What constitutes the optimal approach for investing in the Bitcoin industry during the year 2023/research-7910004084663060634.txt @@ -0,0 +1 @@ +[{"title": "How To Invest In Bitcoin For Beginners", "href": "https://www.forbes.com/sites/qai/2023/02/14/how-to-invest-in-bitcoin-for-beginners/", "body": "Investing in bitcoin as a beginner requires time and research to understand the asset and set up a crypto wallet If you want to learn how to invest in bitcoin for beginners, Q.ai's Crypto Kit..."}, {"title": "Exploring Bitcoin As a Retirement Investment Avenue", "href": "https://www.entrepreneur.com/finance/exploring-bitcoin-as-a-retirement-investment-avenue/456912", "body": "Market Conditions. When exploring Bitcoin as a retirement investment option, it's essential to carefully analyze the existing market landscape. Bitcoin, renowned for its substantial price ..."}, {"title": "How The Bitcoin Ecosystem Works - Forbes", "href": "https://www.forbes.com/sites/digital-assets/article/how-the-bitcoin-ecosystem-works/", "body": "The most important stakeholders in the decentralized bitcoin ecosystem include node operators, who distribute blockchain data, bitcoin miners, who confirm bitcoin transactions in exchange for..."}] \ No newline at end of file diff --git a/processing/__init__.py b/processing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/processing/__pycache__/__init__.cpython-311.pyc b/processing/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f38bba09ed46e0ff90e3bd08f28681a96d7fb26 Binary files /dev/null and b/processing/__pycache__/__init__.cpython-311.pyc differ diff --git a/processing/__pycache__/__init__.cpython-39.pyc b/processing/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7869baaaa5fd5d516a3833e9ac027b9f6ae0e43 Binary files /dev/null and b/processing/__pycache__/__init__.cpython-39.pyc differ diff --git a/processing/__pycache__/html.cpython-311.pyc b/processing/__pycache__/html.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..985cfa4f0d9f93fd9865d217660d30946b17190b Binary files /dev/null and b/processing/__pycache__/html.cpython-311.pyc differ diff --git a/processing/__pycache__/html.cpython-39.pyc b/processing/__pycache__/html.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43df0c711cbfa35be98f5aec9dcdf94638d6380b Binary files /dev/null and b/processing/__pycache__/html.cpython-39.pyc differ diff --git a/processing/__pycache__/text.cpython-311.pyc b/processing/__pycache__/text.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4a05d3e26dc1d595a531d0e4963d13f86c4a4927 Binary files /dev/null and b/processing/__pycache__/text.cpython-311.pyc differ diff --git a/processing/__pycache__/text.cpython-39.pyc b/processing/__pycache__/text.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a68d99d52f255a341574af4074a799b17cf6bf11 Binary files /dev/null and b/processing/__pycache__/text.cpython-39.pyc differ diff --git a/processing/text.py b/processing/text.py new file mode 100644 index 0000000000000000000000000000000000000000..1431f5a358471025eae12aaf6f4d23264b682dcd --- /dev/null +++ b/processing/text.py @@ -0,0 +1,18 @@ +"""Text processing functions""" +from typing import Dict, Generator + +from config import Config +import os + +CFG = Config() + + +def read_txt_files(directory): + all_text = '' + + for filename in os.listdir(directory): + if filename.endswith('.txt'): + with open(os.path.join(directory, filename), 'r') as file: + all_text += file.read() + '\n' + + return all_text diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..11cd16d7e02889809b13a8d8a1e32238297abc6e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +beautifulsoup4==4.12.2 +colorama==0.4.6 +gradio==3.38.0 +openai==0.27.8 +python-dotenv==1.0.0 +Requests==2.31.0 +duckduckgo-search==3.8.4 diff --git a/statics/README_zh.md b/statics/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..0de6dcccabb586b62bd2797a22945c5aec6f23dc --- /dev/null +++ b/statics/README_zh.md @@ -0,0 +1,50 @@ +
+ +
+ +受[gpt-researcher](https://github.com/assafelovic/gpt-researcher)启发,本项目提供了一种利用第三方API而不是官方API生成研究报告的替代方法。要访问此第三方API,请参阅[chimeragpt](https://chimeragpt.adventblocks.cc/)或者[GPT-API-free](https://github.com/chatanywhere/GPT_API_free)。一旦获得API密钥,您就可以使用它来访问chimeragpt API。因此,在运行项目之前,请确保您设置了环境变量`OPENAI_API_KEY`和`OPENAI_API_BASE`。 + +```shell +$ export OPENAI_API_KEY = your_api_key +$ export OPENAI_API_BASE = your_api_base +``` + +或者您可以在`.env`文件中设置api密钥和基础。 + +## 安装 + +1. 克隆存储库 + + ```shell + $ git clone git@github.com:paradoxtown/ai_research_assistant.git + $ cd ai_research_assistant + ``` + +2. 安装依赖项 + + ```shell + $ pip install -r requirements.txt + ``` + +3. 导出环境变量 + + ```shell + $ export OPENAI_API_KEY = your_api_key + $ export OPENAI_API_BASE = your_api_base + ``` + 或修改`.env`文件。 + +4. 运行项目 + + ```shell + $ python app.py + ``` + +## 待办事项 + +- [x] 将Google搜索切换到DuckDuckGo +- [ ] 文献综述 +- [x] 第三方API +- [ ] 优化报告 +- [x] 添加医疗代理和社交代理 +- [ ] 为用户添加自定义单词数和温度的选项 \ No newline at end of file diff --git a/statics/__pycache__/Seafoam.cpython-311.pyc b/statics/__pycache__/Seafoam.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b3792c2f1e9207e82d459c595d862163bffc3bf Binary files /dev/null and b/statics/__pycache__/Seafoam.cpython-311.pyc differ diff --git a/statics/__pycache__/style.cpython-311.pyc b/statics/__pycache__/style.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21b2ed725eb67d258576e66a727481a311d31b8a Binary files /dev/null and b/statics/__pycache__/style.cpython-311.pyc differ diff --git a/statics/example1-1.png b/statics/example1-1.png new file mode 100644 index 0000000000000000000000000000000000000000..91945f3d2c427ad61a1332e14813de5726d7cfbe Binary files /dev/null and b/statics/example1-1.png differ diff --git a/statics/example1-2.png b/statics/example1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1c5c8bb7e3b615415c92f81f2ff34b8d6696c9 Binary files /dev/null and b/statics/example1-2.png differ diff --git a/statics/style.py b/statics/style.py new file mode 100644 index 0000000000000000000000000000000000000000..9e18fe89a4bd97e5a4eb1ed53da45dd5fcd29ae2 --- /dev/null +++ b/statics/style.py @@ -0,0 +1,74 @@ +css = """ + .top-bar { + padding-bottom: 10px; + background-color: transparent; + border-bottom: #dfe4ea 1px solid; + } + + .top-bar .in-bar-title { + background-image: linear-gradient(45deg, #8B5FBF, #D6C6E1, #ffffff); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + font-family: Gelion, "Open Sans", Helvetica, "Helvetica Neue", Arial; + font-size: 2rem; + font-weight: bold; + text-align: left; + display: block; + } + + .top-bar .in-bar-subtitle { + font-family: 'Crimson Pro'; + color: #878787; + font-size: 1.4rem; + margin-top: -5px; + display: block; + } + + .main { + max-width: 800px; + align-self: center; + } + + .output { + padding: 10px; + min-height: 200px; + border: #c0c0c0 1px solid; + border-radius: 5px; + margin-bottom: 10px; + } +""" + +top_bar = """ + + + + + + + +
+
+ + AI Research Assistant + + + + + Your personal free GPT researcher +
+
+ +""" + +research_report_html = """ + # Research Report +""" + +english_polishing_html = """ + # Polished Result +""" + +history_result_html = """ + # History Result +""" \ No newline at end of file diff --git a/statics/title.svg b/statics/title.svg new file mode 100644 index 0000000000000000000000000000000000000000..a50cce80909917ee385ea7d7ba98a52d50ea4357 --- /dev/null +++ b/statics/title.svg @@ -0,0 +1,44 @@ + + +
+ + +
+
+ + AI Research Assistant + + + + + Your personal free GPT researcher +
+
+
+
+
\ No newline at end of file diff --git a/test/__pycache__/test.cpython-311.pyc b/test/__pycache__/test.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..879152a314ee1e24c3220220a3ec14e5d2c8ffd1 Binary files /dev/null and b/test/__pycache__/test.cpython-311.pyc differ diff --git a/test/__pycache__/test2.cpython-311.pyc b/test/__pycache__/test2.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd5b7b57cfa5c88e0986b45b61a2eb2fd0297a24 Binary files /dev/null and b/test/__pycache__/test2.cpython-311.pyc differ diff --git a/test/__pycache__/test3.cpython-311.pyc b/test/__pycache__/test3.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eba6ced1bb3641217e1a337f876eb125cc2eb71d Binary files /dev/null and b/test/__pycache__/test3.cpython-311.pyc differ diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000000000000000000000000000000000000..8f6a0cb9cc00b9e4dc375aada19771e2f5d691cc --- /dev/null +++ b/test/test.py @@ -0,0 +1,17 @@ +import gradio as gr +import test2 as test2 +import test3 as test3 + +theme = gr.themes.Soft( + font_mono=[gr.themes.GoogleFont('Fira Code'), 'ui-monospace', 'Consolas', 'monospace'], +).set( + embed_radius='*radius_md' +) + +with gr.Blocks(theme=theme, title="AI Research Assistant") as demo: + output = gr.Textbox(label="Output") + button = gr.Button("Start") + button.click(fn=test2.generator_, outputs=output) + +demo.queue() +demo.launch() \ No newline at end of file diff --git a/test/test2.py b/test/test2.py new file mode 100644 index 0000000000000000000000000000000000000000..81ff95ebc30ac1c8b744ebfe3bea58dce8f8ffcb --- /dev/null +++ b/test/test2.py @@ -0,0 +1,4 @@ +import test3 as test3 + +def generator_(): + yield from test3.generator() \ No newline at end of file diff --git a/test/test3.py b/test/test3.py new file mode 100644 index 0000000000000000000000000000000000000000..b19587e7b045df07ae61eaec8949524850600394 --- /dev/null +++ b/test/test3.py @@ -0,0 +1,21 @@ +import openai + +openai.api_key = "sk-DQ1nFYzAVzGMznofdi0nig7MebfA9PWrTxCHlLIZIqc4X8xu" +openai.api_base = "https://api.chatanywhere.cn/v1" + +def generator(): + messages = [{ + "role": "user", + "content": "What is the meaning of life?", + }] + response = "" + for chunk in openai.ChatCompletion.create( + model="gpt-3.5-turbo", + messages=messages, + temperature=0.9, + stream=True, + ): + content = chunk["choices"][0].get("delta", {}).get("content") + if content: + response += content + yield response \ No newline at end of file diff --git a/test/test4.py b/test/test4.py new file mode 100644 index 0000000000000000000000000000000000000000..d9f6c140d753757ba78d021bac903ee8b6726be9 --- /dev/null +++ b/test/test4.py @@ -0,0 +1,6 @@ +def test(): + yield 1 + return 2 + +a, b = test() +print(a, b) \ No newline at end of file diff --git a/test/test_duck_go.py b/test/test_duck_go.py new file mode 100644 index 0000000000000000000000000000000000000000..a873c444df05bfafd69c0c58f2e1be008785e30d --- /dev/null +++ b/test/test_duck_go.py @@ -0,0 +1,5 @@ +from duckduckgo_search import DDGS + +with DDGS() as ddgs: + for r in ddgs.answers("sun"): + print(r) \ No newline at end of file