Merge branch 'rag' into frontier

This commit is contained in:
binary-husky 2024-09-02 15:01:12 +00:00
commit 34784c1d40
21 changed files with 1376 additions and 48 deletions

View File

@ -36,8 +36,11 @@ AVAIL_LLM_MODELS = ["gpt-4-1106-preview", "gpt-4-turbo-preview", "gpt-4-vision-p
"gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4-turbo-2024-04-09",
"gpt-3.5-turbo-1106", "gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5",
"gpt-4", "gpt-4-32k", "azure-gpt-4", "glm-4", "glm-4v", "glm-3-turbo",
"gemini-pro", "chatglm3"
"gemini-1.5-pro", "chatglm3"
]
EMBEDDING_MODEL = "text-embedding-3-small"
# --- --- --- ---
# P.S. 其他可用的模型还包括
# AVAIL_LLM_MODELS = [
@ -50,6 +53,7 @@ AVAIL_LLM_MODELS = ["gpt-4-1106-preview", "gpt-4-turbo-preview", "gpt-4-vision-p
# "claude-3-haiku-20240307","claude-3-sonnet-20240229","claude-3-opus-20240229", "claude-2.1", "claude-instant-1.2",
# "moss", "llama2", "chatglm_onnx", "internlm", "jittorllms_pangualpha", "jittorllms_llama",
# "deepseek-chat" ,"deepseek-coder",
# "gemini-1.5-flash",
# "yi-34b-chat-0205","yi-34b-chat-200k","yi-large","yi-medium","yi-spark","yi-large-turbo","yi-large-preview",
# ]
# --- --- --- ---
@ -295,7 +299,7 @@ ARXIV_CACHE_DIR = "gpt_log/arxiv_cache"
# 除了连接OpenAI之外还有哪些场合允许使用代理请尽量不要修改
WHEN_TO_USE_PROXY = ["Download_LLM", "Download_Gradio_Theme", "Connect_Grobid",
"Warmup_Modules", "Nougat_Download", "AutoGen"]
"Warmup_Modules", "Nougat_Download", "AutoGen", "Connect_OpenAI_Embedding"]
# 启用插件热加载

View File

@ -5,6 +5,7 @@ from toolbox import trimmed_format_exc
def get_crazy_functions():
from crazy_functions.读文章写摘要 import 读文章写摘要
from crazy_functions.生成函数注释 import 批量生成函数注释
from crazy_functions.Rag_Interface import Rag问答
from crazy_functions.SourceCode_Analyse import 解析项目本身
from crazy_functions.SourceCode_Analyse import 解析一个Python项目
from crazy_functions.SourceCode_Analyse import 解析一个Matlab项目
@ -50,6 +51,13 @@ def get_crazy_functions():
from crazy_functions.SourceCode_Comment import 注释Python项目
function_plugins = {
"Rag智能召回": {
"Group": "对话",
"Color": "stop",
"AsButton": False,
"Info": "将问答数据记录到向量库中,作为长期参考。",
"Function": HotReload(Rag问答),
},
"虚空终端": {
"Group": "对话|编程|学术|智能体",
"Color": "stop",

View File

@ -0,0 +1,75 @@
from toolbox import CatchException, update_ui, get_conf, get_log_folder, update_ui_lastest_msg
from crazy_functions.crazy_utils import input_clipping
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
from crazy_functions.rag_fns.llama_index_worker import LlamaIndexRagWorker
RAG_WORKER_REGISTER = {}
MAX_HISTORY_ROUND = 5
MAX_CONTEXT_TOKEN_LIMIT = 4096
REMEMBER_PREVIEW = 1000
@CatchException
def Rag问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request):
# 1. we retrieve rag worker from global context
user_name = chatbot.get_user()
if user_name in RAG_WORKER_REGISTER:
rag_worker = RAG_WORKER_REGISTER[user_name]
else:
rag_worker = RAG_WORKER_REGISTER[user_name] = LlamaIndexRagWorker(
user_name,
llm_kwargs,
checkpoint_dir=get_log_folder(user_name, plugin_name='experimental_rag'),
auto_load_checkpoint=True)
chatbot.append([txt, '正在召回知识 ...'])
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
# 2. clip history to reduce token consumption
# 2-1. reduce chat round
txt_origin = txt
if len(history) > MAX_HISTORY_ROUND * 2:
history = history[-(MAX_HISTORY_ROUND * 2):]
txt_clip, history, flags = input_clipping(txt, history, max_token_limit=MAX_CONTEXT_TOKEN_LIMIT, return_clip_flags=True)
input_is_clipped_flag = (flags["original_input_len"] != flags["clipped_input_len"])
# 2-2. if input is clipped, add input to vector store before retrieve
if input_is_clipped_flag:
yield from update_ui_lastest_msg('检测到长输入, 正在向量化 ...', chatbot, history, delay=0) # 刷新界面
# save input to vector store
rag_worker.add_text_to_vector_store(txt_origin)
yield from update_ui_lastest_msg('向量化完成 ...', chatbot, history, delay=0) # 刷新界面
if len(txt_origin) > REMEMBER_PREVIEW:
HALF = REMEMBER_PREVIEW//2
i_say_to_remember = txt[:HALF] + f" ...\n...(省略{len(txt_origin)-REMEMBER_PREVIEW}字)...\n... " + txt[-HALF:]
if (flags["original_input_len"] - flags["clipped_input_len"]) > HALF:
txt_clip = txt_clip + f" ...\n...(省略{len(txt_origin)-len(txt_clip)-HALF}字)...\n... " + txt[-HALF:]
else:
pass
i_say = txt_clip
else:
i_say_to_remember = i_say = txt_clip
else:
i_say_to_remember = i_say = txt_clip
# 3. we search vector store and build prompts
nodes = rag_worker.retrieve_from_store_with_query(i_say)
prompt = rag_worker.build_prompt(query=i_say, nodes=nodes)
# 4. it is time to query llms
if len(chatbot) != 0: chatbot.pop(-1) # pop temp chat, because we are going to add them again inside `request_gpt_model_in_new_thread_with_ui_alive`
model_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
inputs=prompt, inputs_show_user=i_say,
llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
sys_prompt=system_prompt,
retry_times_at_unknown_error=0
)
# 5. remember what has been asked / answered
yield from update_ui_lastest_msg(model_say + '</br></br>' + '对话记忆中, 请稍等 ...', chatbot, history, delay=0.5) # 刷新界面
rag_worker.remember_qa(i_say_to_remember, model_say)
history.extend([i_say, model_say])
yield from update_ui_lastest_msg(model_say, chatbot, history, delay=0) # 刷新界面

View File

