import os import openai from utils.references import References from utils.gpt_interaction import GPTModel from utils.prompts import SYSTEM from langchain.tools import BaseTool from pydantic import BaseModel, Field from typing import Optional, Type MAX_TOKENS = 2048 openai.api_key = os.getenv("OPENAI_API_KEY") default_model = os.getenv("DEFAULT_MODEL") if default_model is None: default_model = "gpt-3.5-turbo-16k" llm = GPTModel(model=default_model, delay=1) paper_system_prompt = '''You are an assistant designed to propose choices of research direction. The user will input questions or some keywords of a fields. You need to generate some paper titles and main contributions. Ensure follow the following instructions: Instruction: - Your response should follow the JSON format. - Your response should have the following structure: { "your suggested paper title": { "summary": "an overview introducing what this paper will include", "contributions": { "contribution1": {"statement": "briefly describe this contribution", "reason": "reason why this contribution can make this paper outstanding"}, "contribution2": {"statement": "briefly describe this contribution", "reason": "reason why this contribution can make this paper outstanding"}, ... } } "your suggested paper title": { "summary": "an overview introducing what this paper will include", "contributions": { "contribution1": {"statement": "briefly describe this contribution", "reason": "reason why this contribution can make this paper outstanding"}, "contribution2": {"statement": "briefly describe this contribution", "reason": "reason why this contribution can make this paper outstanding"}, ... } } ... } - Please list three to five suggested title and at least three contributions for each paper. ''' contribution_system_prompt = '''You are an assistant designed to criticize the contributions of a paper. You will be provided Paper's Title, References and Contributions. Ensure follow the following instructions: Instruction: - Your response should follow the JSON format. - Your response should have the following structure: { "title": "the title provided by the user", "comment": "your thoughts on if this title clearly reflects the key ideas of this paper and explain why" "contributions": { "contribution1": {"statement": "briefly describe what the contribution is", "reason": "reason why the user claims it is a contribution", "judge": "your thought about if this is a novel contribution and explain why", "suggestion": "your suggestion on how to modify the research direction to enhance the novelty "}, "contribution2": {"statement": "briefly describe what the contribution is", "reason": "reason why the user claims it is a contribution", "judge": "your thought about if this is a novel contribution and explain why", "suggestion": "your suggestion on how to modify the research direction to enhance the novelty "}, ... } } - You need to carefully check if the claimed contribution has been made in the provided references, which makes the contribution not novel. - You also need to propose your concerns on if any of contributions could be incremental or just a mild modification on an existing work. ''' def find_research_directions(research_field): output, _ = llm(systems=paper_system_prompt, prompts=research_field, return_json=False) return output def find_references(title, contributions): max_tokens = MAX_TOKENS ref = References(title=title, description=f"{contributions}") keywords, _ = llm(systems=SYSTEM["keywords"], prompts=title, return_json=True) keywords = {keyword: 10 for keyword in keywords} ref.collect_papers(keywords) ref_prompt = ref.to_prompts(max_tokens=max_tokens) return ref_prompt def judge_novelty(title, contributions): max_tokens = MAX_TOKENS ref = References(title=title, description=f"{contributions}") keywords, _ = llm(systems=SYSTEM["keywords"], prompts=title, return_json=True) keywords = {keyword: 10 for keyword in keywords} ref.collect_papers(keywords) ref_prompt = ref.to_prompts(max_tokens=max_tokens) prompt = f"Title: {title}\n References: {ref_prompt}\n Contributions: {contributions}" output, _ = llm(systems=contribution_system_prompt, prompts=prompt, return_json=False) return output functions = [ { "name": "find_research_directions", "description": "when your student has already shown interests in a specific topic and provided a rough description of potential contributions, help your student to dive this direction deeper", "parameters": { "type": "object", "properties": { "research_description": { "type": "string", "description": "a paragraph with details in English describing " "(1) what is the main problem you are trying to solve " "(2) what is the main novelty of this idea (3) how to complete this research." } }, "required": ["research_description"], }, }, { "name": "find_references", "description": "find references for given details of a paper", "parameters": { "type": "object", "properties": { "title": { "type": "string", "description": "the title (in English) of the academic paper your student will write.", }, "contributions": {"type": "string", "description": "a general description on the contributions of this paper in English." "If there are multiple contributions, index them with numbers."}, }, "required": ["title", "contributions"], }, }, { "name": "judge_novelty", "description": "evaluate the novelty of a paper given its title and main contributions", "parameters": { "type": "object", "properties": { "title": { "type": "string", "description": "the title (in English) of the academic paper your student will write.", }, "contributions": {"type": "string", "description": "a general description on the contributions of this paper in English." "If there are multiple contributions, index them with numbers."}, }, "required": ["title", "contributions"], }, } ] TOOLS = {"find_research_directions": find_research_directions, "find_references": find_references, "judge_novelty": judge_novelty} class FindResearchDirectionsCheckInput(BaseModel): research_description: str = Field(..., description="a paragraph with details in English describing (1) what is the main problem you are trying to solve " "(2) what is the main novelty of this idea (3) how to complete this research.") class TitleDescriptionCheckInput(BaseModel): title: str = Field(..., description="the title of the academic paper your student will write in English.") contributions: str = Field(..., description="a general description on the contributions of this paper in English." "If there are multiple contributions, index them with numbers.") class FindResearchDirectionsTool(BaseTool): name = "find_research_directions" description = """Useful when your student has already shown interests in a specific topic and provided a rough description of potential contributions and you need to help your student to dive this direction deeper for your student. """ def _run(self, research_description: str): response = find_research_directions(research_description) return response def _arun(self, research_field: str): raise NotImplementedError("This tool does not support async") args_schema: Optional[Type[BaseModel]] = FindResearchDirectionsCheckInput class JudgeNoveltyTool(BaseTool): name = "judge_novelty" description = """Useful when you need to evaluate the novelty of your student's idea. """ def _run(self, title: str, contributions: str): response = judge_novelty(title, contributions) return response def _arun(self, title: str, contributions: str): raise NotImplementedError("This tool does not support async") args_schema: Optional[Type[BaseModel]] = TitleDescriptionCheckInput class FindReferencesTool(BaseTool): name = "find_references" description = """Useful when you need to find references for a paper. """ def _run(self, title: str, contributions: str): response = find_references(title, contributions) return response def _arun(self, title: str, contributions: str): raise NotImplementedError("This tool does not support async") args_schema: Optional[Type[BaseModel]] = TitleDescriptionCheckInput