bisheng-langchain 0.3.2.2__py3-none-any.whl → 0.3.3rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,11 @@ from bisheng_langchain.gpts.agent_types.llm_functions_agent import (
2
2
  get_openai_functions_agent_executor,
3
3
  get_qwen_local_functions_agent_executor
4
4
  )
5
+ from bisheng_langchain.gpts.agent_types.llm_react_agent import get_react_agent_executor
5
6
 
6
7
 
7
8
  __all__ = [
8
9
  "get_openai_functions_agent_executor",
9
- "get_qwen_local_functions_agent_executor"
10
+ "get_qwen_local_functions_agent_executor",
11
+ "get_react_agent_executor"
10
12
  ]
@@ -0,0 +1,171 @@
1
+ import operator
2
+ from typing import Annotated, Sequence, TypedDict, Union
3
+ from langchain.tools import BaseTool
4
+ from langchain_core.agents import AgentAction, AgentFinish
5
+ from langchain_core.messages import BaseMessage
6
+ from langchain_core.language_models import LanguageModelLike
7
+ from langgraph.graph import END, StateGraph
8
+ from langgraph.graph.state import CompiledStateGraph
9
+ from langgraph.prebuilt.tool_executor import ToolExecutor
10
+ from langgraph.utils import RunnableCallable
11
+ from langchain.agents import create_structured_chat_agent
12
+ from bisheng_langchain.gpts.prompts.react_agent_prompt import react_agent_prompt
13
+
14
+
15
+ def get_react_agent_executor(
16
+ tools: list[BaseTool],
17
+ llm: LanguageModelLike,
18
+ system_message: str,
19
+ interrupt_before_action: bool,
20
+ **kwargs
21
+ ):
22
+ prompt = react_agent_prompt
23
+ prompt = prompt.partial(assistant_message=system_message)
24
+ agent = create_structured_chat_agent(llm, tools, prompt)
25
+ agent_executer = create_agent_executor(agent, tools)
26
+ return agent_executer
27
+
28
+
29
+ def _get_agent_state(input_schema=None):
30
+ if input_schema is None:
31
+
32
+ class AgentState(TypedDict):
33
+ # The input string
34
+ input: str
35
+ # The list of previous messages in the conversation
36
+ chat_history: Sequence[BaseMessage]
37
+ # The outcome of a given call to the agent
38
+ # Needs `None` as a valid type, since this is what this will start as
39
+ agent_outcome: Union[AgentAction, AgentFinish, None]
40
+ # List of actions and corresponding observations
41
+ # Here we annotate this with `operator.add` to indicate that operations to
42
+ # this state should be ADDED to the existing values (not overwrite it)
43
+ intermediate_steps: Annotated[list[tuple[AgentAction, str]], operator.add]
44
+
45
+ else:
46
+
47
+ class AgentState(input_schema):
48
+ # The outcome of a given call to the agent
49
+ # Needs `None` as a valid type, since this is what this will start as
50
+ agent_outcome: Union[AgentAction, AgentFinish, None]
51
+ # List of actions and corresponding observations
52
+ # Here we annotate this with `operator.add` to indicate that operations to
53
+ # this state should be ADDED to the existing values (not overwrite it)
54
+ intermediate_steps: Annotated[list[tuple[AgentAction, str]], operator.add]
55
+
56
+ return AgentState
57
+
58
+
59
+ def create_agent_executor(
60
+ agent_runnable, tools, input_schema=None
61
+ ) -> CompiledStateGraph:
62
+ """This is a helper function for creating a graph that works with LangChain Agents.
63
+
64
+ Args:
65
+ agent_runnable (RunnableLike): The agent runnable.
66
+ tools (list): A list of tools to be used by the agent.
67
+ input_schema (dict, optional): The input schema for the agent. Defaults to None.
68
+
69
+ Returns:
70
+ The `CompiledStateGraph` object.
71
+ """
72
+
73
+ if isinstance(tools, ToolExecutor):
74
+ tool_executor = tools
75
+ else:
76
+ tool_executor = ToolExecutor(tools)
77
+
78
+ state = _get_agent_state(input_schema)
79
+
80
+ # Define logic that will be used to determine which conditional edge to go down
81
+
82
+ def should_continue(data):
83
+ # If the agent outcome is an AgentFinish, then we return `exit` string
84
+ # This will be used when setting up the graph to define the flow
85
+ if isinstance(data["agent_outcome"], AgentFinish):
86
+ return "end"
87
+ # Otherwise, an AgentAction is returned
88
+ # Here we return `continue` string
89
+ # This will be used when setting up the graph to define the flow
90
+ else:
91
+ return "continue"
92
+
93
+ def run_agent(data, config):
94
+ agent_outcome = agent_runnable.invoke(data, config)
95
+ return {"agent_outcome": agent_outcome}
96
+
97
+ async def arun_agent(data, config):
98
+ agent_outcome = await agent_runnable.ainvoke(data, config)
99
+ return {"agent_outcome": agent_outcome}
100
+
101
+ # Define the function to execute tools
102
+ def execute_tools(data, config):
103
+ # Get the most recent agent_outcome - this is the key added in the `agent` above
104
+ agent_action = data["agent_outcome"]
105
+ if not isinstance(agent_action, list):
106
+ agent_action = [agent_action]
107
+ output = tool_executor.batch(agent_action, config, return_exceptions=True)
108
+ return {
109
+ "intermediate_steps": [
110
+ (action, str(out)) for action, out in zip(agent_action, output)
111
+ ]
112
+ }
113
+
114
+ async def aexecute_tools(data, config):
115
+ # Get the most recent agent_outcome - this is the key added in the `agent` above
116
+ agent_action = data["agent_outcome"]
117
+ if not isinstance(agent_action, list):
118
+ agent_action = [agent_action]
119
+ output = await tool_executor.abatch(
120
+ agent_action, config, return_exceptions=True
121
+ )
122
+ return {
123
+ "intermediate_steps": [
124
+ (action, str(out)) for action, out in zip(agent_action, output)
125
+ ]
126
+ }
127
+
128
+ # Define a new graph
129
+ workflow = StateGraph(state)
130
+
131
+ # Define the two nodes we will cycle between
132
+ workflow.add_node("agent", RunnableCallable(run_agent, arun_agent))
133
+ workflow.add_node("tools", RunnableCallable(execute_tools, aexecute_tools))
134
+
135
+ # Set the entrypoint as `agent`
136
+ # This means that this node is the first one called
137
+ workflow.set_entry_point("agent")
138
+
139
+ # We now add a conditional edge
140
+ workflow.add_conditional_edges(
141
+ # First, we define the start node. We use `agent`.
142
+ # This means these are the edges taken after the `agent` node is called.
143
+ "agent",
144
+ # Next, we pass in the function that will determine which node is called next.
145
+ should_continue,
146
+ # Finally we pass in a mapping.
147
+ # The keys are strings, and the values are other nodes.
148
+ # END is a special node marking that the graph should finish.
149
+ # What will happen is we will call `should_continue`, and then the output of that
150
+ # will be matched against the keys in this mapping.
151
+ # Based on which one it matches, that node will then be called.
152
+ {
153
+ # If `tools`, then we call the tool node.
154
+ "continue": "tools",
155
+ # Otherwise we finish.
156
+ "end": END,
157
+ },
158
+ )
159
+
160
+ # We now add a normal edge from `tools` to `agent`.
161
+ # This means that after `tools` is called, `agent` node is called next.
162
+ workflow.add_edge("tools", "agent")
163
+
164
+ # Finally, we compile it!
165
+ # This compiles it into a LangChain Runnable,
166
+ # meaning you can use it as you would any other runnable
167
+ return workflow.compile()
168
+
169
+
170
+ if __name__ == "__main__":
171
+ pass
@@ -97,9 +97,9 @@ class BishengAssistant:
97
97
 