@ -4,7 +4,7 @@ import threading
import os
import logging
def input_clipping(inputs, history, max_token_limit):
def input_clipping(inputs, history, max_token_limit, return_clip_flags=False):
"""
当输入文本 + 历史文本超出最大限制时采取措施丢弃一部分文本
输入
@ -20,17 +20,20 @@ def input_clipping(inputs, history, max_token_limit):
enc = model_info["gpt-3.5-turbo"]['tokenizer']
def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
mode = 'input-and-history'
# 当 输入部分的token占比 小于 全文的一半时,只裁剪历史
input_token_num = get_token_num(inputs)
original_input_len = len(inputs)
if input_token_num < max_token_limit//2:
mode = 'only-history'
max_token_limit = max_token_limit - input_token_num
everything = [inputs] if mode == 'input-and-history' else ['']
everything.extend(history)
n_token = get_token_num('\n'.join(everything))
full_token_num = n_token = get_token_num('\n'.join(everything))
everything_token = [get_token_num(e) for e in everything]
everything_token_num = sum(everything_token)
delta = max(everything_token) // 16 # 截断时的颗粒度
while n_token > max_token_limit:
@ -43,10 +46,24 @@ def input_clipping(inputs, history, max_token_limit):
if mode == 'input-and-history':
inputs = everything[0]
full_token_num = everything_token_num
else:
pass
full_token_num = everything_token_num + input_token_num
history = everything[1:]
return inputs, history
flags = {
"mode": mode,
"original_input_token_num": input_token_num,
"original_full_token_num": full_token_num,
"original_input_len": original_input_len,
"clipped_input_len": len(inputs),
}
if not return_clip_flags:
return inputs, history
else:
return inputs, history, flags
def request_gpt_model_in_new_thread_with_ui_alive(
inputs, inputs_show_user, llm_kwargs,

View File

@ -0,0 +1,122 @@
import llama_index
from llama_index.core import Document
from llama_index.core.schema import TextNode
from request_llms.embed_models.openai_embed import OpenAiEmbeddingModel
from shared_utils.connect_void_terminal import get_chat_default_kwargs
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from crazy_functions.rag_fns.vector_store_index import GptacVectorStoreIndex
from llama_index.core.ingestion import run_transformations
from llama_index.core import PromptTemplate
from llama_index.core.response_synthesizers import TreeSummarize
DEFAULT_QUERY_GENERATION_PROMPT = """\
Now, you have context information as below:
---------------------
{context_str}
---------------------
Answer the user request below (use the context information if necessary, otherwise you can ignore them):
---------------------
{query_str}
"""
QUESTION_ANSWER_RECORD = """\
{{
"type": "This is a previous conversation with the user",
"question": "{question}",
"answer": "{answer}",
}}
"""
class SaveLoad():
def does_checkpoint_exist(self, checkpoint_dir=None):
import os, glob
if checkpoint_dir is None: checkpoint_dir = self.checkpoint_dir
if not os.path.exists(checkpoint_dir): return False
if len(glob.glob(os.path.join(checkpoint_dir, "*.json"))) == 0: return False
return True
def save_to_checkpoint(self, checkpoint_dir=None):
if checkpoint_dir is None: checkpoint_dir = self.checkpoint_dir
self.vs_index.storage_context.persist(persist_dir=checkpoint_dir)
def load_from_checkpoint(self, checkpoint_dir=None):
if checkpoint_dir is None: checkpoint_dir = self.checkpoint_dir
if self.does_checkpoint_exist(checkpoint_dir=checkpoint_dir):
print('loading checkpoint from disk')
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir=checkpoint_dir)
self.vs_index = load_index_from_storage(storage_context, embed_model=self.embed_model)
return self.vs_index
else:
return self.create_new_vs()
def create_new_vs(self):
return GptacVectorStoreIndex.default_vector_store(embed_model=self.embed_model)
class LlamaIndexRagWorker(SaveLoad):
def __init__(self, user_name, llm_kwargs, auto_load_checkpoint=True, checkpoint_dir=None) -> None:
self.debug_mode = True
self.embed_model = OpenAiEmbeddingModel(llm_kwargs)
self.user_name = user_name
self.checkpoint_dir = checkpoint_dir
if auto_load_checkpoint:
self.vs_index = self.load_from_checkpoint(checkpoint_dir)
else:
self.vs_index = self.create_new_vs()
def assign_embedding_model(self):
pass
def inspect_vector_store(self):
# This function is for debugging
self.vs_index.storage_context.index_store.to_dict()
docstore = self.vs_index.storage_context.docstore.docs
vector_store_preview = "\n".join([ f"{_id} | {tn.text}" for _id, tn in docstore.items() ])
print('\n++ --------inspect_vector_store begin--------')
print(vector_store_preview)
print('oo --------inspect_vector_store end--------')
return vector_store_preview
def add_documents_to_vector_store(self, document_list):
documents = [Document(text=t) for t in document_list]
documents_nodes = run_transformations(
documents, # type: ignore
self.vs_index._transformations,
show_progress=True
)
self.vs_index.insert_nodes(documents_nodes)
if self.debug_mode: self.inspect_vector_store()
def add_text_to_vector_store(self, text):
node = TextNode(text=text)
documents_nodes = run_transformations(
[node],
self.vs_index._transformations,
show_progress=True
)
self.vs_index.insert_nodes(documents_nodes)
if self.debug_mode: self.inspect_vector_store()
def remember_qa(self, question, answer):
formatted_str = QUESTION_ANSWER_RECORD.format(question=question, answer=answer)
self.add_text_to_vector_store(formatted_str)
def retrieve_from_store_with_query(self, query):
if self.debug_mode: self.inspect_vector_store()
retriever = self.vs_index.as_retriever()
return retriever.retrieve(query)
def build_prompt(self, query, nodes):
context_str = self.generate_node_array_preview(nodes)
return DEFAULT_QUERY_GENERATION_PROMPT.format(context_str=context_str, query_str=query)
def generate_node_array_preview(self, nodes):
buf = "\n".join(([f"(No.{i+1} | score {n.score:.3f}): {n.text}" for i, n in enumerate(nodes)]))
if self.debug_mode: print(buf)
return buf

View File

@ -0,0 +1,58 @@
from llama_index.core import VectorStoreIndex
from typing import Any, List, Optional
from llama_index.core.callbacks.base import CallbackManager
from llama_index.core.schema import TransformComponent
from llama_index.core.service_context import ServiceContext
from llama_index.core.settings import (
Settings,
callback_manager_from_settings_or_context,
transformations_from_settings_or_context,
)
from llama_index.core.storage.storage_context import StorageContext
class GptacVectorStoreIndex(VectorStoreIndex):
@classmethod
def default_vector_store(
cls,
storage_context: Optional[StorageContext] = None,
show_progress: bool = False,
callback_manager: Optional[CallbackManager] = None,
transformations: Optional[List[TransformComponent]] = None,
# deprecated
service_context: Optional[ServiceContext] = None,
embed_model = None,
**kwargs: Any,
):
"""Create index from documents.
Args:
documents (Optional[Sequence[BaseDocument]]): List of documents to
build the index from.
"""
storage_context = storage_context or StorageContext.from_defaults()
docstore = storage_context.docstore
callback_manager = (
callback_manager
or callback_manager_from_settings_or_context(Settings, service_context)
)
transformations = transformations or transformations_from_settings_or_context(
Settings, service_context
)
with callback_manager.as_trace("index_construction"):
return cls(
nodes=[],
storage_context=storage_context,
callback_manager=callback_manager,
show_progress=show_progress,
transformations=transformations,
service_context=service_context,
embed_model=embed_model,
**kwargs,
)

View File

@ -291,7 +291,7 @@
"gradio的inbrowser触发不太稳定": "In-browser triggering of gradio is not very stable",
"回滚代码到原始的浏览器打开函数": "Roll back code to the original browser open function",
"打开浏览器": "Open browser",
"ChatGPT 学术优化": "ChatGPT academic optimization",
"ChatGPT 学术优化": "GPT Academic",
"代码开源和更新": "Code open source and updates",
"地址🚀": "Address 🚀",
"感谢热情的": "Thanks to the enthusiastic",
@ -3976,5 +3976,234 @@
"为了更灵活地接入vllm多模型管理界面": "To more flexibly access the vllm multi-model management interface",
"读取解析": "Read and parse",
"允许缓存": "Allow caching",
"Run2 中对 Kaon 鉴别的要求被收紧为 $ \\operatorname{ProbNNk}\\left": "The requirement for Kaon discrimination in Run2 has been tightened to $ \\operatorname{ProbNNk}\\left"
"Run2 中对 Kaon 鉴别的要求被收紧为 $ \\operatorname{ProbNNk}\\left": "The requirement for Kaon discrimination in Run2 has been tightened to $ \\operatorname{ProbNNk}\\left",
"当前使用人数太多": "Current user count is too high",
"提取historyBox信息": "Extract historyBox information",
"📚Arxiv论文精细翻译": "Fine translation of 📚Arxiv papers",
"检索中": "Searching",
"受到限制": "Restricted",
"3. 历史输入包含图像": "3. Historical input contains images",
"待通过互联网检索的问题": "Questions to be retrieved via the internet",
"使用 findall 方法查找所有匹配的 Base64 字符串": "Use findall method to find all matching Base64 strings",
"建立文件树": "Build file tree",
"经过clip": "Through clip",
"增强": "Enhance",
"对话存档": "Conversation archive",
"网页": "Webpage",
"怎么下载相关论文": "How to download related papers",
"当前对话是关于 Nginx 的介绍和使用等": "The current conversation is about the introduction and use of Nginx, etc.",
"从而提高学术论文检索的精度": "To improve the accuracy of academic paper retrieval",
"使用自然语言实现您的想法": "Implement your ideas using natural language",
"这样可以保证后续问答能读取到有效的历史记录": "This ensures that subsequent questions and answers can read valid historical records",
"生成对比html": "Generate comparison html",
"Doc2x API 页数受限": "Doc2x API page count limited",
"inputs 本次请求": "Inputs for this request",
"有其原问题": "Has its original question",
"在线搜索失败": "Online search failed",
"选择搜索引擎": "Choose a search engine",
"同步已知模型的其他信息": "Synchronize other information of known models",
"在线搜索服务": "Online search service",
"常规对话": "Regular conversation",
"使用正则表达式匹配模式": "Use regular expressions to match patterns",
"从而提高网页检索的精度": "To improve the accuracy of webpage retrieval",
"GPT-Academic输出文档": "GPT-Academic output document",
"/* 小按钮 */": "/* Small button */",
"历史记录": "History record",
"上传一系列python源文件": "Upload a series of python source files",
"仅DALLE3生效": "Only DALLE3 takes effect",
"判断给定的单个字符是否是全角字符": "Determine if the given single character is a full-width character",
"依次放入每组第一": "Put each group's first one by one",
"这部分代码会逐渐移动到common.js中": "This part of the code will gradually move to common.js",
"列出机器学习的三种应用": "List three applications of machine learning",
"更新主输入区的参数": "Update the parameters of the main input area",
"从以上搜索结果中抽取与问题": "Extract from the above search results related to the question",
"* 如果解码失败": "* If decoding fails",
"如果是已知模型": "If it is a known model",
"一": "One",
"模型切换时的回调": "Callback when switching models",
"加入历史": "Add to history",
"压缩结果": "Compress the result",
"使用 DALLE2/DALLE3 生成图片 | 输入参数字符串": "Use DALLE2/DALLE3 to generate images | Input parameter string",
"搜索分类": "Search category",
"获得空的回复": "Get an empty reply",
"多模态模型": "Multimodal model",
"移除注释": "Remove comments",
"对话背景": "Conversation background",
"获取需要执行的插件名称": "Get the name of the plugin to be executed",
"是否启动语音输入功能": "Whether to enable voice input function",
"更新高级参数输入区的参数": "Update the parameters of the advanced parameter input area",
"启用多模态能力": "Enable multimodal capabilities",
"请根据以上搜索结果回答问题": "Please answer the question based on the above search results",
"生成的问题要求指向对象清晰明确": "The generated question requires clear and specific references to the object",
"Arxiv论文翻译": "Translation of Arxiv paper",
"找不到该模型": "Model not found",
"提取匹配的数字部分并转换为整数": "Extract matching numeric parts and convert to integers",
"尝试进行搜索优化": "Try to optimize the search",
"重新梳理输入参数": "Reorganize input parameters",
"存储翻译好的arxiv论文的路径": "Path to store translated arxiv papers",
"尽量使用英文": "Use English as much as possible",
"插件二级菜单的实现": "Implementation of plugin submenus",
"* 增强优化": "Enhanced optimization",
"但属于其他用户": "But belongs to another user",
"不得有多余字符": "No extra characters allowed",
"怎么解决": "How to solve",
"根据综合回答问题": "Answer questions comprehensively",
"降低温度再试一次": "Lower the temperature and try again",
"作为一个网页搜索助手": "As a web search assistant",
"支持将文件直接粘贴到输入区": "Support pasting files directly into the input area",
"打开新对话": "Open a new conversation",
"但位置非法": "But the position is illegal",
"会自动读取输入框内容": "Will automatically read the input box content",
"移除模块的文档字符串": "Remove the module's docstrings",
"from crazy_functions.联网的ChatGPT_bing版 import 连接bing搜索回答问题": "from crazy_functions.online.ChatGPT_bing import connect_bing_search_to_answer_questions",
"关闭": "Close",
"学术论文": "Academic paper",
"多模态能力": "Multimodal capabilities",
"无渲染": "No rendering",
"弃用功能": "Deprecated feature",
"输入Searxng的地址": "Enter the address of Searxng",
"风格": "Style",
"介绍下第2点": "Introduce the second point",
"你的任务是结合历史记录": "Your task is to combine historical records",
"前端": "Frontend",
"采取措施丢弃一部分文本": "Take measures to discard some text",
"2. 输入包含图像": "2. Input contains images",
"输入问题": "Input question",
"可能原因": "Possible reasons",
"2. Java 是一种面向对象的编程语言": "Java is an object-oriented programming language",
"不支持的检索类型": "Unsupported retrieval type",
"第四步": "Step four",
"2. 机器学习在自然语言处理中的应用": "Applications of machine learning in natural language processing",
"浮动菜单定义": "Definition of floating menu",
"鿿": "Undefined",
"history 历史上下文": "History context",
"1. Java 是一种编译型语言": "Java is a compiled language",
"请根据给定的若干条搜索结果回答问题": "Answer the question based on the given search results",
"当输入文本 + 历史文本超出最大限制时": "When the input text + historical text exceeds the maximum limit",
"限DALLE3": "Limited to DALLE3",
"原问题": "Original question",
"日志文件": "Log file",
"输入图片描述": "Input image description",
"示例使用": "Example usage",
"后续参数": "Subsequent parameters",
"请用一句话对下面的程序文件做一个整体概述": "Please give a brief overview of the program file below in one sentence",
"当前对话是关于深度学习的介绍和应用等": "The current conversation is about the introduction and applications of deep learning",
"点击这里输入「关键词」搜索插件": "Click here to enter 'keywords' search plugin",
"按用户划分": "Divided by user",
"将结果写回源文件": "Write the results back to the source file",
"使用前切换到GPT系列模型": "Switch to GPT series model before using",
"正在读取下一段代码片段": "Reading the next code snippet",
"第二个搜索结果": "Second search result",
"作为一个学术论文搜索助手": "As an academic paper search assistant",
"搜索": "Search",
"无法从searxng获取信息请尝试更换搜索引擎": "Unable to retrieve information from searxng! Please try changing the search engine",
"* 清洗搜索结果": "Cleaning search results",
"或者压缩包": "Or compressed file",
"模型": "Model",
"切换布局": "Switch layout",
"生成当前浏览器窗口的uuid": "Generate the uuid of the current browser window",
"左上角工具栏定义": "Definition of the top-left toolbar",
"from crazy_functions.联网的ChatGPT import ConnectToNetworkToAnswerQuestions": "from crazy_functions.ConnectToNetworkToAnswerQuestions import ChatGPT",
"对最相关的三个搜索结果进行总结": "Summarize the top three most relevant search results",
"刷新失效": "Refresh invalid",
"将处理后的 AST 转换回源代码": "Convert the processed AST back to source code",
"/* 插件下拉菜单 */": "/* Plugin dropdown menu */",
"移除类的文档字符串": "Remove the documentation strings of a class",
"请尽量不要修改": "Please try not to modify",
"并更换新的 API 秘钥": "And replace with a new API key",
"输入文件的路径": "Input file path",
"发现异常嵌套公式": "Identify nested formula exceptions",
"修复不标准的dollar公式符号的问题": "Fix the issue of non-standard dollar formula symbols",
"Searxng互联网检索服务": "Searxng Internet search service",
"联网检索中": "In network retrieval",
"并与“原问题语言相同”": "And in the same language as the original question",
"存在": "Exists",
"列出Java的三种特点": "List three characteristics of Java",
"3. Java 是一种跨平台的编程语言": "3. Java is a cross-platform programming language",
"所有源文件均已处理完毕": "All source files have been processed",
"限DALLE2": "Limited to DALLE2",
"紫东太初大模型 https": "Zidong Taichu Large Model https",
"🎨图片生成": "🎨 Image generation",
"1. 模型本身是多模态模型": "1. The model itself is multimodal",
"相关的信息": "Related information",
"* 或者使用搜索优化器": "* Or use a search optimizer",
"搜索查询": "Search query",
"当前对话是关于 Nginx 的介绍和在Ubuntu上的使用等": "The current conversation is about the introduction of Nginx and its use on Ubuntu, etc.",
"必须以json形式给出": "Must be provided in JSON format",
"开启": "Turn on",
"1. 机器学习在图像识别中的应用": "1. The application of machine learning in image recognition",
"处理代码片段": "Processing code snippet",
"则尝试获取其信息": "Then try to get its information",
"已完成的文件": "Completed file",
"注意这可能会消耗较多token": "Note that this may consume more tokens",
"多模型对话": "Multi-model conversation",
"现在有历史记录": "Now there is a history record",
"你知道 Python 么": "Do you know Python?",
"Base64编码": "Base64 encoding",
"Gradio的inbrowser触发不太稳定": "Gradio's in-browser trigger is not very stable",
"CJK标点符号": "CJK punctuation marks",
"请联系 Doc2x 方面": "Please contact Doc2x for details",
"耗尽generator避免报错": "Exhaust the generator to avoid errors",
"📚本地Latex论文精细翻译": "📚 Local Latex paper finely translated",
"* 尝试解码优化后的搜索结果": "* Try to decode the optimized search results",
"为这些代码添加docstring | 输入参数为路径": "Add docstring for these codes | Input parameter is path",
"读取插件参数": "Read plugin parameters",
"如果剩余的行数非常少": "If the remaining lines are very few",
"输出格式为JSON": "Output format is JSON",
"提取QaBox信息": "Extract QaBox information",
"不使用多模态能力": "Not using multimodal capabilities",
"解析源代码为 AST": "Parse source code into AST",
"使用前请切换模型到GPT系列": "Switch the model to GPT series before using",
"中文字符": "Chinese characters",
"用户的上传目录": "User's upload directory",
"请将文件上传后再执行该任务": "Please upload the file before executing this task",
"移除函数的文档字符串": "Remove the function's docstring",
"新版-更流畅": "New version - smoother",
"检索词": "Search term",
"获取插件参数": "Get plugin parameters",
"获取插件执行函数": "Get plugin execution function",
"为“原问题”生成个不同版本的“检索词”": "Generate different versions of 'search terms' for the 'original question'",
"并清洗重复的搜索结果": "Clean and remove duplicate search results",
"直接返回原始问题": "Directly return the original question",
"从不同角度": "From different perspectives",
"展示已经完成的部分": "Display completed parts",
"搜索优化": "Search optimization",
"解决缩进问题": "Resolve indentation issues",
"直接给出最多{num}个检索词": "Directly provide up to {num} search terms",
"对话数据": "Conversation data",
"定义一个正则表达式来匹配 Base64 字符串": "Define a regular expression to match Base64 strings",
"转化为kwargs字典": "Convert to kwargs dictionary",
"原始数据": "Original data",
"当以下条件满足时": "When the following conditions are met",
"主题修改": "Topic modification",
"Searxng服务地址": "Searxng service address",
"3. 机器学习在推荐系统中的应用": "3. Application of machine learning in recommendation systems",
"全角符号": "Full-width symbols",
"发送到大模型进行分析": "Send for analysis to a large model",
"一个常用的测试目录": "A commonly used test directory",
"在线搜索失败!": "Online search failed!",
"搜索语言": "Search language",
"万事俱备": "All is ready",
"指定了后续参数的名称": "Specified the names of subsequent parameters",
"是否使用搜索增强": "Whether to use search enhancement",
"你知道 GAN 么": "Do you know about GAN?",
"├── 互联网检索": "├── Internet retrieval",
"公式之中出现了异常": "An anomaly occurred in the formula",
"当前对话是关于深度学习的介绍和在图像识别中的应用等": "The current conversation is about the introduction of deep learning and its applications in image recognition, etc.",
"返回反转后的 Base64 字符串列表": "Return a list of Base64 strings reversed",
"一鼓作气处理掉": "Deal with it in one go",
"剩余源文件数量": "Remaining source file count",
"查互联网后回答": "Answer after checking the internet",
"需要生成图像的文本描述": "Text description for generating images",
"* 如果再次失败": "If failed again",
"质量": "Quality",
"请配置 TAICHU_API_KEY": "Please configure TAICHU_API_KEY",
"most_recent_uploaded 是一个放置最新上传图像的路径": "most_recent_uploaded is a path to place the latest uploaded images",
"真正的参数": "Actual parameters",
"生成带注释文件": "Generate files with annotations",
"源自": "From",
"怎么下载": "How to download",
"请稍后": "Please wait",
"会尝试结合历史记录进行搜索优化": "Will try to optimize the search by combining historical records",
"max_token_limit 最大token限制": "max_token_limit maximum token limit"
}

View File

@ -106,5 +106,7 @@
"解析PDF_DOC2X_转Latex": "ParsePDF_DOC2X_toLatex",
"解析PDF_基于DOC2X": "ParsePDF_basedDOC2X",
"解析PDF_简单拆解": "ParsePDF_simpleDecomposition",
"解析PDF_DOC2X_单文件": "ParsePDF_DOC2X_singleFile"
"解析PDF_DOC2X_单文件": "ParsePDF_DOC2X_singleFile",
"注释Python项目": "CommentPythonProject",
"注释源代码": "CommentSourceCode"
}

View File

@ -118,8 +118,8 @@ def main():
choices=[
"常规对话",
"多模型对话",
"智能召回 RAG",
# "智能上下文",
# "智能召回 RAG",
], value="常规对话",
interactive=True, label='', show_label=False,
elem_classes='normal_mut_select', elem_id="gpt-submit-dropdown").style(container=False)

View File

@ -407,22 +407,46 @@ model_info = {
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
# Gemini
# Note: now gemini-pro is an alias of gemini-1.0-pro.
# Warning: gemini-pro-vision has been deprecated.
# Support for gemini-pro-vision has been removed.
"gemini-pro": {
"fn_with_ui": genai_ui,
"fn_without_ui": genai_noui,
"endpoint": gemini_endpoint,
"has_multimodal_capacity": False,
"max_token": 1024 * 32,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
"gemini-pro-vision": {
"gemini-1.0-pro": {
"fn_with_ui": genai_ui,
"fn_without_ui": genai_noui,
"endpoint": gemini_endpoint,
"has_multimodal_capacity": False,
"max_token": 1024 * 32,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
"gemini-1.5-pro": {
"fn_with_ui": genai_ui,
"fn_without_ui": genai_noui,
"endpoint": gemini_endpoint,
"has_multimodal_capacity": True,
"max_token": 1024 * 204800,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
"gemini-1.5-flash": {
"fn_with_ui": genai_ui,
"fn_without_ui": genai_noui,
"endpoint": gemini_endpoint,
"has_multimodal_capacity": True,
"max_token": 1024 * 204800,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
# cohere
"cohere-command-r-plus": {
@ -857,7 +881,7 @@ if "sparkv2" in AVAIL_LLM_MODELS: # 讯飞星火认知大模型
})
except:
print(trimmed_format_exc())
if "sparkv3" in AVAIL_LLM_MODELS or "sparkv3.5" in AVAIL_LLM_MODELS: # 讯飞星火认知大模型
if any(x in AVAIL_LLM_MODELS for x in ("sparkv3", "sparkv3.5", "sparkv4")): # 讯飞星火认知大模型
try:
from .bridge_spark import predict_no_ui_long_connection as spark_noui
from .bridge_spark import predict as spark_ui

View File

@ -8,15 +8,15 @@ import os
import time
from request_llms.com_google import GoogleChatInit
from toolbox import ChatBotWithCookies
from toolbox import get_conf, update_ui, update_ui_lastest_msg, have_any_recent_upload_image_files, trimmed_format_exc, log_chat
from toolbox import get_conf, update_ui, update_ui_lastest_msg, have_any_recent_upload_image_files, trimmed_format_exc, log_chat, encode_image
proxies, TIMEOUT_SECONDS, MAX_RETRY = get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY')
timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \
'网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。'
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None,
console_slience=False):
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="", observe_window:list=[],
console_slience:bool=False):
# 检查API_KEY
if get_conf("GEMINI_API_KEY") == "":
raise ValueError(f"请配置 GEMINI_API_KEY。")
@ -44,9 +44,20 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
raise RuntimeError(f'{gpt_replying_buffer} 对话错误')
return gpt_replying_buffer
def make_media_input(inputs, image_paths):
image_base64_array = []
for image_path in image_paths:
path = os.path.abspath(image_path)
inputs = inputs + f'<br/><br/><div align="center"><img src="file={path}"></div>'
base64 = encode_image(path)
image_base64_array.append(base64)
return inputs, image_base64_array
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
from .bridge_all import model_info
# 检查API_KEY
if get_conf("GEMINI_API_KEY") == "":
yield from update_ui_lastest_msg(f"请配置 GEMINI_API_KEY。", chatbot=chatbot, history=history, delay=0)
@ -57,18 +68,17 @@ def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWith
from core_functional import handle_core_functionality
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
if "vision" in llm_kwargs["llm_model"]:
have_recent_file, image_paths = have_any_recent_upload_image_files(chatbot)
if not have_recent_file:
chatbot.append((inputs, "没有检测到任何近期上传的图像文件请上传jpg格式的图片此外请注意拓展名需要小写"))
yield from update_ui(chatbot=chatbot, history=history, msg="等待图片") # 刷新界面
return
def make_media_input(inputs, image_paths):
for image_path in image_paths:
inputs = inputs + f'<br/><br/><div align="center"><img src="file={os.path.abspath(image_path)}"></div>'
return inputs
if have_recent_file:
inputs = make_media_input(inputs, image_paths)
# multimodal capacity
# inspired by codes in bridge_chatgpt
has_multimodal_capacity = model_info[llm_kwargs['llm_model']].get('has_multimodal_capacity', False)
if has_multimodal_capacity:
has_recent_image_upload, image_paths = have_any_recent_upload_image_files(chatbot, pop=True)
else:
has_recent_image_upload, image_paths = False, []
if has_recent_image_upload:
inputs, image_base64_array = make_media_input(inputs, image_paths)
else:
inputs, image_base64_array = inputs, []
chatbot.append((inputs, ""))
yield from update_ui(chatbot=chatbot, history=history)
@ -76,7 +86,7 @@ def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWith
retry = 0
while True:
try:
stream_response = genai.generate_chat(inputs, llm_kwargs, history, system_prompt)
stream_response = genai.generate_chat(inputs, llm_kwargs, history, system_prompt, image_base64_array, has_multimodal_capacity)
break
except Exception as e:
retry += 1
@ -112,7 +122,6 @@ def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWith
yield from update_ui(chatbot=chatbot, history=history)
if __name__ == '__main__':
import sys
llm_kwargs = {'llm_model': 'gemini-pro'}

View File

@ -7,7 +7,7 @@ import os
import re
import requests
from typing import List, Dict, Tuple
from toolbox import get_conf, encode_image, get_pictures_list, to_markdown_tabs
from toolbox import get_conf, update_ui, encode_image, get_pictures_list, to_markdown_tabs
proxies, TIMEOUT_SECONDS = get_conf("proxies", "TIMEOUT_SECONDS")
@ -112,6 +112,14 @@ def html_local_img(__file, layout="left", max_width=None, max_height=None, md=Tr
return a
def reverse_base64_from_input(inputs):
pattern = re.compile(r'<br/><br/><div align="center"><img[^<>]+base64="([^"]+)"></div>')
base64_strings = pattern.findall(inputs)
return base64_strings
def contain_base64(inputs):
base64_strings = reverse_base64_from_input(inputs)
return len(base64_strings) > 0
class GoogleChatInit:
def __init__(self, llm_kwargs):
@ -119,9 +127,9 @@ class GoogleChatInit:
endpoint = model_info[llm_kwargs['llm_model']]['endpoint']
self.url_gemini = endpoint + "/%m:streamGenerateContent?key=%k"
def generate_chat(self, inputs, llm_kwargs, history, system_prompt):
def generate_chat(self, inputs, llm_kwargs, history, system_prompt, image_base64_array:list=[], has_multimodal_capacity:bool=False):
headers, payload = self.generate_message_payload(
inputs, llm_kwargs, history, system_prompt
inputs, llm_kwargs, history, system_prompt, image_base64_array, has_multimodal_capacity
)
response = requests.post(
url=self.url_gemini,
@ -133,13 +141,16 @@ class GoogleChatInit:
)
return response.iter_lines()
def __conversation_user(self, user_input, llm_kwargs):
def __conversation_user(self, user_input, llm_kwargs, enable_multimodal_capacity):
what_i_have_asked = {"role": "user", "parts": []}
if "vision" not in self.url_gemini:
from .bridge_all import model_info
if enable_multimodal_capacity:
input_, encode_img = input_encode_handler(user_input, llm_kwargs=llm_kwargs)
else:
input_ = user_input
encode_img = []
else:
input_, encode_img = input_encode_handler(user_input, llm_kwargs=llm_kwargs)
what_i_have_asked["parts"].append({"text": input_})
if encode_img:
for data in encode_img:
@ -153,12 +164,12 @@ class GoogleChatInit:
)
return what_i_have_asked
def __conversation_history(self, history, llm_kwargs):
def __conversation_history(self, history, llm_kwargs, enable_multimodal_capacity):
messages = []
conversation_cnt = len(history) // 2
if conversation_cnt:
for index in range(0, 2 * conversation_cnt, 2):
what_i_have_asked = self.__conversation_user(history[index], llm_kwargs)
what_i_have_asked = self.__conversation_user(history[index], llm_kwargs, enable_multimodal_capacity)
what_gpt_answer = {
"role": "model",
"parts": [{"text": history[index + 1]}],
@ -168,7 +179,7 @@ class GoogleChatInit:
return messages
def generate_message_payload(
self, inputs, llm_kwargs, history, system_prompt
self, inputs, llm_kwargs, history, system_prompt, image_base64_array:list=[], has_multimodal_capacity:bool=False
) -> Tuple[Dict, Dict]:
messages = [
# {"role": "system", "parts": [{"text": system_prompt}]}, # gemini 不允许对话轮次为偶数,所以这个没有用,看后续支持吧。。。
@ -179,21 +190,29 @@ class GoogleChatInit:
"%m", llm_kwargs["llm_model"]
).replace("%k", get_conf("GEMINI_API_KEY"))
header = {"Content-Type": "application/json"}
if "vision" not in self.url_gemini: # 不是vision 才处理history
if has_multimodal_capacity:
enable_multimodal_capacity = (len(image_base64_array) > 0) or any([contain_base64(h) for h in history])
else:
enable_multimodal_capacity = False
if not enable_multimodal_capacity:
messages.extend(
self.__conversation_history(history, llm_kwargs)
self.__conversation_history(history, llm_kwargs, enable_multimodal_capacity)
) # 处理 history
messages.append(self.__conversation_user(inputs, llm_kwargs)) # 处理用户对话
messages.append(self.__conversation_user(inputs, llm_kwargs, enable_multimodal_capacity)) # 处理用户对话
payload = {
"contents": messages,
"generationConfig": {
# "maxOutputTokens": 800,
# "maxOutputTokens": llm_kwargs.get("max_token", 1024),
"stopSequences": str(llm_kwargs.get("stop", "")).split(" "),
"temperature": llm_kwargs.get("temperature", 1),
"topP": llm_kwargs.get("top_p", 0.8),
"topK": 10,
},
}
return header, payload

View File

@ -0,0 +1,40 @@
import tiktoken, copy, re
from functools import lru_cache
from concurrent.futures import ThreadPoolExecutor
from toolbox import get_conf, trimmed_format_exc, apply_gpt_academic_string_mask, read_one_api_model_name
# Endpoint 重定向
API_URL_REDIRECT, AZURE_ENDPOINT, AZURE_ENGINE = get_conf("API_URL_REDIRECT", "AZURE_ENDPOINT", "AZURE_ENGINE")
openai_endpoint = "https://api.openai.com/v1/chat/completions"
if not AZURE_ENDPOINT.endswith('/'): AZURE_ENDPOINT += '/'
azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15'
if openai_endpoint in API_URL_REDIRECT: openai_endpoint = API_URL_REDIRECT[openai_endpoint]
openai_embed_endpoint = openai_endpoint.replace("chat/completions", "embeddings")
from .openai_embed import OpenAiEmbeddingModel
embed_model_info = {
# text-embedding-3-small Increased performance over 2nd generation ada embedding model | 1,536
"text-embedding-3-small": {
"embed_class": OpenAiEmbeddingModel,
"embed_endpoint": openai_embed_endpoint,
"embed_dimension": 1536,
},
# text-embedding-3-large Most capable embedding model for both english and non-english tasks | 3,072
"text-embedding-3-large": {
"embed_class": OpenAiEmbeddingModel,
"embed_endpoint": openai_embed_endpoint,
"embed_dimension": 3072,
},
# text-embedding-ada-002 Most capable 2nd generation embedding model, replacing 16 first generation models | 1,536
"text-embedding-ada-002": {
"embed_class": OpenAiEmbeddingModel,
"embed_endpoint": openai_embed_endpoint,
"embed_dimension": 1536,
},
}

View File

@ -0,0 +1,79 @@
from llama_index.embeddings.openai import OpenAIEmbedding
from openai import OpenAI
from toolbox import get_conf
from toolbox import CatchException, update_ui, get_conf, select_api_key, get_log_folder, ProxyNetworkActivate
from shared_utils.key_pattern_manager import select_api_key_for_embed_models
from typing import List, Any
import numpy as np
def mean_agg(embeddings):
"""Mean aggregation for embeddings."""
return np.array(embeddings).mean(axis=0).tolist()
class EmbeddingModel():
def get_agg_embedding_from_queries(
self,
queries: List[str],
agg_fn = None,
):
"""Get aggregated embedding from multiple queries."""
query_embeddings = [self.get_query_embedding(query) for query in queries]
agg_fn = agg_fn or mean_agg
return agg_fn(query_embeddings)
def get_text_embedding_batch(
self,
texts: List[str],
show_progress: bool = False,
):
return self.compute_embedding(texts, batch_mode=True)
class OpenAiEmbeddingModel(EmbeddingModel):
def __init__(self, llm_kwargs:dict=None):
self.llm_kwargs = llm_kwargs
def get_query_embedding(self, query: str):
return self.compute_embedding(query)
def compute_embedding(self, text="这是要计算嵌入的文本", llm_kwargs:dict=None, batch_mode=False):
from .bridge_all_embed import embed_model_info
# load kwargs
if llm_kwargs is None:
llm_kwargs = self.llm_kwargs
if llm_kwargs is None:
raise RuntimeError("llm_kwargs is not provided!")
# setup api and req url
api_key = select_api_key_for_embed_models(llm_kwargs['api_key'], llm_kwargs['embed_model'])
embed_model = llm_kwargs['embed_model']
base_url = embed_model_info[llm_kwargs['embed_model']]['embed_endpoint'].replace('embeddings', '')
# send and compute
with ProxyNetworkActivate("Connect_OpenAI_Embedding"):
self.oai_client = OpenAI(api_key=api_key, base_url=base_url)
if batch_mode:
input = text
assert isinstance(text, list)
else:
input = [text]
assert isinstance(text, str)
res = self.oai_client.embeddings.create(input=input, model=embed_model)
# parse result
if batch_mode:
embedding = [d.embedding for d in res.data]
else:
embedding = res.data[0].embedding
return embedding
def embedding_dimension(self, llm_kwargs):
from .bridge_all_embed import embed_model_info
return embed_model_info[llm_kwargs['embed_model']]['embed_dimension']
if __name__ == "__main__":
pass

View File

@ -88,7 +88,7 @@ def read_single_conf_with_lru_cache(arg):
if is_any_api_key(r):
print亮绿(f"[API_KEY] 您的 API_KEY 是: {r[:15]}*** API_KEY 导入成功")
else:
print亮红("[API_KEY] 您的 API_KEY 不满足任何一种已知的密钥格式请在config文件中修改API密钥之后再运行。")
print亮红(f"[API_KEY] 您的 API_KEY{r[:15]}***不满足任何一种已知的密钥格式请在config文件中修改API密钥之后再运行(详见`https://github.com/binary-husky/gpt_academic/wiki/api_key`")
if arg == 'proxies':
if not read_single_conf_with_lru_cache('USE_PROXY'): r = None # 检查USE_PROXY防止proxies单独起作用
if r is None:

View File

@ -8,13 +8,20 @@ from shared_utils.config_loader import get_conf as get_conf
pj = os.path.join
default_user_name = 'default_user'
# match openai keys
openai_regex = re.compile(
r"sk-[a-zA-Z0-9_-]{48}$|" +
r"sk-[a-zA-Z0-9_-]{92}$|" +
r"sk-proj-[a-zA-Z0-9_-]{48}$|"+
r"sk-proj-[a-zA-Z0-9_-]{124}$|"+
r"sess-[a-zA-Z0-9]{40}$"
)
def is_openai_api_key(key):
CUSTOM_API_KEY_PATTERN = get_conf('CUSTOM_API_KEY_PATTERN')
if len(CUSTOM_API_KEY_PATTERN) != 0:
API_MATCH_ORIGINAL = re.match(CUSTOM_API_KEY_PATTERN, key)
else:
API_MATCH_ORIGINAL = re.match(r"sk-[a-zA-Z0-9]{48}$|sk-proj-[a-zA-Z0-9]{48}$|sess-[a-zA-Z0-9]{40}$", key)
API_MATCH_ORIGINAL = openai_regex.match(key)
return bool(API_MATCH_ORIGINAL)
@ -88,3 +95,19 @@ def select_api_key(keys, llm_model):
api_key = random.choice(avail_key_list) # 随机负载均衡
return api_key
def select_api_key_for_embed_models(keys, llm_model):
import random
avail_key_list = []
key_list = keys.split(',')
if llm_model.startswith('text-embedding-'):
for k in key_list:
if is_openai_api_key(k): avail_key_list.append(k)
if len(avail_key_list) == 0:
raise RuntimeError(f"您提供的api-key不满足要求不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源。")
api_key = random.choice(avail_key_list) # 随机负载均衡
return api_key

586
tests/test_embed.py Normal file
View File

@ -0,0 +1,586 @@
def validate_path():
import os, sys
os.path.dirname(__file__)
root_dir_assume = os.path.abspath(os.path.dirname(__file__) + "/..")
os.chdir(root_dir_assume)
sys.path.append(root_dir_assume)
validate_path() # validate path so you can run from base directory
# # """
# # Test 1
# # """
# # from request_llms.embed_models.openai_embed import OpenAiEmbeddingModel
# # from shared_utils.connect_void_terminal import get_chat_default_kwargs
# # oaiem = OpenAiEmbeddingModel()
# # chat_kwargs = get_chat_default_kwargs()
# # llm_kwargs = chat_kwargs['llm_kwargs']
# # llm_kwargs.update({
# # 'llm_model': "text-embedding-3-small"
# # })
# # res = oaiem.compute_embedding("你好", llm_kwargs)
# # print(res)
# """
# Test 2
# """
# from request_llms.embed_models.openai_embed import OpenAiEmbeddingModel
from shared_utils.connect_void_terminal import get_chat_default_kwargs
# from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# from crazy_functions.rag_fns.vector_store_index import GptacVectorStoreIndex
# from llama_index.core.ingestion import run_transformations
# from llama_index.core import PromptTemplate
# from llama_index.core.response_synthesizers import TreeSummarize
# # NOTE: we add an extra tone_name variable here
# DEFAULT_QUESTION_GENERATION_PROMPT = """\
# Context information is below.
# ---------------------
# {context_str}
# ---------------------
# Given the context information and not prior knowledge.
# generate only questions based on the below query.
# {query_str}
# """
chat_kwargs = get_chat_default_kwargs()
llm_kwargs = chat_kwargs['llm_kwargs']
llm_kwargs.update({
'llm_model': "text-embedding-3-small",
'embed_model': "text-embedding-3-small"
})
# embed_model = OpenAiEmbeddingModel(llm_kwargs)
# ## dir
# documents = SimpleDirectoryReader("private_upload/rag_test/").load_data()
# ## single files
# # from llama_index.core import Document
# # text_list = [text1, text2, ...]
# # documents = [Document(text=t) for t in text_list]
# vsi = GptacVectorStoreIndex.default_vector_store(embed_model=embed_model)
# documents_nodes = run_transformations(
# documents, # type: ignore
# vsi._transformations,
# show_progress=True
# )
# index = vsi.insert_nodes(documents_nodes)
# retriever = vsi.as_retriever()
# query = "what is core_functional.py"
# res = retriever.retrieve(query)
# context_str = '\n'.join([r.text for r in res])
# query_str = query
# query = DEFAULT_QUESTION_GENERATION_PROMPT.format(context_str=context_str, query_str=query_str)
# print(res)
# print(res)
# # response = query_engine.query("Some question about the data should go here")
# # print(response)
from crazy_functions.rag_fns.llama_index_worker import LlamaIndexRagWorker
rag_worker = LlamaIndexRagWorker('good-man-user', llm_kwargs, checkpoint_dir='./longlong_vector_store')
rag_worker.add_text_to_vector_store("""
熊童子Cotyledon tomentosa是景天科银波锦属的多年生肉质草本植物植株多分枝茎绿色肉质叶肥厚交互对生卵圆形绿色密生白色短毛叶端具红色爪样齿二歧聚伞花序小花黄色花期7-9
该种原产于南非开普省喜温暖干燥阳光充足通风良好的环境夏季温度过高会休眠忌寒冷和过分潮湿繁殖方法有扦插
该种叶形叶色较美花朵玲珑小巧叶片形似小熊的脚掌形态奇特十分可爱观赏价值很高
物种索引IN4679748
""")
rag_worker.add_text_to_vector_store("""
碧光环是番杏科碧光玉属 [4]多年生肉质草本植物 [5]碧光环叶表面有半透明的颗粒感晶莹剔透两片圆柱形的叶子在生长初期像兔耳非常可爱长大后叶子会慢慢变长变粗缺水时容易耷拉下来具枝干易群生
碧光环原产于南非碧光环喜温暖和散射光充足的环境较耐寒忌强光暴晒夏季高温休眠明显 [6]碧光环的繁殖方式有扦插和播种 [7]
碧光环小巧饱满圆滚滚的样子很可爱长得好像长耳朵小兔萌萌的样子让人爱不释手而且养起来也不难极具观赏价值 [8]
物种索引IN985654
""")
rag_worker.add_text_to_vector_store("""
福娘为景天科银波锦属的肉质草本植物对生的叶片呈短棒状叶色灰绿表覆白粉叶缘外围镶着紫红色叶片外形多有变化有短圆形厚厚的方形等不同叶形 [5]花期夏秋 [6]
福娘原产于非洲西南部的纳米比亚现世界多地均有栽培性喜欢凉爽通风日照充足的环境较喜光照喜肥生长适温为15-25冬季温度不低于5生长期要见干见湿 [7]在通风透气排水良好的土壤上生长良好一般可用泥炭土蛭石和珍珠岩的混合土繁殖方式一般为扦插繁殖多用枝插叶插的繁殖成功率不高 [8]
因福娘的叶形叶色较美所以具有一定的观赏价值可盆栽放置于电视电脑旁吸收辐射亦可栽植于室内以吸收甲醛等物质净化空气 [9]
物种索引IN772
""")
rag_worker.add_text_to_vector_store("""
石莲 Sinocrassula indica (Decne.) A. Berger是景天科石莲属 [8]的二年生草本植物基生叶莲座状匙状长圆形茎生叶互生宽倒披针状线形或近倒卵形花序圆锥状或近伞房状萼片呈宽三角形花瓣呈红色披针形或卵形雄蕊呈正方形蓇葖果的喙反曲种子平滑花期9月果期10月 [9]锯叶石莲为石莲的变种与原变种的不同处为叶上部有渐尖的锯齿茎和花无毛叶被毛 [10]因叶子有棱有角又似玉石故而得名石莲 [11]
物种索引IN455674
""")
rag_worker.add_text_to_vector_store("""
虹之玉锦Sedum × rubrotinctum 'Aurora' [1]是景天科景天属的多肉植物为虹之玉的锦化品种虹之玉锦与虹之玉的叶片大小没有特别大的变化但颜色会稍有不同虹之玉锦一般会有粉红色中绿色等 [2]生长速度较虹之玉慢很多 [3]
物种索引IN88
""")
rag_worker.add_text_to_vector_store("""
一个幽灵共产主义的幽灵在欧洲游荡为了对这个幽灵进行神圣的围剿旧欧洲的一切势力教皇和沙皇梅特涅和基佐法国的激进派和德国的警察都联合起来了
有哪一个反对党不被它的当政的敌人骂为共产党呢又有哪一个反对党不拿共产主义这个罪名去回敬更进步的反对党人和自己的反动敌人呢
从这一事实中可以得出两个结论
共产主义已经被欧洲的一切势力公认为一种势力
现在是共产党人向全世界公开说明自己的观点自己的目的自己的意图并且拿党自己的宣言来反驳关于共产主义幽灵的神话的时候了
为了这个目的各国共产党人集会于伦敦拟定了如下的宣言用英文法文德文意大利文弗拉芒文和丹麦文公布于世
资产者和无产者
至今一切社会的历史都是阶级斗争的历史
自由民和奴隶贵族和平民领主和农奴行会师傅和帮工一句话压迫者和被压迫者始终处于相互对立的地位进行不断的有时隐蔽有时公开的斗争而每一次斗争的结局都是整个社会受到革命改造或者斗争的各阶级同归于尽
在过去的各个历史时代我们几乎到处都可以看到社会完全划分为各个不同的等级看到社会地位分成多种多样的层次在古罗马有贵族骑士平民奴隶在中世纪有封建主臣仆行会师傅帮工农奴而且几乎在每一个阶级内部又有一些特殊的阶层
从封建社会的灭亡中产生出来的现代资产阶级社会并没有消灭阶级对立它只是用新的阶级新的压迫条件新的斗争形式代替了旧的
但是我们的时代资产阶级时代却有一个特点它使阶级对立简单化了整个社会日益分裂为两大敌对的阵营分裂为两大相互直接对立的阶级资产阶级和无产阶级
从中世纪的农奴中产生了初期城市的城关市民从这个市民等级中发展出最初的资产阶级分子
美洲的发现绕过非洲的航行给新兴的资产阶级开辟了新天地东印度和中国的市场美洲的殖民化对殖民地的贸易交换手段和一般商品的增加使商业航海业和工业空前高涨因而使正在崩溃的封建社会内部的革命因素迅速发展
以前那种封建的或行会的工业经营方式已经不能满足随着新市场的出现而增加的需求了工场手工业代替了这种经营方式行会师傅被工业的中间等级排挤掉了各种行业组织之间的分工随着各个作坊内部的分工的出现而消失了
但是市场总是在扩大需求总是在增加甚至工场手工业也不再能满足需要了于是蒸汽和机器引起了工业生产的革命现代大工业代替了工场手工业工业中的百万富翁一支一支产业大军的首领现代资产者代替了工业的中间等级
大工业建立了由美洲的发现所准备好的世界市场世界市场使商业航海业和陆路交通得到了巨大的发展这种发展又反过来促进了工业的扩展同时随着工业商业航海业和铁路的扩展资产阶级也在同一程度上得到发展增加自己的资本把中世纪遗留下来的一切阶级排挤到后面去
由此可见现代资产阶级本身是一个长期发展过程的产物是生产方式和交换方式的一系列变革的产物
资产阶级的这种发展的每一个阶段都伴随着相应的政治上的进展它在封建主统治下是被压迫的等级在公社里是武装的和自治的团体在一些地方组成独立的城市共和国在另一些地方组成君主国中的纳税的第三等级后来在工场手工业时期它是等级君主国或专制君主国中同贵族抗衡的势力而且是大君主国的主要基础最后从大工业和世界市场建立的时候起它在现代的代议制国家里夺得了独占的政治统治现代的国家政权不过是管理整个资产阶级的共同事务的委员会罢了
资产阶级在历史上曾经起过非常革命的作用
资产阶级在它已经取得了统治的地方把一切封建的宗法的和田园般的关系都破坏了它无情地斩断了把人们束缚于天然尊长的形形色色的封建羁绊它使人和人之间除了赤裸裸的利害关系除了冷酷无情的现金交易就再也没有任何别的联系了它把宗教虔诚骑士热忱小市民伤感这些情感的神圣发作淹没在利己主义打算的冰水之中它把人的尊严变成了交换价值用一种没有良心的贸易自由代替了无数特许的和自力挣得的自由总而言之它用公开的无耻的直接的露骨的剥削代替了由宗教幻想和政治幻想掩盖着的剥削
资产阶级抹去了一切向来受人尊崇和令人敬畏的职业的神圣光环它把医生律师教士诗人和学者变成了它出钱招雇的雇佣劳动者
资产阶级撕下了罩在家庭关系上的温情脉脉的面纱把这种关系变成了纯粹的金钱关系
资产阶级揭示了在中世纪深受反动派称许的那种人力的野蛮使用是以极端怠惰作为相应补充的它第一个证明了人的活动能够取得什么样的成就它创造了完全不同于埃及金字塔罗马水道和哥特式教堂的奇迹它完成了完全不同于民族大迁徙和十字军征讨的远征
资产阶级除非对生产工具从而对生产关系从而对全部社会关系不断地进行革命否则就不能生存下去反之原封不动地保持旧的生产方式却是过去的一切工业阶级生存的首要条件生产的不断变革一切社会状况不停的动荡永远的不安定和变动这就是资产阶级时代不同于过去一切时代的地方一切固定的僵化的关系以及与之相适应的素被尊崇的观念和见解都被消除了一切新形成的关系等不到固定下来就陈旧了一切等级的和固定的东西都烟消云散了一切神圣的东西都被亵渎了人们终于不得不用冷静的眼光来看他们的生活地位他们的相互关系
不断扩大产品销路的需要驱使资产阶级奔走于全球各地它必须到处落户到处开发到处建立联系
资产阶级由于开拓了世界市场使一切国家的生产和消费都成为世界性的了使反动派大为惋惜的是资产阶级挖掉了工业脚下的民族基础古老的民族工业被消灭了并且每天都还在被消灭它们被新的工业排挤掉了新的工业的建立已经成为一切文明民族的生命攸关的问题这些工业所加工的已经不是本地的原料而是来自极其遥远的地区的原料它们的产品不仅供本国消费而且同时供世界各地消费旧的靠本国产品来满足的需要被新的要靠极其遥远的国家和地带的产品来满足的需要所代替了过去那种地方的和民族的自给自足和闭关自守状态被各民族的各方面的互相往来和各方面的互相依赖所代替了物质的生产是如此精神的生产也是如此各民族的精神产品成了公共的财产民族的片面性和局限性日益成为不可能于是由许多种民族的和地方的文学形成了一种世界的文学
资产阶级由于一切生产工具的迅速改进由于交通的极其便利把一切民族甚至最野蛮的民族都卷到文明中来了它的商品的低廉价格是它用来摧毁一切万里长城征服野蛮人最顽强的仇外心理的重炮它迫使一切民族如果它们不想灭亡的话采用资产阶级的生产方式它迫使它们在自己那里推行所谓的文明即变成资产者一句话它按照自己的面貌为自己创造出一个世界
资产阶级使农村屈服于城市的统治它创立了巨大的城市使城市人口比农村人口大大增加起来因而使很大一部分居民脱离了农村生活的愚昧状态正像它使农村从属于城市一样它使未开化和半开化的国家从属于文明的国家使农民的民族从属于资产阶级的民族使东方从属于西方
资产阶级日甚一日地消灭生产资料财产和人口的分散状态它使人口密集起来使生产资料集中起来使财产聚集在少数人的手里由此必然产生的结果就是政治的集中各自独立的几乎只有同盟关系的各有不同利益不同法律不同政府不同关税的各个地区现在已经结合为一个拥有统一的政府统一的法律统一的民族阶级利益和统一的关税的统一的民族
资产阶级在它的不到一百年的阶级统治中所创造的生产力比过去一切世代创造的全部生产力还要多还要大自然力的征服机器的采用化学在工业和农业中的应用轮船的行驶铁路的通行电报的使用整个整个大陆的开垦河川的通航仿佛用法术从地下呼唤出来的大量人口过去哪一个世纪料想到在社会劳动里蕴藏有这样的生产力呢
由此可见资产阶级赖以形成的生产资料和交换手段是在封建社会里造成的在这些生产资料和交换手段发展的一定阶段上封建社会的生产和交换在其中进行的关系封建的农业和工场手工业组织一句话封建的所有制关系就不再适应已经发展的生产力了这种关系已经在阻碍生产而不是促进生产了它变成了束缚生产的桎梏它必须被炸毁它已经被炸毁了
起而代之的是自由竞争以及与自由竞争相适应的社会制度和政治制度资产阶级的经济统治和政治统治
现在我们眼前又进行着类似的运动资产阶级的生产关系和交换关系资产阶级的所有制关系这个曾经仿佛用法术创造了如此庞大的生产资料和交换手段的现代资产阶级社会现在像一个魔法师一样不能再支配自己用法术呼唤出来的魔鬼了几十年来的工业和商业的历史只不过是现代生产力反抗现代生产关系反抗作为资产阶级及其统治的存在条件的所有制关系的历史只要指出在周期性的重复中越来越危及整个资产阶级社会生存的商业危机就够了在商业危机期间总是不仅有很大一部分制成的产品被毁灭掉而且有很大一部分已经造成的生产力被毁灭掉在危机期间发生一种在过去一切时代看来都好像是荒唐现象的社会瘟疫即生产过剩的瘟疫社会突然发现自己回到了一时的野蛮状态仿佛是一次饥荒一场普遍的毁灭性战争使社会失去了全部生活资料仿佛是工业和商业全被毁灭了这是什么缘故呢因为社会上文明过度生活资料太多工业和商业太发达社会所拥有的生产力已经不能再促进资产阶级文明和资产阶级所有制关系的发展相反生产力已经强大到这种关系所不能适应的地步它已经受到这种关系的阻碍而它一着手克服这种障碍就使整个资产阶级社会陷入混乱就使资产阶级所有制的存在受到威胁资产阶级的关系已经太狭窄了再容纳不了它本身所造成的财富了资产阶级用什么办法来克服这种危机呢一方面不得不消灭大量生产力另一方面夺取新的市场更加彻底地利用旧的市场这究竟是怎样的一种办法呢这不过是资产阶级准备更全面更猛烈的危机的办法不过是使防止危机的手段越来越少的办法
资产阶级用来推翻封建制度的武器现在却对准资产阶级自己了
但是资产阶级不仅锻造了置自身于死地的武器它还产生了将要运用这种武器的人现代的工人即无产者
随着资产阶级即资本的发展无产阶级即现代工人阶级也在同一程度上得到发展现代的工人只有当他们找到工作的时候才能生存而且只有当他们的劳动增殖资本的时候才能找到工作这些不得不把自己零星出卖的工人像其他任何货物一样也是一种商品所以他们同样地受到竞争的一切变化市场的一切波动的影响
由于推广机器和分工无产者的劳动已经失去了任何独立的性质因而对工人也失去了任何吸引力工人变成了机器的单纯的附属品要求他做的只是极其简单极其单调和极容易学会的操作因此花在工人身上的费用几乎只限于维持工人生活和延续工人后代所必需的生活资料但是商品的价格从而劳动的价格是同它的生产费用相等的因此劳动越使人感到厌恶工资也就越少不仅如此机器越推广分工越细致劳动量出就越增加这或者是由于工作时间的延长或者是由于在一定时间内所要求的劳动的增加机器运转的加速等等
现代工业已经把家长式的师傅的小作坊变成了工业资本家的大工厂挤在工厂里的工人群众就像士兵一样被组织起来他们是产业军的普通士兵受着各级军士和军官的层层监视他们不仅仅是资产阶级的资产阶级国家的奴隶他们每日每时都受机器受监工首先是受各个经营工厂的资产者本人的奴役这种专制制度越是公开地把营利宣布为自己的最终目的它就越是可鄙可恨和可恶
手的操作所要求的技巧和气力越少换句话说现代工业越发达男工也就越受到女工和童工的排挤对工人阶级来说性别和年龄的差别再没有什么社会意义了他们都只是劳动工具不过因为年龄和性别的不同而需要不同的费用罢了
当厂主对工人的剥削告一段落工人领到了用现钱支付的工资的时候马上就有资产阶级中的另一部分人房东小店主当铺老板等等向他们扑来
以前的中间等级的下层即小工业家小商人和小食利者手工业者和农民所有这些阶级都降落到无产阶级的队伍里来了有的是因为他们的小资本不足以经营大工业经不起较大的资本家的竞争有的是因为他们的手艺已经被新的生产方法弄得不值钱了无产阶级就是这样从居民的所有阶级中得到补充的
无产阶级经历了各个不同的发展阶段它反对资产阶级的斗争是和它的存在同时开始的
最初是单个的工人然后是某一工厂的工人然后是某一地方的某一劳动部门的工人同直接剥削他们的单个资产者作斗争他们不仅仅攻击资产阶级的生产关系而且攻击生产工具本身他们毁坏那些来竞争的外国商品捣毁机器烧毁工厂力图恢复已经失去的中世纪工人的地位
在这个阶段上工人是分散在全国各地并为竞争所分裂的群众工人的大规模集结还不是他们自己联合的结果而是资产阶级联合的结果当时资产阶级为了达到自己的政治目的必须而且暂时还能够把整个无产阶级发动起来因此在这个阶段上无产者不是同自己的敌人作斗争而是同自己的敌人的敌人作斗争即同专制君主制的残余地主非工业资产者和小资产者作斗争因此整个历史运动都集中在资产阶级手里在这种条件下取得的每一个胜利都是资产阶级的胜利
但是随着工业的发展无产阶级不仅人数增加了而且它结合成更大的集体它的力量日益增长它越来越感觉到自己的力量机器使劳动的差别越来越小使工资几乎到处都降到同样低的水平因而无产阶级内部的利益生活状况也越来越趋于一致资产者彼此间日益加剧的竞争以及由此引起的商业危机使工人的工资越来越不稳定机器的日益迅速的和继续不断的改良使工人的整个生活地位越来越没有保障单个工人和单个资产者之间的冲突越来越具有两个阶级的冲突的性质工人开始成立反对资产者的同盟他们联合起来保卫自己的工资他们甚至建立了经常性的团体以便为可能发生的反抗准备食品有些地方斗争爆发为起义
工人有时也得到胜利但这种胜利只是暂时的他们斗争的真正成果并不是直接取得的成功而是工人的越来越扩大的联合这种联合由于大工业所造成的日益发达的交通工具而得到发展这种交通工具把各地的工人彼此联系起来只要有了这种联系就能把许多性质相同的地方性的斗争汇合成全国性的斗争汇合成阶级斗争而一切阶级斗争都是政治斗争中世纪的市民靠乡间小道需要几百年才能达到的联合现代的无产者利用铁路只要几年就可以达到了
无产者组织成为阶级从而组织成为政党这件事不断地由于工人的自相竞争而受到破坏但是这种组织总是重新产生并且一次比一次更强大更坚固更有力它利用资产阶级内部的分裂迫使他们用法律形式承认工人的个别利益英国的十小时工作日法案就是一个例子
旧社会内部的所有冲突在许多方面都促进了无产阶级的发展资产阶级处于不断的斗争中最初反对贵族后来反对同工业进步有利害冲突的那部分资产阶级经常反对一切外国的资产阶级在这一切斗争中资产阶级都不得不向无产阶级呼吁要求无产阶级援助这样就把无产阶级卷进了政治运动于是资产阶级自己就把自己的教育因素即反对自身的武器给予了无产阶级
其次我们已经看到工业的进步把统治阶级的整批成员抛到无产阶级队伍里去或者至少也使他们的生活条件受到威胁他们也给无产阶级带来了大量的教育因素
最后在阶级斗争接近决战的时期统治阶级内部的整个旧社会内部的瓦解过程就达到非常强烈非常尖锐的程度甚至使得统治阶级中的一小部分人脱离统治阶级而归附于革命的阶级即掌握着未来的阶级所以正像过去贵族中有一部分人转到资产阶级方面一样现在资产阶级中也有一部分人特别是已经提高到从理论上认识整个历史运动这一水平的一部分资产阶级思想家转到无产阶级方面来了
在当前同资产阶级对立的一切阶级中只有无产阶级是真正革命的阶级其余的阶级都随着大工业的发展而日趋没落和灭亡无产阶级却是大工业本身的产物
中间等级即小工业家小商人手工业者农民他们同资产阶级作斗争都是为了维护他们这种中间等级的生存以免于灭亡所以他们不是革命的而是保守的不仅如此他们甚至是反动的因为他们力图使历史的车轮倒转如果说他们是革命的那是鉴于他们行将转入无产阶级的队伍这样他们就不是维护他们目前的利益而是维护他们将来的利益他们就离开自己原来的立场而站到无产阶级的立场上来
流氓无产阶级是旧社会最下层中消极的腐化的部分他们在一些地方也被无产阶级革命卷到运动里来但是由于他们的整个生活状况他们更甘心于被人收买去干反动的勾当
在无产阶级的生活条件中旧社会的生活条件已经被消灭了无产者是没有财产的他们和妻子儿女的关系同资产阶级的家庭关系再没有任何共同之处了现代的工业劳动现代的资本压迫无论在英国或法国无论在美国或德国都有是一样的都使无产者失去了任何民族性法律道德宗教在他们看来全都是资产阶级偏见隐藏在这些偏见后面的全都是资产阶级利益
过去一切阶级在争得统治之后总是使整个社会服从于它们发财致富的条件企图以此来巩固它们已获得的生活地位无产者只有废除自己的现存的占有方式从而废除全部现存的占有方式才能取得社会生产力无产者没有什么自己的东西必须加以保护他们必须摧毁至今保护和保障私有财产的一切
过去的一切运动都是少数人的或者为少数人谋利益的运动无产阶级的运动是绝大多数人的为绝大多数人谋利益的独立的运动无产阶级现今社会的最下层如果不炸毁构成官方社会的整个上层就不能抬起头来挺起胸来
如果不就内容而就形式来说无产阶级反对资产阶级的斗争首先是一国范围内的斗争每一个国家的无产阶级当然首先应该打倒本国的资产阶级
在叙述无产阶级发展的最一般的阶段的时候我们循序探讨了现存社会内部或多或少隐蔽着的国内战争直到这个战争爆发为公开的革命无产阶级用暴力推翻资产阶级而建立自己的统治
我们已经看到至今的一切社会都是建立在压迫阶级和被压迫阶级的对立之上的但是为了有可能压迫一个阶级就必须保证这个阶级至少有能够勉强维持它的奴隶般的生存的条件农奴曾经在农奴制度下挣扎到公社成员的地位小资产者曾经在封建专制制度的束缚下挣扎到资产者的地位现代的工人却相反他们并不是随着工业的进步而上升而是越来越降到本阶级的生存条件以下工人变成赤贫者贫困比人口和财富增长得还要快由此可以明显地看出资产阶级再不能做社会的统治阶级了再不能把自己阶级的生存条件当作支配一切的规律强加于社会了资产阶级不能统治下去了因为它甚至不能保证自己的奴隶维持奴隶的生活因为它不得不让自己的奴隶落到不能养活它反而要它来养活的地步社会再不能在它统治下生存下去了就是说它的生存不再同社会相容了
资产阶级生存和统治的根本条件是财富在私人手里的积累是资本的形成和增殖资本的条件是雇佣劳动雇佣劳动完全是建立在工人的自相竞争之上的资产阶级无意中造成而又无力抵抗的工业进步使工人通过结社而达到的革命联合代替了他们由于竞争而造成的分散状态于是随着大工业的发展资产阶级赖以生产和占有产品的基础本身也就从它的脚下被挖掉了它首先生产的是它自身的掘墓人资产阶级的灭亡和无产阶级的胜利是同样不可避免的
无产者和共产党人
共产党人同全体无产者的关系是怎样的呢
共产党人不是同其他工人政党相对立的特殊政党
他们没有任何同整个无产阶级的利益不同的利益
他们不提出任何特殊的原则用以塑造无产阶级的运动
共产党人同其他无产阶级政党不同的地方只是一方面在无产者不同的民族的斗争中共产党人强调和坚持整个无产阶级共同的不分民族的利益另一方面在无产阶级和资产阶级的斗争所经历的各个发展阶段上共产党人始终代表整个运动的利益
因此在实践方面共产党人是各国工人政党中最坚决的始终起推动作用的部分在理论方面他们胜过其余无产阶级群众的地方在于他们了解无产阶级运动的条件进程和一般结果
共产党人的最近目的是和其他一切无产阶级政党的最近目的一样的使无产阶级形成为阶级推翻资产阶级的统治由无产阶级夺取政权
共产党人的理论原理决不是以这个或那个世界改革家所发明或发现的思想原则为根据的
这些原理不过是现存的阶级斗争我们眼前的历史运动的真实关系的一般表述废除先前存在的所有制关系并不是共产主义所独具的特征
一切所有制关系都经历了经常的历史更替经常的历史变更
例如法国革命废除了封建的所有制代之以资产阶级的所有制
共产主义的特征并不是要废除一般的所有制而是要废除资产阶级的所有制
但是现代的资产阶级私有制是建立在阶级对立上面建立在一些人对另一些人的剥削上面的产品生产和占有的最后而又完备的表现
从这个意义上说共产党人可以把自己的理论概括为一句话消灭私有制
有人责备我们共产党人说我们消灭个人挣得的自己劳动得来的财产要消灭构成个人的一切自由活动和独立的基础的财产
好一个劳动得来的自己挣得的自己赚来的财产你们说的是资产阶级财产出现以前的那种小资产阶级小农的财产吗那种财产用不着我们去消灭工业的发展已经把它消灭了而且每天都在消灭它
或者你们说的是现代的资产阶级的私有财产吧
但是难道雇佣劳动无产者的劳动会给无产者创造出财产来吗没有的事这种劳动所创造的资本即剥削雇佣劳动的财产只有在不断产生出新的雇佣劳动来重新加以剥削的条件下才能增殖的财产现今的这种财产是在资本和雇佣劳动的对立中运动的让我们来看看这种对立的两个方面吧
做一个资本家这就是说他在生产中不仅占有一种纯粹个人的地位而且占有一种社会地位资本是集体的产物它只有通过社会许多成员的共同活动而且归根到底只有通过社会全体成员的共同活动才能运动起来
因此资本不是一种个人力量而是一种社会力量
因此把资本变为公共的属于社会全体成员的财产这并不是把个人财产变为社会财产这里所改变的只是财产的社会性质它将失掉它的阶级性质
现在我们来看看雇佣劳动
雇佣劳动的平均价格是最低限度的工资即工人为维持其工人的生活所必需的生活资料的数额因此雇佣工人靠自己的劳动所占有的东西只够勉强维持他的生命的再生产我们决不打算消灭这种供直接生命再生产用的劳动产品的个人占有这种占有并不会留下任何剩余的东西使人们有可能支配别人的劳动我们要消灭的只是这种占有的可怜的性质在这种占有下工人仅仅为增殖资本而活着只有在统治阶级的利益需要他活着的时候才能活着
在资产阶级社会里活的劳动只是增殖已经积累起来的劳动的一种手段在共产主义社会里已经积累起来的劳动只是扩大丰富和提高工人的生活的一种手段
因此在资产阶级社会里是过去支配现在在共产主义社会里是现在支配过去在资产阶级社会里资本具有独立性和个性而活动着的个人却没有独立性和个性
而资产阶级却把消灭这种关系说成是消灭个性和自由说对了的确正是要消灭资产者的个性独立性和自由
在现今的资产阶级生产关系的范围内所谓自由就是自由贸易自由买卖
但是买卖一消失自由买卖也就会消失关于自由买卖的言论也像我们的资产阶级的其他一切关于自由的大话一样仅仅对于不自由的买卖来说对于中世纪被奴役的市民来说才是有意义的而对于共产主义要消灭买卖消灭资产阶级生产关系和资产阶级本身这一点来说却是毫无意义的
我们要消灭私有制你们就惊慌起来但是在你们的现存社会里私有财产对十分之九的成员来说已经被消灭了这种私有制这所以存在正是因为私有财产对十分之九的成员来说已经不存在可见你们责备我们是说我们要消灭那种以社会上的绝大多数人没有财产为必要条件的所有制
总而言之你们责备我们是说我们要消灭你们的那种所有制的确我们是要这样做的
从劳动不再能变为资本货币地租一句话不再能变为可以垄断的社会力量的时候起就是说从个人财产不再能变为资产阶级财产的时候起你们说个性被消灭了
由此可见你们是承认你们所理解的个性不外是资产者资产阶级私有者这样的个性确实应当被消灭
共产主义并不剥夺任何人占有社会产品的权力它只剥夺利用这种占有去奴役他人劳动的权力
有人反驳说私有制一消灭一切活动就会停止懒惰之风就会兴起
这样说来资产阶级社会早就应该因懒惰而灭亡了因为在这个社会里劳者不获获者不劳所有这些顾虑都可以归结为这样一个同义反复一旦没有资本也就不再有雇佣劳动了
所有这些对共产主义的物质产品的占有方式和生产方式的责备也被扩及到精神产品的占有和生产方面正如阶级的所有制的终止在资产者看来是生产本身的终止一样阶级的教育的终止在他们看来就等于一切教育的终止
资产者唯恐失去的那种教育绝大多数人来说是把人训练成机器
但是你们既然用你们资产阶级关于自由教育法等等的观念来衡量废除资产阶级所有制的主张那就请你们不要同我们争论了你们的观念本身是资产阶级的生产关系和所有制关系的产物正像你们的法不过是被奉为法律的你们这个阶级的意志一样而这种意志的内容是由你们这个阶级的物质生活条件决定的
你们的利己观念使你们把自己的生产关系和所有制关系从历史的在生产过程中是暂时的关系变成永恒的自然规律和理性规律这种利己观念是你们和一切灭亡了的统治阶级所共有的谈到古代所有制的时候你们所能理解的谈到封建所有制的时候你们所能理解的一谈到资产阶级所有制你们就再也不能理解了
消灭家庭连极端的激进派也对共产党人的这种可耻的意图表示愤慨
现代的资产阶级的家庭是建立在什么基础上的呢是建立在资本上面建立在私人发财上面的这种家庭只是在资产阶级那里才以充分发展的形式存在着而无产者的被迫独居和公开的卖淫则是它的补充
资产者的家庭自然会随着它的这种补充的消失而消失两者都要随着资本的消失而消失
你们是责备我们要消灭父母对子女的剥削吗我们承认这种罪状
但是你们说我们用社会教育代替家庭教育就是要消灭人们最亲密的关系
而你们的教育不也是由社会决定的吗不也是由你们进行教育时所处的那种社会关系决定的吗不也是由社会通过学校等等进行的直接的或间接的干涉决定的吗共产党人并没有发明社会对教育的作用他们仅仅是要改变这种作用的性质要使教育摆脱统治阶级的影响
无产者的一切家庭联系越是由于大工业的发展而被破坏他们的子女越是由于这种发展而被变成单纯的商品和劳动工具资产阶级关于家庭和教育关于父母和子女的亲密关系的空话就越是令人作呕
但是你们共产党人是要实行公妻制的啊整个资产阶级异口同声地向我们这样叫喊
资产者是把自己的妻子看作单纯的生产工具的他们听说生产工具将要公共使用自然就不能不想到妇女也会遭到同样的命运
他们想也没有想到问题正在于使妇女不再处于单纯生产工具的地位
其实我们的资产者装得道貌岸然对所谓的共产党人的正式公妻制表示惊讶那是再可笑不过了公妻制无需共产党人来实行它差不多是一向就有的
我们的资产者不以他们的无产者的妻子和女儿受他们支配为满足正式的卖淫更不必说了他们还以互相诱奸妻子为最大的享乐
资产阶级的婚姻实际上是公妻制人们至多只能责备共产党人说他们想用正式的公开的公妻制来代替伪善地掩蔽着的公妻制其实不言而喻随着现在的生产关系的消灭从这种关系中产生的公妻制即正式的和非正式的卖淫也就消失了
有人还责备共产党人说他们要取消祖国取消民族
工人没有祖国决不能剥夺他们所没有的东西因为无产阶级首先必须取得政治统治上升为民族的阶级把自身组织成为民族所以它本身还是民族的虽然完全不是资产阶级所理解的那种意思
随着资产阶级的发展随着贸易自由的实现和世界市场的建立随着工业生产以及与之相适应的生活条件的趋于一致各国人民之间的民族分隔和对立日益消失
无产阶级的统治将使它们更快地消失联合的行动至少是各文明国家的联合的行动是无产阶级获得解放的首要条件之一
人对人的剥削一消灭民族对民族的剥削就会随之消灭
民族内部的阶级对立一消失民族之间的敌对关系就会随之消失
从宗教的哲学的和一切意识形态的观点对共产主义提出的种种责难都不值得详细讨论了
人们的观念观点和概念一句话人们的意识随着人们的生活条件人们的社会关系人们的社会存在的改变而改变这难道需要经过深思才能了解吗
思想的历史除了证明精神生产随着物质生产的改造而改造还证明了什么呢任何一个时代的统治思想始终都不过是统治阶级的思想
当人们谈到使整个社会革命化的思想时他们只是表明了一个事实在旧社会内部已经形成了新社会的因素旧思想的瓦解是同旧生活条件的瓦解步调一致的
当古代世界走向灭亡的时候古代的各种宗教就被基督教战胜了当基督教思想在18世纪被启蒙思想击败的时候封建社会正在同当时革命的资产阶级进行殊死的斗争信仰自由和宗教自由的思想不过表明竞争在信仰领域里占统治地位罢了
但是有人会说宗教的道德的哲学的政治的法的观念等等在历史发展的进程中固然是不断改变的而宗教道德哲学政治和法在这种变化中却始终保存着
此外还存在着一切社会状态所共有的永恒真理如自由正义等等但是共产主义要废除永恒真理它要废除宗教道德而不是加以革新所以共产主义是同至今的全部历史发展相矛盾的
这种责难归结为什么呢至今的一切社会的历史都是在阶级对立中运动的而这种对立在不同的时代具有不同的形式
但是不管阶级对立具有什么样的形式社会上一部分人对另一部分人的剥削却是过去各个世纪所共有的事实因此毫不奇怪各个世纪的社会意识尽管形形色色千差万别总是在某些共同的形式中运动的这些形式这些意识形式只有当阶级对立完全消失的时候才会完全消失
共产主义革命就是同传统的所有制关系实行最彻底的决裂毫不奇怪它在自己的发展进程中要同传统的观念实行最彻底的决裂
不过我们还是把资产阶级对共产主义的种种责难撇开吧
前面我们已经看到工人革命的第一步就是使无产阶级上升为统治阶级争得民主
无产阶级将利用自己的政治统治一步一步地夺取资产阶级的全部资本把一切生产工具集中在国家即组织成为统治阶级的无产阶级手里并且尽可能快地增加生产力的总量
要做到这一点当然首先必须对所有权和资产阶级生产关系实行强制性的干涉也就是采取这样一些措施这些措施在经济上似乎是不够充分的和没有力量的但是在运动进程中它们会越出本身而且作为变革全部生产方式的手段是必不可少的
这些措施在不同的国家里当然会是不同的
但是最先进的国家几乎都可以采取下面的措施
1剥夺地产把地租用于国家支出
2征收高额累进税
3废除继承权
4没收一切流亡分子和叛乱分子的财产
5通过拥有国家资本和独享垄断权的国家银行把信贷集中在国家手里
6把全部运输业集中在国家的手里
7按照总的计划增加国家工厂和生产工具开垦荒地和改良土壤
8实行普遍劳动义务制成立产业军特别是在农业方面
9把农业和工业结合起来促使城乡对立逐步消灭
10对所有儿童实行公共的和免费的教育取消现在这种形式的儿童的工厂劳动把教育同物质生产结合起来等等
当阶级差别在发展进程中已经消失而全部生产集中在联合起来的个人的手里的时候公共权力就失去政治性质原来意义上的政治权力是一个阶级用以压迫另一个阶级的有组织的暴力如果说无产阶级在反对资产阶级的斗争中一定要联合为阶级如果说它通过革命使自己成为统治阶级并以统治阶级的资格用暴力消灭旧的生产关系那么它在消灭这种生产关系的同时也就消灭了阶级对立的存在条件消灭阶级本身的存在条件从而消灭了它自己这个阶级的统治
代替那存在着阶级和阶级对立的资产阶级旧社会的将是这样一个联合体在那里每个人的自由发展是一切人的自由发展的条件
社会主义的和共产主义的文献
1反动的社会主义
封建的社会主义
法国和英国的贵族按照他们的历史地位所负的使命就是写一些抨击现代资产阶级社会的作品在法国的1830年七月革命和英国的改革运动 他们再一次被可恨的暴发户打败了从此就再谈不上严重的政治斗争了他们还能进行的只是文字斗争但是即使在文字方面也不可能重弹复辟时期的老调了为了激起同情贵族们不得不装模作样似乎他们已经不关心自身的利益只是为了被剥削的工人阶级的利益才去写对资产阶级的控诉书他们用来泄愤的手段是唱唱诅咒他们的新统治者的歌并向他叽叽咕咕地说一些或多或少凶险的预言
这样就产生了封建的社会主义半是挽歌半是谤文半是过去的回音半是未来的恫吓它有时也能用辛辣俏皮而尖刻的评论剌中资产阶级的心但是它由于完全不能理解现代历史的进程而总是令人感到可笑
为了拉拢人民贵族们把无产阶级的乞食袋当作旗帜来挥舞但是每当人民跟着他们走的时候都发现他们的臀部带有旧的封建纹章于是就哈哈大笑一哄而散
一部分法国正统派和青年英国都演过这出戏
封建主说他们的剥削方式和资产阶级的剥削不同那他们只是忘记了他们是在完全不同的目前已经过时的情况和条件下进行剥削的他们说在他们的统治下并没有出现过现代的无产阶级那他们只是忘记了现代的资产阶级正是他们的社会制度的必然产物
不过他们毫不掩饰自己的批评的反动性质他们控告资产阶级的主要罪状正是在于在资产阶级的统治下有一个将把整个旧社会制度炸毁的阶级发展起来
他们责备资产阶级与其说是因为它产生了无产阶级不如说是因为它产生了革命的无产阶级
因此在政治实践中他们参与对工人阶级采取的一切暴力措施在日常生活中他们违背自己的那一套冠冕堂皇的言词屈尊拾取金苹果不顾信义仁爱和名誉去做羊毛甜菜和烧洒的买卖
正如僧侣总是同封建主携手同行一样僧侣的社会主义也总是同封建的社会主义携手同行的
要给基督教禁欲主义涂上一层社会主义的色彩是再容易不过了基督教不是也激烈反对私有财产反对婚姻反对国家吗它不是提倡用行善和求乞独身和禁欲修道和礼拜来代替这一切吗基督教的社会主义只不过是僧侣用来使贵族的怨愤神圣的圣水罢了
小资产阶级的社会主义
封建贵族并不是被资产阶级所推翻的其生活条件在现代资产阶级社会里日益恶化和消失的唯一阶级中世纪的城关市民和小农等级是现代资产阶级的前身在工商业不很发达的国家里这个阶级还在新兴的资产阶级身旁勉强生存着
在现代文明已经发展的国家里形成了一个新的小资产阶级它摇摆于无产阶级和资产阶级之间并且作为资产阶级社会的补充部分不断地重新组成但是这一阶级的成员经常被竞争抛到无产阶级队伍里去而且随着大工业的发展他们甚至觉察到他们很快就会完全失去他们作为现代社会中一个独立部分的地位在商业工业和农业中很快就会被监工和雇员所代替
在农民阶级远远超过人口半数的国家例如在法国那些站在无产阶级方面反对资产阶级的著作家自然是用小资产阶级和小农的尺度去批判资产阶级制度的是从小资产阶级的立场出发替工人说话的这样就形成了小资产阶级的社会主义西斯蒙第不仅对法国而且对英国来说都是这类著作家的首领
这种社会主义非常透彻地分析了现代生产关系中的矛盾它揭穿了经济学家的虚伪的粉饰它确凿地证明了机器和分工的破坏作用资本和地产的积聚生产过剩危机小资产者和小农的必然没落无产阶级的贫困生产的无政府状态财富分配的极不平均各民族之间的毁灭性的工业战争以及旧风尚旧家庭关系和旧民族性的解体
但是这种社会主义按其实际内容来说或者是企图恢复旧的生产资料和交换手段从而恢复旧的所有制关系和旧的社会或者是企图重新把现代的生产资料和交换手段硬塞到已被它们突破而且必然被突破的旧的所有制关系的框子里去它在这两种场合都是反动的同时又是空想的
工业中的行会制度农业中的宗法经济这就是它的结论
这一思潮在它以后的发展中变成了一种怯懦的悲叹
德国的或真正的社会主义
法国的社会主义和共产主义的文献是在居于统治地位的资产阶级的压迫下产生的并且是同这种统治作斗争的文字表现这种文献被搬到德国的时候那里的资产阶级才刚刚开始进行反对封建专制制度的斗争
德国的哲学家半哲学家和美文学家贪婪地抓住了这种文献不过他们忘记了在这种著作从法国搬到德国的时候法国的生活条件却没有同时搬过去在德国的条件下法国的文献完全失去了直接实践的意义而只具有纯粹文献的形式它必然表现为关于真正的社会关于实现人的本质的无谓思辨这样第一次法国革命的要求在18世纪的德国哲学家看来不过是一般实践理性的要求而革命的法国资产阶级的意志的表现在他们心目中就是纯粹的意志本来的意志真正人的意志的规律
德国著作家的唯一工作就是把新的法国的思想同他们的旧的哲学信仰调和起来或者毋宁说就是从他们的哲学观点出发去掌握法国的思想
这种掌握就像掌握外国语一样是通过翻译的
大家知道僧侣们曾经在古代异教经典的手抄本上面写上荒诞的天主教圣徒传德国著作家对世俗的法国文献采取相反的作法他们在法国的原著下面写上自己的哲学胡说例如他们在法国人对货币关系的批判下面写上人的本质的外化在法国人对资产阶级国家的批判下面写上所谓抽象普遍物的统治的扬弃等等
这种在法国人的论述下面塞进自己哲学词句的做法他们称之为行动的哲学真正的社会主义德国的社会主义科学社会主义的哲学论证等等
法国的社会主义和共产主义的文献就这样被完全阉割了既然这种文献在德国人手里已不再表现一个阶级反对另一个阶级的斗争于是德国人就认为他们克服了法国人的片面性他们不代表真实的要求而代表真理的要求不代表无产者的利益而代表人的本质的利益即一般人的利益这种人不属于任何阶级根本不存在于现实界而只存在于云雾弥漫的哲学幻想的太空
这种曾经郑重其事地看待自己那一套拙劣的小学生作业并且大言不惭地加以吹嘘的德国社会主义现在渐渐失去了它的自炫博学的天真
德国的特别是普鲁士的资产阶级反对封建主和专制王朝的斗争一句话自由主义运动越来越严重了
于是真正的社会主义就得到了一个好机会把社会主义的要求同政治运动对立起来用诅咒异端邪说的传统办法诅咒自由主义诅咒代议制国家诅咒资产阶级的竞争资产阶级的新闻出版自由资产阶级的法资产阶级的自由和平等并且向人民群众大肆宣扬说什么在这个资产阶级运动中人民群众非但一无所得反而会失去一切德国的社会主义恰好忘记了法国的批判德国的社会主义是这种批判的可怜的回声是以现代的资产阶级社会以及相应的物质生活条件和相当的政治制度为前提的而这一切前提当时在德国正是尚待争取的
这种社会主义成了德意志各邦专制政府及其随从僧侣教员容克和官僚求之不得的吓唬来势汹汹的资产阶级的稻草人
这种社会主义是这些政府用来镇压德国工人起义的毒辣的皮鞭和枪弹的甜蜜的补充
既然真正的社会主义就这样成了这些政府对付德国资产阶级的武器那么它也就直接代表了一种反动的利益即德国小市民的利益在德国16世纪遗留下来的从那时起经常以不同形式重新出现的小资产阶级是现存制度的真实的社会基础
保存这个小资产阶级就是保存德国的现存制度这个阶级胆战心惊地从资产阶级的工业统治和政治统治那里等候着无可幸免的灭亡这一方面是由于资本的积聚另一方面是由于革命无产阶级的兴起在它看来真正的社会主义能起一箭双雕的作用真正的社会主义像瘟疫一样流行起来了
德国的社会主义者给自己的那几条干瘪的永恒真理披上一件用思辨的蛛丝织成的绣满华丽辞藻的花朵和浸透甜情蜜意的甘露的外衣这件光彩夺目的外衣只是使他们的货物在这些顾客中间增加销路罢了
同时德国的社会主义也越来越认识到自己的使命就是充当这种小市民的夸夸其谈的代言人
它宣布德意志民族是模范的民族德国小市民是模范的人它给这些小市民的每一种丑行都加上奥秘的高尚的社会主义的意义使之变成完全相反的东西它发展到最后就直接反对共产主义的野蛮破坏的倾向并且宣布自己是不偏不倚地超乎任何阶级斗争之上的现今在德国流行的一切所谓社会主义和共产主义的著作除了极少数的例外都属于这一类卑鄙龌龊的令人委靡的文献
2保守的或资产阶级的社会主义
资产阶级中的一部分人想要消除社会的弊病以便保障资产阶级社会的生存
这一部分人包括经济学家博爱主义者人道主义者劳动阶级状况改善派慈善事业组织者动物保护协会会员戒酒协会发起人以及形形色色的小改良家这种资产阶级的社会主义甚至被制成一些完整的体系
我们可以举蒲鲁东的贫困的哲学作为例子
社会主义的资产者愿意要现代社会的生存条件但是不要由这些条件必然产生的斗争和危险他们愿意要现存的社会但是不要那些使这个社会革命化和瓦解的因素他们愿意要资产阶级但是不要无产阶级在资产阶级看来它所统治的世界自然是最美好的世界资产阶级的社会主义把这种安慰人心的观念制成半套或整套的体系它要求无产阶级实现它的体系走进新的耶路撒冷其实它不过是要求无产阶级停留在现今的社会里但是要抛弃他们关于这个社会的可恶的观念
这种社会主义的另一种不够系统但是比较实际的形式力图使工人阶级厌弃一切革命运动硬说能给工人阶级带来好处的并不是这样或那样的政治改革而仅仅是物质生活条件即经济关系的改变但是这种社会主义所理解的物质生活条件的改变绝对不是只有通过革命的途径才能实现的资产阶级生产关系的废除而是一些在这种生产关系的基础上实行的行政上的改良因而丝毫不会改变资本和雇佣劳动的关系至多只能减少资产阶级的统治费用和简化它的财政管理
资产阶级的社会主义只有在它变成纯粹的演说辞令的时候才获得自己的适当的表现
自由贸易为了工人阶级的利益保护关税为了工人阶级的利益单身牢房为了工人阶级的利益这才是资产阶级的社会主义唯一认真说出的最后的话
资产阶级的社会主义就是这样一个论断资产者之为资产者是为了工人阶级的利益
3批判的空想的社会主义和共产主义
在这里我们不谈在现代一切大革命中表达过无产阶级要求的文献巴贝夫等人的著作
无产阶级在普遍激动的时代在推翻封建社会的时期直接实现自己阶级利益的最初尝试都不可避免地遭到了失败这是由于当时无产阶级本身还不够发展由于无产阶级解放的物质条件还没具备这些条件只是资产阶级时代的产物随着这些早期的无产阶级运动而出现的革命文献就其内容来说必然是反动的这种文献倡导普遍的禁欲主义和粗陋的平均主义
本来意义的社会主义和共产主义的体系圣西门傅立叶欧文等人的体系是在无产阶级和资产阶级之间的斗争还不发展的最初时期出现的关于这个时期我们在前面已经叙述过了资产阶级和无产阶级
诚然这些体系的发明家看到了阶级的对立以及占统治地位的社会本身中的瓦解因素的作用但是他们看不到无产阶级方面的任何历史主动性看不到它所特有的任何政治运动
由于阶级对立的发展是同工业的发展步调一致的所以这些发明家也不可能看到无产阶级解放的物质条件于是他们就去探求某种社会科学社会规律以便创造这些条件
社会的活动要由他们个人的发明活动来代替解放的历史条件要由幻想的条件来代替无产阶级的逐步组织成为阶级要由一种特意设计出来的社会组织来代替在他们看来今后的世界历史不过是宣传和实施他们的社会计划
诚然他们也意识到他们的计划主要是代表工人阶级这一受苦最深的阶级的利益在他们心目中无产阶级只是一个受苦最深的阶级
但是由于阶级斗争不发展由于他们本身的生活状况他们就以为自己是高高超乎这种阶级对立之上的他们要改善社会一切成员的生活状况甚至生活最优裕的成员也包括在内因此他们总是不加区别地向整个社会呼吁而且主要是向统治阶级呼吁他们以为人们只要理解他们的体系就会承认这种体系是最美好的社会的最美好的计划
因此他们拒绝一切政治行动特别是一切革命行动他们想通过和平的途径达到自己的目的并且企图通过一些小型的当然不会成功的试验通过示范的力量来为新的社会福音开辟道路
这种对未来社会的幻想的描绘在无产阶级还很不发展因而对本身的地位的认识还基于幻想的时候是同无产阶级对社会普遍改造的最初的本能的渴望相适应的
但是这些社会主义和共产主义的著作也含有批判的成分这些著作抨击现存社会的全部基础因此它们提供了启发工人觉悟的极为宝贵的材料它们关于未来社会的积极的主张例如消灭城乡对立消灭家庭消灭私人营利消灭雇佣劳动提倡社会和谐把国家变成纯粹的生产管理机构所有这些主张都只是表明要消灭阶级对立而这种阶级对立在当时刚刚开始发展它们所知道的只是这种对立的早期的不明显的不确定的形式因此这些主张本身还带有纯粹空想的性质
批判的空想的社会主义和共产主义的意义是同历史的发展成反比的阶级斗争越发展和越具有确定的形式这种超乎阶级斗争的幻想这种反对阶级斗争的幻想就越失去任何实践意义和任何理论根据所以虽然这些体系的创始人在许多方面是革命的但是他们的信徒总是组成一些反动的宗派这些信徒无视无产阶级的历史进展还是死守着老师们的旧观点因此他们一贯企图削弱阶级斗争调和对立他们还总是梦想用试验的办法来实现自己的社会空想创办单个的法伦斯泰尔建立国内移民区创立小伊加利亚即袖珍版的新耶路撒冷而为了建造这一切空中楼阁他们就不得不呼吁资产阶级发善心和慷慨解囊他们逐渐地堕落到上述反动的或保守的社会主义者的一伙中去了所不同的只是他们更加系统地卖弄学问狂热地迷信自己那一套社会科学的奇功异效
因此他们激烈地反对工人的一切政治运动认为这种运动只是由于盲目地不相信新福音才发生的
在英国有欧文主义者反对宪章派在法国有傅立叶主义者反对改革派
共产党人对各种反对党派的态度
看过第二章之后就可以了解共产党人同已经形成的工人政党的关系因而也就可以了解他们同英国宪章派和北美土地改革派的关系
共产党人为工人阶级的最近的目的和利益而斗争但是他们在当前的运动中同时代表运动的未来在法国共产党人同社会主义民主党联合起来反对保守的和激进的资产阶级但是并不因此放弃对那些从革命的传统中承袭下来的空谈和幻想采取批判态度的权利
在瑞士共产党人支持激进派但是并不忽略这个政党是由互相矛盾的分子组成的其中一部分是法国式的民主社会主义者一部分是激进的资产者
在波兰人中间共产党人支持那个把土地革命当作民族解放的条件的政党即发动过1846年克拉科夫起义的政党
在德国只要资产阶级采取革命的行动共产党就同它一起去反对专制君主制封建土地所有制和小市民的反动性
但是共产党一分钟也不忽略教育工人尽可能明确地意识到资产阶级和无产阶级的敌对的对立以便德国工人能够立刻利用资产阶级统治所必然带来的社会的和政治的条件作为反对资产阶级的武器以便在推翻德国的反动阶级之后立即开始反对资产阶级本身的斗争
共产党人把自己的主要注意力集中在德国因为德国正处在资产阶级革命的前夜因为同17世纪的英国和18世纪的法国相比德国将在整个欧洲文明更进步的条件下拥有发展得多的无产阶级去实现这个变革因而德国的资产阶级革命只能是无产阶级革命的直接序幕
总之共产党人到处都支持一切反对现存的社会制度和政治制度的革命运动
在所有这些运动中他们都强调所有制问题是运动的基本问题不管这个问题的发展程度怎样
最后共产党人到处都努力争取全世界民主政党之间的团结和协调
共产党人不屑于隐瞒自己的观点和意图他们公开宣布他们的目的只有用暴力推翻全部现存的社会制度才能达到让统治阶级在共产主义革命面前发抖吧无产者在这个革命中失去的只是锁链他们获得的将是整个世界
全世界无产者联合起来
""")
query = '福娘的物种'
nodes = rag_worker.retrieve_from_store_with_query(query)
build_prompt = rag_worker.build_prompt(query, nodes)
preview = rag_worker.generate_node_array_preview(nodes)
print(preview)
print(build_prompt)
print(nodes)
# vs = rag_worker.load_from_checkpoint('./good_man_vector_store')
# rag_worker.add_text_to_vector_store(r"I see that the (0.6.0) index persisted on disk contains: docstore.json, index_store.json and vector_store.json, but they don't seem to contain file paths or title metadata from the original documents, so maybe that's not captured and stored?")
# rag_worker.add_text_to_vector_store(r"Thanks! I'm trying to cluster (all) the vectors, then generate a description (label) for each cluster by sending (just) the vectors in each cluster to GPT to summarize, then associate the vectors with the original documents and classify each document by applying a sort of weighted sum of its cluster-labeled snippets. Not sure how useful that will be, but I want to try! I've got the vectors now (although I'm bit worried that the nested structure I'm getting them from might change without warning in the future!), and I'm able to cluster them, but I don't know how to associate the vectors (via their nodes) back to the original documents yet...")
# res = rag_worker.retrieve_from_store_with_query('cluster')
# rag_worker.save_to_checkpoint(checkpoint_dir = './good_man_vector_store')
# print(vs)

