From 553120d7e030e724b227a4a496c02d4f15d921ca Mon Sep 17 00:00:00 2001 From: Tom Hammel Date: Tue, 24 Mar 2026 14:46:35 +0100 Subject: [PATCH 1/4] Add ollama for local llms to handover documentation tool --- aas_editor/tools/handover_doc_llm/README.md | 60 +++++++----- aas_editor/tools/handover_doc_llm/config.py | 35 ++++++- .../handover_documentation_tool.py | 93 +++++++++++++++++-- pyproject.toml | 1 + 4 files changed, 154 insertions(+), 35 deletions(-) diff --git a/aas_editor/tools/handover_doc_llm/README.md b/aas_editor/tools/handover_doc_llm/README.md index 4a9a6f30..d295d156 100644 --- a/aas_editor/tools/handover_doc_llm/README.md +++ b/aas_editor/tools/handover_doc_llm/README.md @@ -1,36 +1,54 @@ # Handover Documentation tool -The Handover Documentation Tool is a extension of the AAS Manager that allows users to generate a Handover Documentation from a given PDF file with the usage of LLMs. +The Handover Documentation Tool is an extension of the AAS Manager that allows users to generate a Handover Documentation Submodel from a given PDF file with the usage of LLMs. + +## Usage -Usage: - Select the "Handover Documentation tool" from the "Tools" menu. - In the opened dialog, select the LLM provider and model you want to use. -- Provide your API key for the selected LLM provider. +- For cloud providers: provide your API key. For Ollama: optionally provide a custom base URL. +- Select the embedding provider to use for RAG on large documents. For Ollama embeddings, optionally specify a custom embedding model and base URL. - Drag and drop or select the PDF file you want to use. - Check and adjust the extracted data if necessary. -- The Handover Documentation will be added to the current AAS file. +- The Handover Documentation Submodel will be added to the current AAS file or a new file. -The tool uses the [LangChain](https://python.langchain.com/docs/) library for the interaction with LLMs. -It splits the PDF into smaller chunks and uses vector stores to store the chunks. -After that, it uses a RAG chain to query the LLM with the data. +## How it works +The tool uses the [LangChain](https://python.langchain.com/docs/) library for interaction with LLMs. +For large documents it splits the PDF into smaller chunks, stores them in a FAISS vector store, and uses a RAG chain to query the LLM with the relevant context. Small documents are passed directly to the LLM without RAG. -The tool currently supports the following LLM providers: -- OpenAI -- Anthropic -- Google Vertex -- Groq -- Mistral AI +## Supported LLM providers -Disclaimer: The Handover Documentation tool relies on Large Language Models for information extraction. LLMs may produce incomplete, inaccurate, or inconsistent results. Always verify the extracted documentation before use in production or compliance-relevant contexts. +| Provider | Type | Requires | +|----------|------|----------| +| OpenAI | Cloud API | API key | +| Anthropic | Cloud API | API key | +| Google Vertex | Cloud API | API key | +| Groq | Cloud API | API key | +| Mistral AI | Cloud API | API key | +| **Ollama** | **Local** | [Ollama](https://ollama.com) installed & running | +### Using Ollama (local LLMs) +1. Install [Ollama](https://ollama.com) and start the server. +2. Pull a model, e.g.: `ollama pull llama3.2` +3. Select **Ollama** as the LLM provider in the dialog. +4. Enter the model name (e.g. `llama3.2`). Leave the Base URL empty to use the default (`http://localhost:11434`). +5. Select **Ollama** as the embedding provider. Optionally enter a custom embedding model name (default: `nomic-embed-text`) and base URL. +6. Pull the embedding model: `ollama pull nomic-embed-text` -The Handover Documentation Tool is a extension of the AAS Manager that allows users to generate a Handover Documentation Submodel from a given PDF file with the usage of LLMs. +Recommended models for this task: `llama3.2`, `qwen2.5`, `mistral`. -Usage: -- Select the LLM provider and model you want to use. -- Provide your API key for the selected LLM provider. -- Drag and drop or select the PDF file you want to use. -- Check and adjust the extracted data if necessary. -- The Handover Documentation Submodel will be added to the current AAS file or a new file. +## Supported embedding providers + +| Provider | Type | Notes | +|----------|------|-------| +| HuggingFace | Local | Default; uses `sentence-transformers/all-mpnet-base-v2`; no key required | +| OpenAI | Cloud API | Requires a separate OpenAI API key | +| Ollama | Local | Custom model (default: `nomic-embed-text`) and base URL configurable | + +The embedding provider is selected automatically based on the chosen LLM provider but can be changed manually. + +## Disclaimer + +The Handover Documentation tool relies on Large Language Models for information extraction. LLMs may produce incomplete, inaccurate, or inconsistent results. Always verify the extracted documentation before use in production or compliance-relevant contexts. diff --git a/aas_editor/tools/handover_doc_llm/config.py b/aas_editor/tools/handover_doc_llm/config.py index c8d3f871..051c82b1 100644 --- a/aas_editor/tools/handover_doc_llm/config.py +++ b/aas_editor/tools/handover_doc_llm/config.py @@ -23,12 +23,24 @@ def _init_mistral_chat(model, key): return ChatMistralAI(model=model, api_key=key) -def _init_hf_embeddings(_key): +def _init_ollama_chat(model, key): + from langchain_ollama import ChatOllama + base_url = key if key else "http://localhost:11434" + return ChatOllama(model=model, base_url=base_url) + + +def _init_ollama_embeddings(key, model="nomic-embed-text"): + from langchain_ollama import OllamaEmbeddings + base_url = key if key else "http://localhost:11434" + return OllamaEmbeddings(model=model or "nomic-embed-text", base_url=base_url) + + +def _init_hf_embeddings(_key, _model=None): from langchain_huggingface import HuggingFaceEmbeddings return HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2") -def _init_openai_embeddings(key): +def _init_openai_embeddings(key, _model=None): from langchain_openai import OpenAIEmbeddings return OpenAIEmbeddings(api_key=key) @@ -68,12 +80,25 @@ def _init_openai_embeddings(key): "default_model": "mistral-large-latest", "init": _init_mistral_chat, }, + "Ollama": { + "default_model": "llama3.2", + "init": _init_ollama_chat, + }, } EMBEDDING_PROVIDERS = { - "default": _init_hf_embeddings, - "huggingface": _init_hf_embeddings, - "OpenAI": _init_openai_embeddings, + "HuggingFace": { + "default_model": "", + "init": _init_hf_embeddings, + }, + "OpenAI": { + "default_model": "", + "init": _init_openai_embeddings, + }, + "Ollama": { + "default_model": "nomic-embed-text", + "init": _init_ollama_embeddings, + }, } PROMPT = """ diff --git a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py index 7ad8132f..5aebd451 100644 --- a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py +++ b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py @@ -53,7 +53,8 @@ class PdfProcessingThread(QThread): show_answer_dialog = pyqtSignal(str) def __init__(self, file_path: str, llm_provider: str, llm_model: str, api_key: str, - pages_front: str, pages_end: str): + pages_front: str, pages_end: str, embedding_provider: str = "HuggingFace", + embedding_api_key: str = "", embedding_model: str = ""): super().__init__() self.file_path = file_path self.llm_provider = llm_provider @@ -61,12 +62,14 @@ def __init__(self, file_path: str, llm_provider: str, llm_model: str, api_key: s self.api_key = api_key self.pages_front = pages_front self.pages_end = pages_end + self.embedding_provider = embedding_provider + self.embedding_api_key = embedding_api_key + self.embedding_model = embedding_model - def init_embeddings(self, provider: str = "default", api_key: str = None): - if provider in EMBEDDING_PROVIDERS: - return EMBEDDING_PROVIDERS[provider](api_key) - else: - return EMBEDDING_PROVIDERS["default"](api_key) + def init_embeddings(self, provider: str = "HuggingFace", api_key: str = None, model: str = ""): + if provider not in EMBEDDING_PROVIDERS: + provider = "HuggingFace" + return EMBEDDING_PROVIDERS[provider]["init"](api_key, model) def init_llm(self, provider: str, chat_model: str, api_key: str): if provider in LLM_PROVIDERS: @@ -75,6 +78,7 @@ def init_llm(self, provider: str, chat_model: str, api_key: str): raise ValueError(f"Unsupported LLM provider: {provider}") def _fix_json_with_llm(self, llm, raw_answer: str, schema: dict, error_msg: str) -> str: + from langchain_core.prompts import ChatPromptTemplate fix_prompt = ChatPromptTemplate.from_messages([ ("system", "You are a JSON correction assistant. " @@ -141,7 +145,7 @@ def run(self): logging.info("Using RAG approach for document processing.") print("Using RAG approach for document processing.") - embeddings = self.init_embeddings(self.llm_provider, self.api_key) + embeddings = self.init_embeddings(self.embedding_provider, self.embedding_api_key, self.embedding_model) splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100) splits = splitter.split_documents(docs) vector_store = FAISS.from_documents(splits, embeddings) @@ -259,7 +263,28 @@ def __init__(self, parent=None): self.apiKeyLineEdit = QLineEdit(self, toolTip="API Key for LLM service", placeholderText="Enter API Key here", echoMode=QLineEdit.EchoMode.Password) + self.apiKeyLabel = QLabel("API Key:", self) self.modelLineEdit = QLineEdit(self, toolTip="Choose model to use") + self.embeddingApiKeyLabel = QLabel("Embedding API Key:", self) + self.embeddingApiKeyLineEdit = QLineEdit(self) + self.embeddingApiKeyLineEdit.setPlaceholderText("Enter API Key here") + self.embeddingApiKeyLineEdit.setEchoMode(QLineEdit.EchoMode.Password) + self.embeddingApiKeyLineEdit.setToolTip("API Key for the embedding provider") + self.embeddingApiKeyLabel.hide() + self.embeddingApiKeyLineEdit.hide() + + self.embeddingModelLabel = QLabel("Embedding Model:", self) + self.embeddingModelLineEdit = QLineEdit(self) + self.embeddingModelLineEdit.setToolTip( + "Ollama embedding model to use for RAG. Leave empty for default (nomic-embed-text).\n" + "Pull the model first, e.g.: ollama pull nomic-embed-text") + self.embeddingModelLabel.hide() + self.embeddingModelLineEdit.hide() + + self.embeddingProviderComboBox = QComboBox(self, toolTip="Embedding provider used for RAG on large documents") + self.embeddingProviderComboBox.addItems([k for k in EMBEDDING_PROVIDERS.keys()]) + self.embeddingProviderComboBox.currentIndexChanged.connect(self.embedding_provider_changed) + self.providerLineEdit = QComboBox(self, toolTip="LLM Provider", currentIndexChanged=self.provider_changed) self.providerLineEdit.addItems([k for k in LLM_PROVIDERS.keys()]) @@ -324,7 +349,10 @@ def _initLayout(self): model_h.addWidget(self.model_info_label) llm_form.addRow(QLabel("LLM Model:"), model_container) - llm_form.addRow(QLabel("API Key:"), self.apiKeyLineEdit) + llm_form.addRow(self.apiKeyLabel, self.apiKeyLineEdit) + llm_form.addRow(QLabel("Embeddings:"), self.embeddingProviderComboBox) + llm_form.addRow(self.embeddingModelLabel, self.embeddingModelLineEdit) + llm_form.addRow(self.embeddingApiKeyLabel, self.embeddingApiKeyLineEdit) gb_llm.setLayout(llm_form) layout.addWidget(gb_llm) @@ -387,6 +415,9 @@ def processPdf(self, file: str): self.apiKeyLineEdit.text(), pages_front=self.pagesFrontLineEdit.text(), pages_end=self.pagesEndLineEdit.text(), + embedding_provider=self.embeddingProviderComboBox.currentText(), + embedding_api_key=self.embeddingApiKeyLineEdit.text(), + embedding_model=self.embeddingModelLineEdit.text(), ) self.processingThread.processing_error.connect(self.on_processing_error) @@ -406,7 +437,51 @@ def on_processing_error(self, error_message): self.cleanup_thread() def provider_changed(self): - self.modelLineEdit.setPlaceholderText(LLM_PROVIDERS[self.providerLineEdit.currentText()]["default_model"]) + provider = self.providerLineEdit.currentText() + self.modelLineEdit.setPlaceholderText(LLM_PROVIDERS[provider]["default_model"]) + if provider == "Ollama": + self.apiKeyLabel.setText("Base URL:") + self.apiKeyLineEdit.setPlaceholderText("http://localhost:11434 (leave empty for default)") + self.apiKeyLineEdit.setEchoMode(QLineEdit.EchoMode.Normal) + self.apiKeyLineEdit.setToolTip("Base URL of the Ollama server (leave empty for default)") + self.embeddingProviderComboBox.setCurrentText("Ollama") + else: + self.apiKeyLabel.setText("API Key:") + self.apiKeyLineEdit.setPlaceholderText("Enter API Key here") + self.apiKeyLineEdit.setEchoMode(QLineEdit.EchoMode.Password) + self.apiKeyLineEdit.setToolTip("API Key for LLM service") + if provider == "OpenAI": + self.embeddingProviderComboBox.setCurrentText("OpenAI") + else: + self.embeddingProviderComboBox.setCurrentText("HuggingFace") + + def embedding_provider_changed(self): + provider = self.embeddingProviderComboBox.currentText() + if provider == "OpenAI": + self.embeddingApiKeyLabel.setText("Embedding API Key:") + self.embeddingApiKeyLineEdit.setPlaceholderText("Enter OpenAI API Key") + self.embeddingApiKeyLineEdit.setEchoMode(QLineEdit.EchoMode.Password) + self.embeddingApiKeyLineEdit.setToolTip("OpenAI API Key for embeddings") + self.embeddingApiKeyLabel.show() + self.embeddingApiKeyLineEdit.show() + self.embeddingModelLabel.hide() + self.embeddingModelLineEdit.hide() + elif provider == "Ollama": + self.embeddingApiKeyLabel.setText("Embedding Base URL:") + self.embeddingApiKeyLineEdit.setPlaceholderText("http://localhost:11434 (leave empty for default)") + self.embeddingApiKeyLineEdit.setEchoMode(QLineEdit.EchoMode.Normal) + self.embeddingApiKeyLineEdit.setToolTip("Base URL of the Ollama server for embeddings") + self.embeddingApiKeyLabel.show() + self.embeddingApiKeyLineEdit.show() + self.embeddingModelLabel.show() + self.embeddingModelLineEdit.show() + self.embeddingModelLineEdit.setPlaceholderText( + EMBEDDING_PROVIDERS["Ollama"]["default_model"]) + else: + self.embeddingApiKeyLabel.hide() + self.embeddingApiKeyLineEdit.hide() + self.embeddingModelLabel.hide() + self.embeddingModelLineEdit.hide() def closeEvent(self, event): if self.processingThread and self.processingThread.isRunning(): diff --git a/pyproject.toml b/pyproject.toml index 9dc2d4c4..dd92f692 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ dependencies = [ "langchain-groq==1.1.1", "langchain-google-vertexai==3.2.1", "langchain-mistralai==1.1.1", + "langchain-ollama==0.3.2", "langchain-community==0.4.1", "pypdf==6.6.0", "sentence-transformers==5.2.0", From f3804ef97910efaa6a167569c662c9dc964a7c70 Mon Sep 17 00:00:00 2001 From: Tom Hammel Date: Tue, 5 May 2026 13:00:54 +0200 Subject: [PATCH 2/4] Update langchain-ollama dependency to version 1.0.0 This fixes pip install errors --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index dd92f692..603b1a86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ dependencies = [ "langchain-groq==1.1.1", "langchain-google-vertexai==3.2.1", "langchain-mistralai==1.1.1", - "langchain-ollama==0.3.2", + "langchain-ollama==1.0.0", "langchain-community==0.4.1", "pypdf==6.6.0", "sentence-transformers==5.2.0", From ec18f5e892080dd51ad72b5805be67fc25313a69 Mon Sep 17 00:00:00 2001 From: Tom Hammel Date: Wed, 13 May 2026 14:39:26 +0200 Subject: [PATCH 3/4] Enhance Ollama chat initialization with optional schema parameter and update document version handling --- aas_editor/tools/handover_doc_llm/config.py | 31 ++++++++++++------- .../documentation_generator.py | 10 +++--- .../handover_documentation_tool.py | 10 +++--- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/aas_editor/tools/handover_doc_llm/config.py b/aas_editor/tools/handover_doc_llm/config.py index 051c82b1..00530a2c 100644 --- a/aas_editor/tools/handover_doc_llm/config.py +++ b/aas_editor/tools/handover_doc_llm/config.py @@ -23,10 +23,13 @@ def _init_mistral_chat(model, key): return ChatMistralAI(model=model, api_key=key) -def _init_ollama_chat(model, key): +def _init_ollama_chat(model, key, schema=None): from langchain_ollama import ChatOllama base_url = key if key else "http://localhost:11434" - return ChatOllama(model=model, base_url=base_url) + kwargs = {"model": model, "base_url": base_url} + if schema is not None: + kwargs["format"] = schema + return ChatOllama(**kwargs) def _init_ollama_embeddings(key, model="nomic-embed-text"): @@ -61,7 +64,7 @@ def _init_openai_embeddings(key, _model=None): LLM_PROVIDERS = { "OpenAI": { - "default_model": "gpt-40-mini", + "default_model": "gpt-4o-mini", "init": _init_openai_chat, }, "Anthropic": { @@ -189,7 +192,10 @@ def _init_openai_embeddings(key, _model=None): "required": ["classId"], "additionalProperties": false, "properties": { - "classId": { "type": "string", "minLength": 1 } + "classId": { + "type": "string", + "enum": ["01-01", "02-01", "02-02", "02-03", "02-04", "03-01", "03-02", "03-03", "03-04", "03-05", "03-06", "04-01"] + } } }, "documentVersion": { @@ -201,19 +207,20 @@ def _init_openai_embeddings(key, _model=None): ], "additionalProperties": false, "properties": { - "title": { "type": "object", "additionalProperties": { "type": "string" } }, - "subTitle": { "type": "object", "additionalProperties": { "type": "string" } }, - "description": { "type": "object", "additionalProperties": { "type": "string" } }, - "keyWords": { "type": "object", "additionalProperties": { "type": "string" } }, - "version": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]+)*$" }, + "title": { "type": "object", "minProperties": 1, "additionalProperties": { "type": "string", "minLength": 1 } }, + "subTitle": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } }, + "description": { "type": "object", "minProperties": 1, "additionalProperties": { "type": "string", "minLength": 1 } }, + "keyWords": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } }, + "version": { "type": "string", "minLength": 1 }, "language": { "type": "array", - "items": { "type": "string", "minLength": 2 }, + "items": { "type": "string", "minLength": 2, "maxLength": 3, "pattern": "^[a-z]{2,3}$" }, "minItems": 1, + "maxItems": 10, "uniqueItems": true }, - "statusSetDate": { "type": "string", "format": "date-time" }, - "statusValue": { "type": "string", "minLength": 1 }, + "statusSetDate": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, + "statusValue": { "type": "string", "enum": ["InReview", "Released"] }, "organizationShortName": { "type": "string", "minLength": 1 }, "organizationOfficialName": { "type": "string", "minLength": 1 } } diff --git a/aas_editor/tools/handover_doc_llm/documentation_generator.py b/aas_editor/tools/handover_doc_llm/documentation_generator.py index 0778aff9..ec128c4d 100644 --- a/aas_editor/tools/handover_doc_llm/documentation_generator.py +++ b/aas_editor/tools/handover_doc_llm/documentation_generator.py @@ -122,9 +122,9 @@ def json2document(json_str: str): from aas_editor.tools.handover_doc_llm.handover_submodel import HandoverDocumentation documentID = HandoverDocumentation.Documents.Documents_item.DocumentIds.Documentids_item( - documentIsPrimary=True, #TODO: Fix me + documentIsPrimary=True, documentDomainId=obj['document']['documentId'].get('documentDomainId', ''), - documentIdentifier=obj['document']['documentId'].get('valueId', '')) + documentIdentifier=obj['document']['documentId'].get('documentIdentifier', '')) classId = obj['document']['documentClassification'].get('classId', '') documentClassification = HandoverDocumentation.Documents.Documents_item.DocumentClassifications.Documentclassifications_item( @@ -146,14 +146,14 @@ def json2document(json_str: str): documentVersion = HandoverDocumentation.Documents.Documents_item.DocumentVersions.Documentversions_item( language=obj['document']['documentVersion'].get('language', ['']), - version=obj['document']['documentVersion'].get('documentVersionId', ''), + version=obj['document']['documentVersion'].get('version', ''), title=obj['document']['documentVersion'].get('title'), subtitle=obj['document']['documentVersion'].get('subTitle'), description_=obj['document']['documentVersion'].get('description'), keyWords=obj['document']['documentVersion'].get('keyWords'), statusSetDate=statusSetDate, statusValue=obj['document']['documentVersion'].get('statusValue', ''), - organizationShortName=obj['document']['documentVersion'].get('organizationName', ''), + organizationShortName=obj['document']['documentVersion'].get('organizationShortName', ''), organizationOfficialName=obj['document']['documentVersion'].get('organizationOfficialName', ''), digitalFiles=HandoverDocumentation.Documents.Documents_item.DocumentVersions.Documentversions_item.DigitalFiles([digitalFile]) ) @@ -205,7 +205,7 @@ def documents2handover_documentation(documents, id_: str = "0"): "title": {"de":"Datensheet", "en":"Datasheet"}, "subTitle": {}, "description": {"de": "Datensheet für 222-101", "en":"Datasheet for 222-101"}, - "keyWords": {"de": ["example_company", "222-101"], "en": ["example_company", "222-101"]}, + "keyWords": {"de": "222-101", "en": "222-101"}, "statusSetDate": "2025-09-22", "statusValue": "Released", "organizationShortName": "example_company", diff --git a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py index 5aebd451..80c004f4 100644 --- a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py +++ b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py @@ -71,8 +71,10 @@ def init_embeddings(self, provider: str = "HuggingFace", api_key: str = None, mo provider = "HuggingFace" return EMBEDDING_PROVIDERS[provider]["init"](api_key, model) - def init_llm(self, provider: str, chat_model: str, api_key: str): + def init_llm(self, provider: str, chat_model: str, api_key: str, schema: dict = None): if provider in LLM_PROVIDERS: + if provider == "Ollama" and schema is not None: + return LLM_PROVIDERS[provider]["init"](chat_model, api_key, schema=schema) return LLM_PROVIDERS[provider]["init"](chat_model, api_key) else: raise ValueError(f"Unsupported LLM provider: {provider}") @@ -157,18 +159,16 @@ def run(self): retriever = SimpleRetriever(docs=docs) # 4. Chain Execution - llm = self.init_llm(self.llm_provider, self.llm_model, self.api_key) + schema = json.loads(RESPONSE_SCHEMA) + llm = self.init_llm(self.llm_provider, self.llm_model, self.api_key, schema=schema) prompt = ChatPromptTemplate.from_template(PROMPT) document_chain = create_stuff_documents_chain(llm, prompt) docs_for_context = retriever.invoke("") - # Using a generic input if specific query isn't provided llm_response = document_chain.invoke({"input": "", "context": docs_for_context}) answer = llm_response if isinstance(llm_response, str) else llm_response.get('answer', '') # 5. JSON Validation - schema = json.loads(RESPONSE_SCHEMA) - max_fix_attempts = 2 last_error = None From 86b564935b70ada7a3242401ea02b8a1444d4b73 Mon Sep 17 00:00:00 2001 From: zrgt Date: Tue, 23 Jun 2026 21:10:57 +0200 Subject: [PATCH 4/4] Fix imports, JSON editor bg, and qualifier defaults - Force dark background on all QsciLexerJSON style slots so whitespace and newlines no longer render as white in the JSON editor - Replace per-field Qualifier cardinality defaults with qualifier = () in handover_submodel.py --- .../documentation_generator.py | 4 +- .../handover_documentation_tool.py | 17 +- .../handover_doc_llm/handover_submodel.py | 1192 ++--------------- aas_editor/widgets/jsonEditor.py | 5 + 4 files changed, 94 insertions(+), 1124 deletions(-) diff --git a/aas_editor/tools/handover_doc_llm/documentation_generator.py b/aas_editor/tools/handover_doc_llm/documentation_generator.py index ec128c4d..60fa27de 100644 --- a/aas_editor/tools/handover_doc_llm/documentation_generator.py +++ b/aas_editor/tools/handover_doc_llm/documentation_generator.py @@ -105,7 +105,7 @@ } } -def json2document(json_str: str): +def json2document(json_str: str, filename: str = None): """ Convert a JSON string to documents and entities. @@ -134,7 +134,7 @@ def json2document(json_str: str): ) digitalFile = HandoverDocumentation.Documents.Documents_item.DocumentVersions.Documentversions_item.DigitalFiles.Digitalfiles_item( - value="SOME_PATH", #TODO: Fix me + value=filename, content_type=MIME_TYPE) statusSetDate = obj['document']['documentVersion'].get('statusSetDate', '').split('-') diff --git a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py index 80c004f4..cbbeac69 100644 --- a/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py +++ b/aas_editor/tools/handover_doc_llm/handover_documentation_tool.py @@ -36,6 +36,10 @@ from aas_editor.widgets.dropfilebox import DropFileQWebEngineView from aas_editor.widgets.jsonEditor import JSONEditor +from langchain_community.document_loaders import PyPDFLoader +from langchain_classic.chains.combine_documents import create_stuff_documents_chain +from langchain_core.prompts import ChatPromptTemplate + DOCUMENT_ROLE = 1000 @@ -102,13 +106,9 @@ def _fix_json_with_llm(self, llm, raw_answer: str, schema: dict, error_msg: str) def run(self): tmp_path = None - try: - from langchain_community.document_loaders import PyPDFLoader - from langchain_classic.chains.combine_documents import create_stuff_documents_chain - from langchain_core.prompts import ChatPromptTemplate - - # 1. Safer File Handling: Copy file instead of reading entire bytes into memory + # 1. Load PDF via pypdf directly (avoids langchain_community import chain + # which triggers a C-stack overflow on Python 3.14 via transformers/numpy) suffix = ".pdf" with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_pdf: tmp_path = tmp_pdf.name @@ -385,6 +385,7 @@ def chooseAndProcessPdf(self): def processPdf(self, file: str): self.current_file = file + self.current_filename = os.path.basename(self.current_file) self.html_renderer.setHtml("""
Processing PDF...
@@ -508,9 +509,9 @@ def show_answer_dialog(self, answer): while dialog.exec(): try: json_str = dialog.text.text() - document = json2document(json_str) + document = json2document(json_str, self.current_filename) - item = QListWidgetItem(os.path.basename(self.current_file)) + item = QListWidgetItem(self.current_filename) item.setData(DOCUMENT_ROLE, document) item.setToolTip(self.current_file) self.documentList.addItem(item) diff --git a/aas_editor/tools/handover_doc_llm/handover_submodel.py b/aas_editor/tools/handover_doc_llm/handover_submodel.py index c3ada04e..09cb565b 100644 --- a/aas_editor/tools/handover_doc_llm/handover_submodel.py +++ b/aas_editor/tools/handover_doc_llm/handover_submodel.py @@ -49,43 +49,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="https://domain.com/...", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -148,43 +114,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="XF90-884", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -247,43 +179,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="true", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -357,26 +255,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -488,26 +369,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -659,43 +523,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="03-02", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -752,43 +582,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Operation@en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -850,43 +646,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="VDI2770:2020", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -960,26 +722,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1083,26 +828,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1250,43 +978,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1347,26 +1041,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1526,43 +1203,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="V1.2", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1621,43 +1264,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Examplary title@en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1715,43 +1324,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Examplary subtitle@en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1812,43 +1387,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Abstract@en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -1906,43 +1447,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Examplary keywords@en", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2004,43 +1511,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="2020-02-06", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2100,43 +1573,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Released", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2189,43 +1628,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Example company", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2288,43 +1693,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="Example company Ltd.", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2369,43 +1740,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="AllowedIdShort", - value_type=str, - value=r"RefersTo[\d{2,3}]", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2469,26 +1806,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2634,43 +1954,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="AllowedIdShort", - value_type=str, - value=r"BasedOn[\d{2,3}]", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2734,26 +2020,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -2906,43 +2175,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="AllowedIdShort", - value_type=str, - value=r"TranslationOf[\d{2,3}]", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3006,26 +2241,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3179,60 +2397,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="docu_cecc_fullmanual_DE.PDF", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="AllowedIdShort", - value_type=str, - value=r"DigitalFile[\d{2,3}]", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3292,26 +2459,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3459,60 +2609,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="ExampleValue", - value_type=str, - value="docu_cecc_fullmanual_DE.jpg", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - Qualifier( - type_="AllowedIdShort", - value_type=str, - value=r"PreviewFile[\d{2,3}]", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3592,26 +2691,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3762,26 +2844,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3913,26 +2978,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -3979,26 +3027,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -4158,26 +3189,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -4261,26 +3275,9 @@ def __init__( ), embedded_data_specifications: Iterable[EmbeddedDataSpecification] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="One", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -4412,26 +3409,9 @@ def __init__( EmbeddedDataSpecification ] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="OneToMany", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -4477,26 +3457,9 @@ def __init__( supplemental_semantic_id: Iterable[Reference] = (), embedded_data_specifications: Iterable[EmbeddedDataSpecification] = None, ): + if qualifier is None: - qualifier = ( - Qualifier( - type_="SMT/Cardinality", - value_type=str, - value="ZeroToOne", - value_id=None, - kind=QualifierKind.CONCEPT_QUALIFIER, - semantic_id=ExternalReference( - key=( - Key( - type_=KeyTypes.GLOBAL_REFERENCE, - value="https://admin-shell.io/SubmodelTemplates/Cardinality/1/0", - ), - ), - referred_semantic_id=None, - ), - supplemental_semantic_id=(), - ), - ) + qualifier = () if embedded_data_specifications is None: embedded_data_specifications = [] @@ -4626,7 +3589,7 @@ def __init__( referred_semantic_id=None, ), qualifier: Iterable[Qualifier] = None, - kind: ModellingKind = ModellingKind.TEMPLATE, + kind: ModellingKind = ModellingKind.INSTANCE, extension: Iterable[Extension] = (), supplemental_semantic_id: Iterable[Reference] = ( ExternalReference( @@ -4641,6 +3604,7 @@ def __init__( ), embedded_data_specifications: Iterable[EmbeddedDataSpecification] = None, ): + if qualifier is None: qualifier = () diff --git a/aas_editor/widgets/jsonEditor.py b/aas_editor/widgets/jsonEditor.py index 04003928..7f73f603 100644 --- a/aas_editor/widgets/jsonEditor.py +++ b/aas_editor/widgets/jsonEditor.py @@ -62,6 +62,11 @@ def apply_dark_theme(self): lexer.setDefaultPaper(QColor("#282c34")) lexer.setDefaultColor(QColor("#abb2bf")) + # Force dark background on every style slot (whitespace/Default/unclosed etc.) + for _sid in range(20): + lexer.setPaper(QColor("#282c34"), _sid) + lexer.setColor(QColor("#abb2bf"), _sid) + # Define a helper to keep code clean def set_style(style_id, color_hex, bold=False): color = QColor(color_hex)