├── .gitignore ├── pandora-next-usage ├── README.md ├── .env.template ├── requestshare.py └── process.py ├── README.cn.md ├── customize-langchain-LLm.py ├── README.md ├── pandora_usage.py └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .env -------------------------------------------------------------------------------- /pandora-next-usage/README.md: -------------------------------------------------------------------------------- 1 | 1.需要将.env.template改成.env并根据里面的提示填入相应的变量 2 | 2.在请求API的时候需要使用share token去请求 3 | 3.Share token需要使用access token去请求 4 | 4.请求API的时候,请求地址别忘了加上前缀 -------------------------------------------------------------------------------- /pandora-next-usage/.env.template: -------------------------------------------------------------------------------- 1 | URL="填写服务器API路径,记得加上前缀,举例http://pandora-next:8181/liuweiqing147" 2 | PANDORA_SHARE_TOKEN="这里填写share token,请求方法见requestshare.py" 3 | PANDORA_ACCESS_TOKEN="" -------------------------------------------------------------------------------- /pandora-next-usage/requestshare.py: -------------------------------------------------------------------------------- 1 | import requests, os 2 | from dotenv import load_dotenv 3 | 4 | load_dotenv() # 加载 .env 文件 5 | token = os.environ.get("PANDORA_ACCESS_TOKEN") 6 | 7 | url = "https://ai.fakeopen.com/token/register" 8 | 9 | payload = f"unique_name=fakeopen&access_token={token}&expires_in=0&show_conversations=true&show_userinfo=true" 10 | headers = {"Content-Type": "application/x-www-form-urlencoded"} 11 | 12 | response = requests.request("POST", url, headers=headers, data=payload) 13 | 14 | print(response.text) 15 | -------------------------------------------------------------------------------- /pandora-next-usage/process.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import uuid 4 | import requests 5 | import json 6 | import time 7 | import logging 8 | 9 | from dotenv import load_dotenv 10 | 11 | 12 | # 不能删除此程序新建的对话,因为会话id在此程序运行过程中会一直保留, 13 | # 如果删除了,会话id就无法找到(新会话conversation_id应为none),造成错误 14 | class AskChatGPT: 15 | def __init__(self, url, headers): 16 | self.url = url 17 | self.headers = headers 18 | 19 | def process_data( 20 | self, 21 | prompt, 22 | stop=None, 23 | ): 24 | model = "gpt-4" # gpt-4/text-davinci-002-render-sha 25 | data = { 26 | "model": model, 27 | "messages": [ 28 | {"role": "user", "content": prompt}, 29 | ], 30 | } 31 | response = requests.post( 32 | f"{self.url}/v1/chat/completions", json=data, headers=self.headers 33 | ) 34 | if response.status_code not in range(200, 300): 35 | logging.error( 36 | f"API call failed with status {response.status_code}: {response.text}" 37 | ) 38 | return json.dumps({"error": f"API call failed: {response.text}"}) 39 | try: 40 | # response_data = self.pre_process(response.text) # 新的预处理 41 | response_data = response.text 42 | response_data = json.loads(response_data) # 尝试解析数据 43 | # print("response_data", response_data) 44 | parts = response_data["choices"][0]["message"]["content"] 45 | except json.JSONDecodeError: 46 | logging.error(f"Invalid JSON data: {response_data}") 47 | response_data = json.dumps( 48 | {"error": "Invalid data received, Jsondecodererror"} 49 | ) # 创建一个错误的 JSON 响应 50 | return response_data 51 | except TypeError: 52 | logging.error(f"Invalid JSON data: {response_data}") 53 | response_data = json.dumps({"error": "Invalid data received, type error"}) 54 | return response_data 55 | # 将 parts 中的字符串连接起来形成完整的回复 56 | response_message = "".join(parts) 57 | if stop: 58 | for stop_value in stop: 59 | stop_index = response_message.find(stop_value) 60 | if stop_index != -1: 61 | response_message = response_message[:stop_index] 62 | break 63 | return response_message 64 | 65 | 66 | if __name__ == "__main__": 67 | load_dotenv() # 加载 .env 文件 68 | token = os.environ.get("PANDORA_SHARE_TOKEN") 69 | headers = {"Content-Type": "application/json", "Authorization": "Bearer " + token} 70 | url = os.environ.get("URL") 71 | ask_chatgpt = AskChatGPT(url, headers) 72 | while True: 73 | input_data = input("请输入:") 74 | print(ask_chatgpt.process_data(input_data)) 75 | time.sleep(1) 76 | -------------------------------------------------------------------------------- /README.cn.md: -------------------------------------------------------------------------------- 1 | [English](README.md)| 简体中文 2 | 3 | # Pandora ChatGPT API Integration for Langchain(customize-longchain-LLm.py) 4 | 5 | 本项目通过整合 Pandora 项目,以 API 的形式调用 ChatGPT 网页版,并将其与 Langchain 的自定义语言模型结合使用,从而节省使用 GPT-4 API 的费用。 6 | 7 | ## 功能 8 | 9 | - 调用 ChatGPT 网页版的 API 10 | - 使用自定义。语言模型实现 ChatGPT 的功能 11 | - 可选的停止符列表支持 12 | 13 | ## 代码示例 14 | 15 | ```python 16 | from langchain.callbacks.manager import CallbackManagerForLLMRun 17 | from langchain.llms.base import LLM 18 | import uuid 19 | import requests 20 | import json 21 | from pydantic import BaseModel 22 | import os 23 | from tool import other_tools 24 | 25 | class CustomChatGPT(LLM): 26 | ... 27 | 28 | if __name__ == "__main__": 29 | llm = CustomChatGPT(base_url="your url") # 需要自己在服务器上搭建pandora程序 30 | response = llm("This is a foobar thing") 31 | ``` 32 | 33 | ## 使用方法 34 | 35 | 1. 将 Pandora 项目部署到您的服务器上。 36 | 2. 使用您的服务器 URL 替换 `your url`。 37 | 3. 实例化 `CustomChatGPT` 类。 38 | 4. 调用 `_call` 方法(也就是llm(“prompt“)),传入相关参数并获取返回的消息。 39 | 40 | ## 注意事项 41 | 42 | - 请确保您的服务器已成功部署 Pandora 项目。 43 | - 在使用 `_call` 方法时,请确保传入正确的参数,如:prompt、stop 等。 44 | 45 | # Pandora ChatGPT API Integration for Langchain - 附加内容(pandora-usage.py) 46 | 47 | 本项目除了提供整合 Pandora 的功能,还会介绍 Pandora 的基本用法。 48 | 49 | ## Pandora 基本用法 50 | 51 | 下面的代码提供了一些基本的 Pandora 用法,包括: 52 | 53 | - 列出可用模型 54 | - 以分页方式列出会话列表 55 | - 删除所有会话 56 | - 通过会话 ID 获取指定会话详情 57 | - 通过会话 ID 删除指定会话 58 | - 通过会话 ID 设置指定的会话标题 59 | - 自动生成指定新会话的标题 60 | - 让 ChatGPT 重新生成回复 61 | - 让 ChatGPT 讲之前的恢复继续下去 62 | - 向 ChatGPT 提问,等待其回复 63 | 64 | ```python 65 | import requests 66 | import json 67 | import uuid 68 | 69 | # base_url = "https://your-api-domain" # 替换为您的API域名 70 | 71 | # 列出账号可用的模型 72 | def list_models(): 73 | ... 74 | 75 | # 以分页方式列出会话列表 76 | def list_conversations(offset=1, limit=20): 77 | ... 78 | 79 | # 删除所有会话 80 | def delete_all_conversations(): 81 | ... 82 | 83 | # 通过会话ID获取指定会话详情 84 | def get_conversation(conversation_id): 85 | ... 86 | 87 | # 通过会话ID删除指定会话 88 | def delete_conversation(conversation_id): 89 | ... 90 | 91 | # 通过会话ID设置指定的会话标题 92 | def set_conversation_title(conversation_id, title): 93 | ... 94 | 95 | # 自动生成指定新会话的标题 96 | def generate_conversation_title(conversation_id, model, message_id): 97 | ... 98 | 99 | # 让ChatGPT重新生成回复 100 | def regenerate_chatgpt(prompt, model, message_id, parent_message_id, conversation_id, stream=True): 101 | ... 102 | 103 | # 让ChatGPT讲之前的恢复继续下去 104 | def continue_chatgpt(model, parent_message_id, conversation_id, stream=True): 105 | ... 106 | 107 | # 向ChatGPT提问,等待其回复 108 | def ask_chatgpt(prompt, model, message_id, parent_message_id, conversation_id=None, stream=False): 109 | ... 110 | 111 | def ask(): 112 | ... 113 | 114 | def main(): 115 | ... 116 | 117 | if __name__ == "__main__": 118 | main() 119 | ``` 120 | 121 | ## 使用方法 122 | 123 | 1. 将您的 API 域名替换 `base_url`。 124 | 2. 调用相应的函数进行相应的操作。 125 | 126 | ## 注意事项 127 | 128 | - 请确保您的 API 域名正确配置。 129 | - 在调用函数时,请确保传入正确的参数。 130 | 131 | ## 贡献者 132 | 133 | 欢迎您为本项目作出贡献!请在 GitHub 上提交 issue 或 pull request。 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /customize-langchain-LLm.py: -------------------------------------------------------------------------------- 1 | import time 2 | from typing import Any, List, Mapping, Optional 3 | from langchain.callbacks.manager import CallbackManagerForLLMRun 4 | from langchain.llms.base import LLM 5 | import uuid 6 | import requests 7 | import json 8 | from pydantic import BaseModel 9 | import os 10 | from tool import other_tools 11 | 12 | class CustomChatGPT(LLM): 13 | 14 | base_url: str 15 | session: Optional[str] 16 | parent_message_id: Optional[str] 17 | 18 | @property 19 | def _llm_type(self) -> str: 20 | return "custom_chatgpt" 21 | 22 | def _call( 23 | self, 24 | prompt: str, 25 | stop: Optional[List[str]] = None, 26 | run_manager: Optional[CallbackManagerForLLMRun] = None, 27 | conversation_id: Optional[str] = None, 28 | parent_message_id: Optional[str] = None, 29 | ) -> str: 30 | # if stop is not None: 31 | # raise ValueError("stop kwargs are not permitted.") 32 | # 将 ask_chatgpt 的逻辑放在这里 33 | model = "gpt-4"#gpt-4/text-davinci-002-render-sha 34 | message_id = str(uuid.uuid4()) 35 | if parent_message_id is None: 36 | if self.parent_message_id is not None: 37 | parent_message_id = self.parent_message_id 38 | else: 39 | parent_message_id = str(uuid.uuid4()) 40 | # parent_message_id = self.parent_message_id 41 | if conversation_id is None and self.session is not None: 42 | # 默认为保存的conversation_id,也就是上一次会话,如果用户有输入,则为用户输入的id,不改变值 43 | conversation_id = self.session 44 | data = { 45 | "prompt": prompt, 46 | "model": model, 47 | "message_id": message_id, 48 | "parent_message_id": parent_message_id, 49 | "stream": False, 50 | "conversation_id": conversation_id, 51 | } 52 | response = requests.post(f"{self.base_url}/api/conversation/talk", json=data) 53 | response_data = response.text 54 | response_data = json.loads(response_data) 55 | parts = response_data['message']['content']['parts'] 56 | # 将 parts 中的字符串连接起来形成完整的回复 57 | response_message = ''.join(parts) 58 | if stop: 59 | for stop_value in stop: 60 | stop_index = response_message.find(stop_value) 61 | if stop_index != -1: 62 | response_message = response_message[:stop_index] 63 | break 64 | if self.session is None: 65 | self.session = response_data["conversation_id"]#如果一开始传入的id为none,这里需要更新id 66 | # 更新 parent_message_id 67 | self.parent_message_id = response_data["message"]['id'] 68 | return response_message 69 | 70 | @property 71 | def _identifying_params(self) -> Mapping[str, Any]: 72 | return {"base_url": self.base_url} 73 | 74 | 75 | #仅供测试用 76 | class FakeLLM(LLM): 77 | 78 | @property 79 | def _llm_type(self) -> str: 80 | return "custom" 81 | 82 | def _call( 83 | self, 84 | prompt: str = None, 85 | stop: Optional[List[str]] = None, 86 | run_manager: Optional[CallbackManagerForLLMRun] = None, 87 | ) -> str: 88 | prompt = '''Action: avg_price 89 | Action Input: SOLUSDT 90 | 91 | Action: avg_price 92 | Action Input: BTCUSDT 93 | 94 | Action: avg_price 95 | Action Input: ETHUSDT 96 | 97 | Action: avg_price 98 | Action Input: BNBUSDT 99 | 100 | Action: avg_price 101 | Action Input: XRPUSDT''' 102 | return prompt 103 | 104 | 105 | 106 | if __name__ == "__main__": 107 | llm = CustomChatGPT(base_url="your url")#需要自己在服务器上搭建pandora程序 108 | response = llm("This is a foobar thing") 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | English | [简体中文](README.cn.md) 2 | 3 | # Pandora ChatGPT API Integration for Langchain (customize-longchain-LLm.py) 4 | 5 | This project saves the cost of using the GPT-4 API by integrating the Pandora project to call the ChatGPT web version as an API and using it in conjunction with Langchain's custom language model. 6 | 7 | ## Features 8 | 9 | - Call the ChatGPT web version's API 10 | - Use custom. language model to implement ChatGPT's functionality 11 | - Optional stop list support 12 | 13 | ## Code examples 14 | 15 | ```python 16 | from langchain.callbacks.manager import CallbackManagerForLLMRun 17 | from langchain.llms.base import LLM 18 | import uuid 19 | import requests 20 | import json 21 | from pydantic import BaseModel 22 | import os 23 | from tool import other_tools 24 | 25 | class CustomChatGPT(LLM). 26 | ... 27 | 28 | if __name__ == "__main__". 29 | llm = CustomChatGPT(base_url="your url") # need to build the pandora application on the server itself 30 | response = llm("This is a foobar thing") 31 | ``` 32 | 33 | ## How to use 34 | 35 | 1. Deploy the Pandora project to your server. 2. 36 | 2. Replace `your url` with your server URL. 3. 37 | 3. Instantiate the `CustomChatGPT` class. 4. 38 | 4. Call the `_call` method (also known as llm("prompt")), pass in the relevant parameters and get the returned message. 39 | 40 | ## Caution 41 | 42 | - Make sure your server has successfully deployed the Pandora project. 43 | - When using the `_call` method, make sure you pass in the correct parameters, such as prompt, stop, etc. 44 | 45 | # Pandora ChatGPT API Integration for Langchain - additional content (pandora-usage.py) 46 | 47 | This project not only provides integration with Pandora, but also introduces basic usage of Pandora. 48 | 49 | ## Pandora Basic Usage 50 | 51 | The following code provides some basic Pandora usage, including 52 | 53 | - List available models 54 | - List sessions in a paginated manner 55 | - Deleting all sessions 56 | - Get the details of a given session by its session ID 57 | - Deleting a specified session by session ID 58 | - Set the specified session title by session ID 59 | - Automatically generate a title for a specified new session 60 | - Have ChatGPT regenerate replies 61 | - Allow ChatGPT to continue the previous recovery 62 | - Ask ChatGPT a question and wait for a reply 63 | 64 | ```python 65 | import requests 66 | import json 67 | import uuid 68 | 69 | # base_url = "https://your-api-domain" # Replace with your API domain name 70 | 71 | # List the models available for the account 72 | def list_models(). 73 | ... 74 | 75 | # List the conversations in a paginated manner 76 | def list_conversations(offset=1, limit=20). 77 | ... 78 | 79 | # Delete all conversations 80 | def delete_all_conversations(). 81 | ... 82 | 83 | # Get the details of a given session by its session ID 84 | def get_conversation(conversation_id). 85 | ... 86 | 87 | # Delete the specified conversation by its session ID 88 | def delete_conversation(conversation_id). 89 | ... 90 | 91 | # Set the specified session title by the session ID 92 | def set_conversation_title(conversation_id, title). 93 | ... 94 | 95 | # Automatically generate the title of the specified new session 96 | def generate_conversation_title(conversation_id, model, message_id). 97 | ... 98 | 99 | # Make ChatGPT regenerate replies 100 | def regenerate_chatgpt(prompt, model, message_id, parent_message_id, conversation_id, stream=True). 101 | ... 102 | 103 | # Let ChatGPT continue with the previous recovery 104 | def continue_chatgpt(model, parent_message_id, conversation_id, stream=True). 105 | ... 106 | 107 | # Ask ChatGPT a question and wait for a reply 108 | def ask_chatgpt(prompt, model, message_id, parent_message_id, conversation_id=None, stream=False). 109 | ... 110 | 111 | def ask(). 112 | ... 113 | 114 | def main(). 115 | ... 116 | 117 | if __name__ == "__main__". 118 | main() 119 | ``` 120 | 121 | ## Usage 122 | 123 | 1. Replace `base_url` with the domain name of your API. 124 | 2. Call the corresponding function to perform the corresponding operation. 125 | 126 | ## Caution 127 | 128 | - Please make sure your API domain name is configured correctly. 129 | - When calling the function, please make sure to pass the correct parameters. 130 | 131 | ## Contributors 132 | 133 | Feel free to contribute to this project! Please submit an issue or pull request on GitHub. 134 | 135 | Translated with www.DeepL.com/Translator (free version) -------------------------------------------------------------------------------- /pandora_usage.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import uuid 4 | 5 | # base_url = "https://your-api-domain" # 替换为您的API域名 6 | 7 | # 列出账号可用的模型 8 | def list_models(): 9 | response = requests.get(f"{base_url}/api/models") 10 | return response.json() 11 | 12 | # 以分页方式列出会话列表 13 | def list_conversations(offset=1, limit=20): 14 | params = {"offset": offset, "limit": limit} 15 | response = requests.get(f"{base_url}/api/conversations", params=params) 16 | return response.json() 17 | 18 | # 删除所有会话 19 | def delete_all_conversations(): 20 | response = requests.delete(f"{base_url}/api/conversations") 21 | return response.json() 22 | 23 | # 通过会话ID获取指定会话详情 24 | def get_conversation(conversation_id): 25 | response = requests.get(f"{base_url}/api/conversation/{conversation_id}") 26 | return response.json() 27 | 28 | # 通过会话ID删除指定会话 29 | def delete_conversation(conversation_id): 30 | response = requests.delete(f"{base_url}/api/conversation/{conversation_id}") 31 | return response.json() 32 | 33 | # 通过会话ID设置指定的会话标题 34 | def set_conversation_title(conversation_id, title): 35 | data = {"title": title} 36 | response = requests.patch(f"{base_url}/api/conversation/{conversation_id}", json=data) 37 | return response.json() 38 | 39 | # 自动生成指定新会话的标题 40 | def generate_conversation_title(conversation_id, model, message_id): 41 | data = {"model": model, "message_id": message_id} 42 | response = requests.post(f"{base_url}/api/conversation/gen_title/{conversation_id}", json=data) 43 | return response.json() 44 | 45 | 46 | # 让ChatGPT重新生成回复 47 | def regenerate_chatgpt(prompt, model, message_id, parent_message_id, conversation_id, stream=True): 48 | data = { 49 | "prompt": prompt, 50 | "model": model, 51 | "message_id": message_id, 52 | "parent_message_id": parent_message_id, 53 | "conversation_id": conversation_id, 54 | "stream": stream 55 | } 56 | response = requests.post(f"{base_url}/api/conversation/regenerate", json=data) 57 | return response.json() 58 | 59 | # 让ChatGPT讲之前的恢复继续下去 60 | def continue_chatgpt(model, parent_message_id, conversation_id, stream=True): 61 | data = { 62 | "model": model, 63 | "parent_message_id": parent_message_id, 64 | "conversation_id": conversation_id, 65 | "stream": stream 66 | } 67 | response = requests.post(f"{base_url}/api/conversation/goon", json=data) 68 | return response.json() 69 | 70 | # 向ChatGPT提问,等待其回复 71 | def ask_chatgpt(prompt, model, message_id, parent_message_id, conversation_id=None, stream=False): 72 | data = { 73 | "prompt": prompt, 74 | "model": model, 75 | "message_id": message_id, 76 | "parent_message_id": parent_message_id, 77 | "stream": stream, 78 | "conversation_id": conversation_id, 79 | } 80 | if conversation_id is not None: 81 | data["conversation_id"] = conversation_id 82 | response = requests.post(f"{base_url}/api/conversation/talk", json=data) 83 | response_data = response.text 84 | response_data = json.loads(response_data) 85 | parts = response_data['message']['content']['parts'] 86 | # 将 parts 中的字符串连接起来形成完整的回复 87 | response_message = ''.join(parts) 88 | print(response_message) 89 | return response_data["conversation_id"],response_data["message"]['id'] 90 | 91 | def ask(): 92 | # 向ChatGPT提问 93 | leap_parent_message_id = False 94 | conversation_id = str(input("请输入conversation_id:")) # 需要手动设置5.2 95 | print("当前会话的id:", conversation_id) 96 | if conversation_id == "": 97 | print("创建会话") 98 | conversation_id = None 99 | parent_message_id = str(uuid.uuid4()) 100 | leap_parent_message_id = True 101 | if not leap_parent_message_id: 102 | parent_message_id = str(input("请输入parent_message_id:")) # 需要手动设置5.2 103 | while True: 104 | # 向ChatGPT提问,等待其回复 105 | model = "gpt-4" # 选择一个可用的模型Default (GPT-3.5):text-davinci-002-render-sha等 106 | prompt = str(input("请输入prompt:")) 107 | message_id = str(uuid.uuid4()) # 随机生成一个消息ID 108 | conversation_id, parent_message_id = ask_chatgpt(prompt, model, message_id, parent_message_id, conversation_id) 109 | print("当前会话的id:", parent_message_id) 110 | 111 | 112 | def main(): 113 | # 列出可用模型 114 | models = list_models() 115 | print("Available models:", models) 116 | 117 | # 以分页方式列出会话列表 118 | conversations = list_conversations(offset=1, limit=20) 119 | print("Conversations list:", conversations) 120 | 121 | # 向ChatGPT提问 122 | #ask() 123 | 124 | 125 | # # 获取会话ID,以便后续操作 126 | 127 | # # 通过会话ID获取指定会话详情 128 | # conversation_id = "a4eba9e6-4ca1-4d7b-80ef-fb96fbea74f5" 129 | # conversation = get_conversation(conversation_id) 130 | # print("Conversation details:", conversation) 131 | 132 | # 自动生成指定新会话的标题 133 | # gen_title_response = generate_conversation_title(conversation_id, model, message_id) 134 | # print("Generated title:", gen_title_response) 135 | 136 | # # 通过会话ID设置指定的会话标题 137 | # set_title_response = set_conversation_title(conversation_id, "新标题") 138 | # print("Set title response:", set_title_response) 139 | 140 | # # 让ChatGPT讲之前的恢复继续下去 141 | # parent_message_id = chatgpt_response["message_id"] 142 | # continue_response = continue_chatgpt(model, parent_message_id, conversation_id) 143 | # print("Continue response:", continue_response) 144 | 145 | # # 删除会话 146 | # conversation_id = "10daeb20-0eb4-4cc9-a2ba-05b6fdd4311b" 147 | # delete_response = delete_conversation(conversation_id) 148 | # print("Delete conversation response:", delete_response) 149 | 150 | #删除全部对话(慎用) 151 | # really_delete = str(input("是否删除全部对话?(y/n)")) 152 | # if really_delete == "y": 153 | # delete_response = delete_all_conversations() 154 | # print("Delete conversation response:", delete_response) 155 | 156 | if __name__ == "__main__": 157 | main() 158 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. --------------------------------------------------------------------------------