View File

@ -21,10 +21,32 @@ class TestKeyPatternManager(unittest.TestCase):
key = "sx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sess-wg61ZafYHpNz7FFwIH7HGZlbVqUVaeV5tatHCWpl"
key = "sess-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sess-wg61ZafYHpNz7FFwIH7HGZlbVqUVa5tatHCWpl"
key = "sess-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxx-xxxxxxxxxxxxxxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxx-xxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxx-xxxxxx-xxxxxxxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxx-xxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxx-xxxxxxxxxxxxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxx-xxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxx-xxxxxxxxxxxxxxxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sk-proj-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxx-xxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sk-proj-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxx-xxxxxxxx"
self.assertTrue(is_openai_api_key(key))
key = "sk-proj-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxx-xxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sk-proj-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxx"
self.assertFalse(is_openai_api_key(key))
key = "sk-proj-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxx-xxx啊xxxxxxx"
self.assertFalse(is_openai_api_key(key))

0
tests/test_rag.py Normal file
View File

View File

@ -1354,6 +1354,11 @@ async function multiplex_function_begin(multiplex_sel) {
call_plugin_via_name(_align_name_in_crazy_function_py);
return;
}
if (multiplex_sel === "智能召回 RAG") {
let _align_name_in_crazy_function_py = "Rag智能召回";
call_plugin_via_name(_align_name_in_crazy_function_py);
return;
}
}
async function run_multiplex_shift(multiplex_sel){
let key = multiplex_sel;

View File

@ -100,16 +100,19 @@ def ArgsGeneralWrapper(f):
user_name = request.username
else:
user_name = default_user_name
embed_model = get_conf("EMBEDDING_MODEL")
cookies.update({
'top_p': top_p,
'api_key': cookies['api_key'],
'llm_model': llm_model,
'embed_model': embed_model,
'temperature': temperature,
'user_name': user_name,
})
llm_kwargs = {
'api_key': cookies['api_key'],
'llm_model': llm_model,
'embed_model': embed_model,
'top_p': top_p,
'max_length': max_length,
'temperature': temperature,
@ -621,9 +624,12 @@ def load_chat_cookies():
}
}
)
EMBEDDING_MODEL = get_conf("EMBEDDING_MODEL")
return {
"api_key": API_KEY,
"llm_model": LLM_MODEL,
"embed_model": EMBEDDING_MODEL,
"customize_fn_overwrite": customize_fn_overwrite_,
}