To solve the optimization problem described, we first need to convert the natural language description into a symbolic representation. This involves defining variables, an objective function, and constraints based on the given information.

Let's denote:
- $x_1$ as the number of Package 1 sold,
- $x_2$ as the number of Package 2 sold.

The objective is to maximize profit. Given that the profit per package 1 is $10 and the profit per package 2 is $12, the objective function can be represented as:
\[ \text{Maximize: } 10x_1 + 12x_2 \]

Constraints are based on the availability of souvenirs and snacks:
- Each Package 1 contains 5 souvenirs, and each Package 2 contains 4 souvenirs. The museum has 1000 souvenirs.
- Each Package 1 contains 10 snacks, and each Package 2 contains 15 snacks. The museum has 1400 snacks.

Thus, the constraints can be represented as:
\[ 5x_1 + 4x_2 \leq 1000 \] (souvenir constraint)
\[ 10x_1 + 15x_2 \leq 1400 \] (snack constraint)

Additionally, $x_1$ and $x_2$ must be non-negative since they represent quantities of packages:
\[ x_1 \geq 0 \]
\[ x_2 \geq 0 \]

And because we can't sell fractions of a package, ideally $x_1$ and $x_2$ should be integers, but for simplicity in finding the maximum profit without considering the integrality constraint (which could slightly reduce the optimal solution due to the discrete nature of the packages), we'll proceed with the current formulation.

The symbolic representation of the problem is thus:
```json
{
  'sym_variables': [('x1', 'Number of Package 1 sold'), ('x2', 'Number of Package 2 sold')],
  'objective_function': '10*x1 + 12*x2',
  'constraints': ['5*x1 + 4*x2 <= 1000', '10*x1 + 15*x2 <= 1400', 'x1 >= 0', 'x2 >= 0']
}
```

Now, let's translate this into Gurobi code in Python:

```python
from gurobipy import *

# Create a new model
m = Model("Museum_Gift_Shop")

# Create variables
x1 = m.addVar(vtype=GRB.CONTINUOUS, name="Package1")
x2 = m.addVar(vtype=GRB.CONTINUOUS, name="Package2")

# Set the objective function
m.setObjective(10*x1 + 12*x2, GRB.MAXIMIZE)

# Add constraints
m.addConstr(5*x1 + 4*x2 <= 1000, "SouvenirConstraint")
m.addConstr(10*x1 + 15*x2 <= 1400, "SnackConstraint")
m.addConstr(x1 >= 0, "NonNegativity_x1")
m.addConstr(x2 >= 0, "NonNegativity_x2")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print("Packages of Type 1 to sell:", x1.x)
    print("Packages of Type 2 to sell:", x2.x)
    print("Maximum Profit: $", m.objVal)
else:
    print("No optimal solution found")
```