98
98
  # init agent executor
99
99
  agent_executor_params = self.assistant_params['agent_executor']
100
- agent_executor_type = agent_executor_params.pop('type')
100
+ self.agent_executor_type = agent_executor_params.pop('type')
101
101
  self.assistant = ConfigurableAssistant(
102
- agent_executor_type=agent_executor_type,
102
+ agent_executor_type=self.agent_executor_type,
103
103
  tools=tools,
104
104
  llm=llm,
105
105
  assistant_message=assistant_message,
@@ -119,7 +119,10 @@ class BishengAssistant:
119
119
  inputs.append(HumanMessage(content=chat_history[i]))
120
120
  inputs.append(AIMessage(content=chat_history[i+1]))
121
121
  inputs.append(HumanMessage(content=query))
122
- result = asyncio.run(self.assistant.ainvoke(inputs))
122
+ if self.agent_executor_type == 'get_react_agent_executor':
123
+ result = asyncio.run(self.assistant.ainvoke({"input": inputs[-1].content, "chat_history": inputs[:-1]}))
124
+ else:
125
+ result = asyncio.run(self.assistant.ainvoke(inputs))
123
126
  return result
124
127
 
125
128
 
@@ -127,14 +130,12 @@ if __name__ == "__main__":
127
130
  from langchain.globals import set_debug
128
131
 
129
132
  # set_debug(True)
130
- chat_history = []
131
- query = "请简要分析中科创达软件股份有限公司2019年聘任、解聘会计师事务的情况。"
132
- # chat_history = ['你好', '你好,有什么可以帮助你吗?', '福蓉科技股价多少?', '福蓉科技(股票代码:300049)的当前股价为48.67元。']
133
- # query = '去年这个时候的股价是多少?'
134
- # bisheng_assistant = BishengAssistant("config/base_scene.yaml")
133
+ # chat_history = []
134
+ # query = "600519、300750股价多少?"
135
+ chat_history = ['你好', '你好,有什么可以帮助你吗?', '福蓉科技股价多少?', '福蓉科技(股票代码:300049)的当前股价为48.67元。']
136
+ query = '今天是什么时候?去年这个时候的股价是多少?'
137
+ bisheng_assistant = BishengAssistant("config/base_scene.yaml")
135
138
  # bisheng_assistant = BishengAssistant("config/knowledge_scene.yaml")
136
- bisheng_assistant = BishengAssistant("config/rag_scene.yaml")
139
+ # bisheng_assistant = BishengAssistant("config/rag_scene.yaml")
137
140
  result = bisheng_assistant.run(query, chat_history=chat_history)
138
- for r in result:
139
- print(f'------------------')
140
- print(type(r), r)
141
+ print(result)
@@ -0,0 +1,68 @@
1
+ from typing import List, Union
2
+ from langchain_core.prompts.chat import (
3
+ ChatPromptTemplate,
4
+ HumanMessagePromptTemplate,
5
+ SystemMessagePromptTemplate,
6
+ MessagesPlaceholder
7
+ )
8
+ from langchain_core.prompts.prompt import PromptTemplate
9
+ from langchain_core.messages import FunctionMessage, SystemMessage, ToolMessage, AIMessage, HumanMessage, ChatMessage
10
+
11
+
12
+ system_temp = """
13
+ {assistant_message}
14
+
15
+ Respond to the human as helpfully and accurately as possible. You have access to the following tools:
16
+
17
+ {tools}
18
+
19
+ Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
20
+
21
+ Valid "action" values: "Final Answer" or {tool_names}
22
+
23
+ Provide only ONE action per $JSON_BLOB, as shown:
24
+
25
+ ```
26
+ {{{{
27
+ "action": $TOOL_NAME,
28
+ "action_input": $INPUT
29
+ }}}}
30
+ ```
31
+
32
+ Follow this format:
33
+
34
+ Question: input question to answer
35
+ Thought: consider previous and subsequent steps
36
+ Action:
37
+ ```
38
+ $JSON_BLOB
39
+ ```
40
+ Observation: action result
41
+ ... (repeat Thought/Action/Observation N times)
42
+ Thought: I know what to respond
43
+ Action:
44
+ ```
45
+ {{{{
46
+ "action": "Final Answer",
47
+ "action_input": "Final response to human"
48
+ }}}}
49
+
50
+ Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation
51
+ """
52
+
53
+ human_temp = """Question: {input}
54
+
55
+ Thought: {agent_scratchpad}
56
+ (reminder to respond in a JSON blob no matter what)"""
57
+
58
+
59
+ react_agent_prompt = ChatPromptTemplate(
60
+ input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools', 'assistant_message'],
61
+ optional_variables=['chat_history'],
62
+ input_types={'chat_history': List[Union[AIMessage, HumanMessage, ChatMessage, SystemMessage, FunctionMessage, ToolMessage]]},
63
+ messages=[
64
+ SystemMessagePromptTemplate.from_template(system_temp),
65
+ MessagesPlaceholder(variable_name='chat_history', optional=True),
66
+ HumanMessagePromptTemplate.from_template(human_temp)
67
+ ]
68
+ )
@@ -97,6 +97,7 @@ class BishengRetrievalQA(Chain):
97
97
  max_content: int = 15000,
98
98
  sort_by_source_and_index: bool = False,
99
99
  callbacks: Callbacks = None,
100
+ return_source_documents: bool = False,
100
101
  **kwargs: Any,
101
102
  ) -> BishengRetrievalQA:
102
103
  bisheng_rag_tool = BishengRAGTool(
@@ -111,6 +112,7 @@ class BishengRetrievalQA(Chain):
111
112
  return cls(
112
113
  bisheng_rag_tool=bisheng_rag_tool,
113
114
  callbacks=callbacks,
115
+ return_source_documents=return_source_documents,
114
116
  **kwargs,
115
117
  )
116
118
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bisheng-langchain
3
- Version: 0.3.2.2
3
+ Version: 0.3.3rc1
4
4
  Summary: bisheng langchain modules
5
5
  Home-page: https://github.com/dataelement/bisheng
6
6
  Author: DataElem
@@ -28,7 +28,7 @@ Requires-Dist: pydantic ==1.10.13
28
28
  Requires-Dist: pymupdf ==1.23.8
29
29
  Requires-Dist: shapely ==2.0.2
30
30
  Requires-Dist: filetype ==1.2.0
31
- Requires-Dist: langgraph ==0.0.30
31
+ Requires-Dist: langgraph ==0.0.50
32
32
  Requires-Dist: openai ==1.14.3
33
33
  Requires-Dist: langchain-openai ==0.1.0
34
34
  Requires-Dist: llama-index ==0.9.48
@@ -70,20 +70,22 @@ bisheng_langchain/embeddings/interface/__init__.py,sha256=GNY3tibpRxpAdAfSvQmXBK
70
70
  bisheng_langchain/embeddings/interface/types.py,sha256=VdurbtsnjCPdlOjPFcK2Mg6r9bJYYHb3tepvkk-y3nM,461
71
71
  bisheng_langchain/embeddings/interface/wenxin.py,sha256=5d9gI4enmfkD80s0FHKiDt33O0mwM8Xc5WTubnMUy8c,3104
72
72
  bisheng_langchain/gpts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- bisheng_langchain/gpts/assistant.py,sha256=OEB9HA-FpNKGOviVoafld4MHDIEQS5u9AU0QlMuJ-po,5344
73
+ bisheng_langchain/gpts/assistant.py,sha256=lObPDRSSzRcz6jijj76zr9dtfWOIztCaII429BPTHsU,5444
74
74
  bisheng_langchain/gpts/auto_optimization.py,sha256=WNsC19rgvuDYQlSIaYThq5RqCbuobDbzCwAJW4Ksw0c,3626
75
75
  bisheng_langchain/gpts/auto_tool_selected.py,sha256=21WETf9o0YS-QEBwv3mmZRObKWszefQkXEqAA6KzoaM,1582
76
76
  bisheng_langchain/gpts/load_tools.py,sha256=LiiK1OqFu7Ki-F_Rhfi1rgp0wBQCSrTDdqsgwciTOIU,8099
77
77
  bisheng_langchain/gpts/message_types.py,sha256=7EJOx62j9E1U67jxWgxE_I7a8IjAvvKANknXkD2gFm0,213
78
78
  bisheng_langchain/gpts/utils.py,sha256=t3YDxaJ0OYd6EKsek7PJFRYnsezwzEFK5oVU-PRbu5g,6671
79
- bisheng_langchain/gpts/agent_types/__init__.py,sha256=bg0zlTYGfNXoSBqcICHlzNpVQbejMYeyji_dzvP5qQ0,261
79
+ bisheng_langchain/gpts/agent_types/__init__.py,sha256=88tFt1GfrfIqa4hCg0cMJk7rTeUmCSSdiVhR41CW4rM,381
80
80
  bisheng_langchain/gpts/agent_types/llm_functions_agent.py,sha256=IXg5u8dSk-FcLvjrvvLcN5revGccXylXkD73ZWhaDWs,8715
81
+ bisheng_langchain/gpts/agent_types/llm_react_agent.py,sha256=W6IJMwoFUj_a2cXZ_nXOpzaHBjP5IBrFxRTSejNVi9A,6678
81
82
  bisheng_langchain/gpts/prompts/__init__.py,sha256=pOnXvk6_PjqAoLrh68sI9o3o6znKGxoLMVFP-0XTCJo,704
82
83
  bisheng_langchain/gpts/prompts/assistant_prompt_base.py,sha256=Q69qWxtwaeGPPwMWXQ44OsQPg7wHB7nYT17wbqQe3kM,57
83
84
  bisheng_langchain/gpts/prompts/assistant_prompt_cohere.py,sha256=GLQ77oXqSlE7Xes2ObsFsNon5nOJOCRhQOKE5bUpgaI,2421
84
85
  bisheng_langchain/gpts/prompts/assistant_prompt_opt.py,sha256=TZsRK4XPMrUhGg0PoMyiE3wE-aG34UmlVflkCl_c0QI,4151
85
86
  bisheng_langchain/gpts/prompts/breif_description_prompt.py,sha256=w4A5et0jB-GkxEMQBp4i6GKX3RkVeu7NzWEjOZZAicM,5336
86
87
  bisheng_langchain/gpts/prompts/opening_dialog_prompt.py,sha256=VVF0JLHtetupVB0kabiFHWDHlQaa4nFLcbYXgIBA3nw,5965
88
+ bisheng_langchain/gpts/prompts/react_agent_prompt.py,sha256=YGaO4S0r9AZhzt9Idyiw2mcd5QH1GLIIGc2oAN2YKdE,1976
87
89
  bisheng_langchain/gpts/prompts/select_tools_prompt.py,sha256=AyvVnrLEsQy7RHuGTPkcrMUxgA98Q0TzF-xweoc7GyY,1400
88
90
  bisheng_langchain/gpts/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
91
  bisheng_langchain/gpts/tools/api_tools/__init__.py,sha256=CkEjgIFM4GIv86V1B7SsFLaB6M86c54QuO8wIRizUZ8,1608
@@ -107,7 +109,7 @@ bisheng_langchain/input_output/__init__.py,sha256=sW_GB7MlrHYsqY1Meb_LeimQqNsMz1
107
109
  bisheng_langchain/input_output/input.py,sha256=I5YDmgbvvj1o2lO9wi8LE37wM0wP5jkhUREU32YrZMQ,1094
108
110
  bisheng_langchain/input_output/output.py,sha256=6U-az6-Cwz665C2YmcH3SYctWVjPFjmW8s70CA_qphk,11585
109
111
  bisheng_langchain/rag/__init__.py,sha256=Rm_cDxOJINt0H4bOeUo3JctPxaI6xKKXZcS-R_wkoGs,198
110
- bisheng_langchain/rag/bisheng_rag_chain.py,sha256=pbvaLuAwBWyGyvi0qBcqrOz9HScEPfpfEE9GWobVv-M,5891
112
+ bisheng_langchain/rag/bisheng_rag_chain.py,sha256=2GMDUPJaW-D7tpOQ9qPt2vGZwmcXBS0UrcibO7J2S1g,5999
111
113
  bisheng_langchain/rag/bisheng_rag_pipeline.py,sha256=neoBK3TtuQ07_WeuJCzYlvtsDQNepUa_68NT8VCgytw,13749
112
114
  bisheng_langchain/rag/bisheng_rag_pipeline_v2.py,sha256=iOoF7mbLp9qDGPsV0fEmgph_Ba8VnECYvCPebXk8xmo,16144
113
115
  bisheng_langchain/rag/bisheng_rag_tool.py,sha256=8M59rQqUGS7b1GH_pjNwcqJa2HikK3B4ZqWl59ZCUJY,13113
@@ -150,7 +152,7 @@ bisheng_langchain/vectorstores/__init__.py,sha256=zCZgDe7LyQ0iDkfcm5UJ5NxwKQSRHn
150
152
  bisheng_langchain/vectorstores/elastic_keywords_search.py,sha256=Pm1rS50GJ0HWbjBsFDgs28SVuVbjGSRPOor6yJlnE7w,13347
151
153
  bisheng_langchain/vectorstores/milvus.py,sha256=lrnezKnYXhyH5M1g3a-Mcwpj9mwzAj44TKmzyUXlQYY,36297
152
154
  bisheng_langchain/vectorstores/retriever.py,sha256=hj4nAAl352EV_ANnU2OHJn7omCH3nBK82ydo14KqMH4,4353
153
- bisheng_langchain-0.3.2.2.dist-info/METADATA,sha256=bpPBmNOC74Lta6zplA_rXDTiNBJwGFabRjNiKAYcJnU,2486
154
- bisheng_langchain-0.3.2.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
155
- bisheng_langchain-0.3.2.2.dist-info/top_level.txt,sha256=Z6pPNyCo4ihyr9iqGQbH8sJiC4dAUwA_mAyGRQB5_Fs,18
156
- bisheng_langchain-0.3.2.2.dist-info/RECORD,,
155
+ bisheng_langchain-0.3.3rc1.dist-info/METADATA,sha256=g-nXaJGFy9IawsFS-md6KPFWVSn7RsZ4c6aK_DPkIqg,2487
156
+ bisheng_langchain-0.3.3rc1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
157
+ bisheng_langchain-0.3.3rc1.dist-info/top_level.txt,sha256=Z6pPNyCo4ihyr9iqGQbH8sJiC4dAUwA_mAyGRQB5_Fs,18
158
+ bisheng_langchain-0.3.3rc1.dist-info/RECORD,,